From 72ab8a1a02a8c2f8de46d60e963140fa4d01d804 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Sat, 8 Nov 2025 01:01:14 +1100 Subject: [PATCH 01/69] Add dummy commit to create branch --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index c74441baef3..f91be3390e2 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +TODO:eddeee888 +
GraphQL Code Generator logo From df51ccc20e4124ca01b54c1201f2365e9d97df30 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Sat, 15 Nov 2025 22:48:52 +1100 Subject: [PATCH 02/69] Ensure CI runs --- .github/workflows/main.yml | 2 ++ README.md | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1fbe24c817d..066d1a06e03 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -4,9 +4,11 @@ on: push: branches: - master + - master-next # FIXME:eddeee888 Remove once done pull_request: branches: - master + - master-next # FIXME:eddeee888 Remove once released concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/README.md b/README.md index f91be3390e2..f5ab64e989a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -TODO:eddeee888 +FIXME:eddeee888
GraphQL Code Generator logo From 5c5ba93c8bb6ba9bcaaa0c47ba44533b90c58f33 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Sat, 15 Nov 2025 23:16:40 +1100 Subject: [PATCH 03/69] [typescript-operations] Generate `Exact` into target file (#10504) * Create standalone test * Add Exact and set up test * Remove Exact from typescript plugin * Update tests that switch out Exact * Update dev tests * Add changeset * Update test * Add InputMaybe Scalars tests * Fix schema in test * Fix up examples tests * Add result enum example --- .changeset/lovely-sloths-kiss.md | 7 + .../external-documents/app/types.generated.ts | 1 + dev-test/githunt/typed-document-nodes.ts | 2 +- dev-test/githunt/types.avoidOptionals.ts | 2 +- dev-test/githunt/types.d.ts | 2 +- dev-test/githunt/types.enumsAsTypes.ts | 2 +- .../githunt/types.flatten.preResolveTypes.ts | 2 +- dev-test/githunt/types.immutableTypes.ts | 2 +- ...ypes.preResolveTypes.onlyOperationTypes.ts | 2 +- dev-test/githunt/types.preResolveTypes.ts | 2 +- dev-test/githunt/types.ts | 2 +- .../gql-tag-operations-masking/gql/graphql.ts | 2 +- .../gql-tag-operations-urql/gql/graphql.ts | 2 +- dev-test/gql-tag-operations/gql/graphql.ts | 2 +- .../gql-tag-operations/graphql/graphql.ts | 2 +- dev-test/modules/types.ts | 1 - dev-test/star-wars/types.avoidOptionals.ts | 2 +- dev-test/star-wars/types.d.ts | 2 +- dev-test/star-wars/types.excludeQueryAlpha.ts | 2 +- dev-test/star-wars/types.excludeQueryBeta.ts | 2 +- .../star-wars/types.globallyAvailable.d.ts | 2 +- dev-test/star-wars/types.immutableTypes.ts | 2 +- ...ypes.preResolveTypes.onlyOperationTypes.ts | 2 +- dev-test/star-wars/types.preResolveTypes.ts | 2 +- dev-test/star-wars/types.skipSchema.ts | 2 +- dev-test/star-wars/types.ts | 2 +- dev-test/subpath-import/result.d.ts | 1 - dev-test/test-federation/generated/types.ts | 1 - dev-test/test-null-value/result.d.ts | 2 +- dev-test/test-schema/env.types.ts | 1 - dev-test/test-schema/resolvers-federation.ts | 1 - dev-test/test-schema/resolvers-root.ts | 1 - dev-test/test-schema/resolvers-stitching.ts | 1 - dev-test/test-schema/resolvers-types.ts | 1 - ...ypes.preResolveTypes.onlyOperationTypes.ts | 2 +- dev-test/test-schema/types.preResolveTypes.ts | 2 +- .../test-schema/typings.avoidOptionals.ts | 1 - dev-test/test-schema/typings.enum.ts | 1 - .../test-schema/typings.immutableTypes.ts | 1 - dev-test/test-schema/typings.ts | 1 - dev-test/test-schema/typings.wrapped.ts | 2 +- .../src/gql/graphql.ts | 2 +- .../persisted-documents/src/gql/graphql.ts | 2 +- .../apollo-client-defer/src/gql/graphql.ts | 2 +- .../react/apollo-client/src/gql/graphql.ts | 2 +- .../react/http-executor/src/gql/graphql.ts | 2 +- .../tanstack-react-query/src/gql/graphql.ts | 2 +- examples/react/urql/src/gql/graphql.ts | 2 +- examples/typescript-esm/src/gql/graphql.ts | 2 +- .../src/gql/graphql.ts | 2 +- .../typescript-resolvers/src/type-defs.d.ts | 1 - .../vite/vite-react-cts/src/gql/graphql.ts | 2 +- .../vite/vite-react-mts/src/gql/graphql.ts | 2 +- .../vite/vite-react-ts/src/gql/graphql.ts | 2 +- .../vue/apollo-composable/src/gql/graphql.ts | 2 +- examples/vue/urql/src/gql/graphql.ts | 2 +- examples/vue/villus/src/gql/graphql.ts | 2 +- examples/yoga-tests/src/gql/graphql.ts | 2 +- .../typescript/operations/src/index.ts | 6 +- .../__snapshots__/ts-documents.spec.ts.snap | 4 - .../operations/tests/ts-documents.spec.ts | 3 - .../tests/ts-documents.standalone.spec.ts | 123 ++++++++++++++++++ .../__snapshots__/ts-resolvers.spec.ts.snap | 2 - .../typescript/typescript/src/visitor.ts | 8 -- .../client/tests/client-preset.spec.ts | 46 +++---- 65 files changed, 202 insertions(+), 97 deletions(-) create mode 100644 .changeset/lovely-sloths-kiss.md create mode 100644 packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts diff --git a/.changeset/lovely-sloths-kiss.md b/.changeset/lovely-sloths-kiss.md new file mode 100644 index 00000000000..3005f29b02b --- /dev/null +++ b/.changeset/lovely-sloths-kiss.md @@ -0,0 +1,7 @@ +--- +'@graphql-codegen/typescript-operations': major +'@graphql-codegen/typescript': major +'@graphql-codegen/client-preset': major +--- + +BREAKING CHANGE: `typescript` plugin no longer generates `Exact` utility type. Instead, `typescript-operations` generates said utility type for every file it creates. This is because it is used _only_ for `Variables`, so we only need to generate it once for every generated operation file. diff --git a/dev-test/external-documents/app/types.generated.ts b/dev-test/external-documents/app/types.generated.ts index fc9a2a812b2..4fb00945d52 100644 --- a/dev-test/external-documents/app/types.generated.ts +++ b/dev-test/external-documents/app/types.generated.ts @@ -1,3 +1,4 @@ +type Exact = { [K in keyof T]: T[K] }; export type UserQueryVariables = Exact<{ id: Scalars['ID']['input']; }>; diff --git a/dev-test/githunt/typed-document-nodes.ts b/dev-test/githunt/typed-document-nodes.ts index c9c007657a3..c66776120af 100644 --- a/dev-test/githunt/typed-document-nodes.ts +++ b/dev-test/githunt/typed-document-nodes.ts @@ -2,7 +2,6 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -11,6 +10,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/githunt/types.avoidOptionals.ts b/dev-test/githunt/types.avoidOptionals.ts index a4e3d208f51..2721f037033 100644 --- a/dev-test/githunt/types.avoidOptionals.ts +++ b/dev-test/githunt/types.avoidOptionals.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -9,6 +8,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/githunt/types.d.ts b/dev-test/githunt/types.d.ts index ff7ed78627a..c274281c82a 100644 --- a/dev-test/githunt/types.d.ts +++ b/dev-test/githunt/types.d.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -9,6 +8,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/githunt/types.enumsAsTypes.ts b/dev-test/githunt/types.enumsAsTypes.ts index ff7ed78627a..c274281c82a 100644 --- a/dev-test/githunt/types.enumsAsTypes.ts +++ b/dev-test/githunt/types.enumsAsTypes.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -9,6 +8,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/githunt/types.flatten.preResolveTypes.ts b/dev-test/githunt/types.flatten.preResolveTypes.ts index 7e27c6e0c65..79cfc9907ab 100644 --- a/dev-test/githunt/types.flatten.preResolveTypes.ts +++ b/dev-test/githunt/types.flatten.preResolveTypes.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -9,6 +8,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/githunt/types.immutableTypes.ts b/dev-test/githunt/types.immutableTypes.ts index 37dedae5fc1..2699d81cbb8 100644 --- a/dev-test/githunt/types.immutableTypes.ts +++ b/dev-test/githunt/types.immutableTypes.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -9,6 +8,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts index fafa495e046..8694046a546 100644 --- a/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -9,6 +8,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/githunt/types.preResolveTypes.ts b/dev-test/githunt/types.preResolveTypes.ts index 057f9f78ccd..89246563df7 100644 --- a/dev-test/githunt/types.preResolveTypes.ts +++ b/dev-test/githunt/types.preResolveTypes.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -9,6 +8,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/githunt/types.ts b/dev-test/githunt/types.ts index 057f9f78ccd..89246563df7 100644 --- a/dev-test/githunt/types.ts +++ b/dev-test/githunt/types.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -9,6 +8,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/gql-tag-operations-masking/gql/graphql.ts b/dev-test/gql-tag-operations-masking/gql/graphql.ts index fe63c39880c..4e6a15678c2 100644 --- a/dev-test/gql-tag-operations-masking/gql/graphql.ts +++ b/dev-test/gql-tag-operations-masking/gql/graphql.ts @@ -3,7 +3,6 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ export type Maybe = T | null; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -12,6 +11,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/gql-tag-operations-urql/gql/graphql.ts b/dev-test/gql-tag-operations-urql/gql/graphql.ts index b1f670a60f3..a2080173c54 100644 --- a/dev-test/gql-tag-operations-urql/gql/graphql.ts +++ b/dev-test/gql-tag-operations-urql/gql/graphql.ts @@ -3,7 +3,6 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ export type Maybe = T | null; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -12,6 +11,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/gql-tag-operations/gql/graphql.ts b/dev-test/gql-tag-operations/gql/graphql.ts index b1f670a60f3..a2080173c54 100644 --- a/dev-test/gql-tag-operations/gql/graphql.ts +++ b/dev-test/gql-tag-operations/gql/graphql.ts @@ -3,7 +3,6 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ export type Maybe = T | null; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -12,6 +11,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/gql-tag-operations/graphql/graphql.ts b/dev-test/gql-tag-operations/graphql/graphql.ts index b1f670a60f3..a2080173c54 100644 --- a/dev-test/gql-tag-operations/graphql/graphql.ts +++ b/dev-test/gql-tag-operations/graphql/graphql.ts @@ -3,7 +3,6 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ export type Maybe = T | null; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -12,6 +11,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/modules/types.ts b/dev-test/modules/types.ts index 9686d9c2ff2..656b99b6de1 100644 --- a/dev-test/modules/types.ts +++ b/dev-test/modules/types.ts @@ -2,7 +2,6 @@ import { GraphQLResolveInfo } from 'graphql'; export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { diff --git a/dev-test/star-wars/types.avoidOptionals.ts b/dev-test/star-wars/types.avoidOptionals.ts index 9f902a4cf66..8c6d14b0131 100644 --- a/dev-test/star-wars/types.avoidOptionals.ts +++ b/dev-test/star-wars/types.avoidOptionals.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -9,6 +8,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/star-wars/types.d.ts b/dev-test/star-wars/types.d.ts index 3cf2a972200..32aaf9b03e6 100644 --- a/dev-test/star-wars/types.d.ts +++ b/dev-test/star-wars/types.d.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -9,6 +8,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/star-wars/types.excludeQueryAlpha.ts b/dev-test/star-wars/types.excludeQueryAlpha.ts index 58688ef48c7..738c9d0939e 100644 --- a/dev-test/star-wars/types.excludeQueryAlpha.ts +++ b/dev-test/star-wars/types.excludeQueryAlpha.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -9,6 +8,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/star-wars/types.excludeQueryBeta.ts b/dev-test/star-wars/types.excludeQueryBeta.ts index 43677ef773d..3d1158736c6 100644 --- a/dev-test/star-wars/types.excludeQueryBeta.ts +++ b/dev-test/star-wars/types.excludeQueryBeta.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -9,6 +8,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/star-wars/types.globallyAvailable.d.ts b/dev-test/star-wars/types.globallyAvailable.d.ts index 4bc089978b1..3fdb377c8da 100644 --- a/dev-test/star-wars/types.globallyAvailable.d.ts +++ b/dev-test/star-wars/types.globallyAvailable.d.ts @@ -1,12 +1,12 @@ type Maybe = T | null; type InputMaybe = Maybe; -type Exact = { [K in keyof T]: T[K] }; type MakeOptional = Omit & { [SubKey in K]?: Maybe }; type MakeMaybe = Omit & { [SubKey in K]: Maybe }; type MakeEmpty = { [_ in K]?: never }; type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/star-wars/types.immutableTypes.ts b/dev-test/star-wars/types.immutableTypes.ts index eb4f1283e16..f09f0c3ffe3 100644 --- a/dev-test/star-wars/types.immutableTypes.ts +++ b/dev-test/star-wars/types.immutableTypes.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -9,6 +8,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts index 8a7dfa7c6ae..526d78cd631 100644 --- a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -9,6 +8,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/star-wars/types.preResolveTypes.ts b/dev-test/star-wars/types.preResolveTypes.ts index 48c07f03464..0875acc793e 100644 --- a/dev-test/star-wars/types.preResolveTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -9,6 +8,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/star-wars/types.skipSchema.ts b/dev-test/star-wars/types.skipSchema.ts index 48c07f03464..0875acc793e 100644 --- a/dev-test/star-wars/types.skipSchema.ts +++ b/dev-test/star-wars/types.skipSchema.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -9,6 +8,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/star-wars/types.ts b/dev-test/star-wars/types.ts index 48c07f03464..0875acc793e 100644 --- a/dev-test/star-wars/types.ts +++ b/dev-test/star-wars/types.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -9,6 +8,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/subpath-import/result.d.ts b/dev-test/subpath-import/result.d.ts index eadc3a20514..0594f80c2ae 100644 --- a/dev-test/subpath-import/result.d.ts +++ b/dev-test/subpath-import/result.d.ts @@ -5,7 +5,6 @@ import { GraphQLResolveInfo } from 'graphql'; export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { diff --git a/dev-test/test-federation/generated/types.ts b/dev-test/test-federation/generated/types.ts index e9f0817821f..65c97cd274a 100644 --- a/dev-test/test-federation/generated/types.ts +++ b/dev-test/test-federation/generated/types.ts @@ -2,7 +2,6 @@ import { GraphQLResolveInfo, GraphQLScalarType, GraphQLScalarTypeConfig } from ' export type Maybe = T | null | undefined; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { diff --git a/dev-test/test-null-value/result.d.ts b/dev-test/test-null-value/result.d.ts index 8b97092ed9b..4b37cd5a870 100644 --- a/dev-test/test-null-value/result.d.ts +++ b/dev-test/test-null-value/result.d.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -9,6 +8,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/test-schema/env.types.ts b/dev-test/test-schema/env.types.ts index 16b18213fcd..4b28b59578d 100644 --- a/dev-test/test-schema/env.types.ts +++ b/dev-test/test-schema/env.types.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { diff --git a/dev-test/test-schema/resolvers-federation.ts b/dev-test/test-schema/resolvers-federation.ts index 7f0a0d6503f..75ebca192e8 100644 --- a/dev-test/test-schema/resolvers-federation.ts +++ b/dev-test/test-schema/resolvers-federation.ts @@ -2,7 +2,6 @@ import { GraphQLResolveInfo } from 'graphql'; export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { diff --git a/dev-test/test-schema/resolvers-root.ts b/dev-test/test-schema/resolvers-root.ts index 7cbcd79c1bb..3528e3a05a7 100644 --- a/dev-test/test-schema/resolvers-root.ts +++ b/dev-test/test-schema/resolvers-root.ts @@ -2,7 +2,6 @@ import { GraphQLResolveInfo } from 'graphql'; export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { diff --git a/dev-test/test-schema/resolvers-stitching.ts b/dev-test/test-schema/resolvers-stitching.ts index 645f4f0feca..65e6ea0b0c9 100644 --- a/dev-test/test-schema/resolvers-stitching.ts +++ b/dev-test/test-schema/resolvers-stitching.ts @@ -2,7 +2,6 @@ import { FieldNode, GraphQLResolveInfo, SelectionSetNode } from 'graphql'; export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { diff --git a/dev-test/test-schema/resolvers-types.ts b/dev-test/test-schema/resolvers-types.ts index bfad048bbe9..cb13e5c9bb8 100644 --- a/dev-test/test-schema/resolvers-types.ts +++ b/dev-test/test-schema/resolvers-types.ts @@ -2,7 +2,6 @@ import { GraphQLResolveInfo } from 'graphql'; export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { diff --git a/dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts index dff81900611..541df10d958 100644 --- a/dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -9,6 +8,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/test-schema/types.preResolveTypes.ts b/dev-test/test-schema/types.preResolveTypes.ts index 4d0ee75aa17..e114e0af309 100644 --- a/dev-test/test-schema/types.preResolveTypes.ts +++ b/dev-test/test-schema/types.preResolveTypes.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -9,6 +8,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/test-schema/typings.avoidOptionals.ts b/dev-test/test-schema/typings.avoidOptionals.ts index 855268c0ff4..d5215c529a5 100644 --- a/dev-test/test-schema/typings.avoidOptionals.ts +++ b/dev-test/test-schema/typings.avoidOptionals.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { diff --git a/dev-test/test-schema/typings.enum.ts b/dev-test/test-schema/typings.enum.ts index 7fe50ed4a55..3cfe81f2d53 100644 --- a/dev-test/test-schema/typings.enum.ts +++ b/dev-test/test-schema/typings.enum.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { diff --git a/dev-test/test-schema/typings.immutableTypes.ts b/dev-test/test-schema/typings.immutableTypes.ts index 24c3af3f281..36b580cf3a9 100644 --- a/dev-test/test-schema/typings.immutableTypes.ts +++ b/dev-test/test-schema/typings.immutableTypes.ts @@ -1,6 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { diff --git a/dev-test/test-schema/typings.ts b/dev-test/test-schema/typings.ts index 0833c36242b..5afeb856f16 100644 --- a/dev-test/test-schema/typings.ts +++ b/dev-test/test-schema/typings.ts @@ -2,7 +2,6 @@ import { GraphQLResolveInfo } from 'graphql'; export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { diff --git a/dev-test/test-schema/typings.wrapped.ts b/dev-test/test-schema/typings.wrapped.ts index bdacb9bc37b..c607ba519fb 100644 --- a/dev-test/test-schema/typings.wrapped.ts +++ b/dev-test/test-schema/typings.wrapped.ts @@ -1,7 +1,6 @@ declare namespace GraphQL { export type Maybe = T | null; export type InputMaybe = Maybe; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe; }; @@ -12,6 +11,7 @@ declare namespace GraphQL { export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/examples/persisted-documents-string-mode/src/gql/graphql.ts b/examples/persisted-documents-string-mode/src/gql/graphql.ts index 46fcc1d38b5..bb1d048aba9 100644 --- a/examples/persisted-documents-string-mode/src/gql/graphql.ts +++ b/examples/persisted-documents-string-mode/src/gql/graphql.ts @@ -3,7 +3,6 @@ import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -12,6 +11,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/examples/persisted-documents/src/gql/graphql.ts b/examples/persisted-documents/src/gql/graphql.ts index 542b1e50ce4..53cf201b793 100644 --- a/examples/persisted-documents/src/gql/graphql.ts +++ b/examples/persisted-documents/src/gql/graphql.ts @@ -3,7 +3,6 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ export type Maybe = T | null; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -12,6 +11,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/examples/react/apollo-client-defer/src/gql/graphql.ts b/examples/react/apollo-client-defer/src/gql/graphql.ts index d914da266cd..b8f8cc8cb01 100644 --- a/examples/react/apollo-client-defer/src/gql/graphql.ts +++ b/examples/react/apollo-client-defer/src/gql/graphql.ts @@ -3,7 +3,6 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ export type Maybe = T | null; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -12,6 +11,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/examples/react/apollo-client/src/gql/graphql.ts b/examples/react/apollo-client/src/gql/graphql.ts index 798c9d481c2..6375a217610 100644 --- a/examples/react/apollo-client/src/gql/graphql.ts +++ b/examples/react/apollo-client/src/gql/graphql.ts @@ -3,7 +3,6 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ export type Maybe = T | null; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -12,6 +11,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/examples/react/http-executor/src/gql/graphql.ts b/examples/react/http-executor/src/gql/graphql.ts index 798c9d481c2..6375a217610 100644 --- a/examples/react/http-executor/src/gql/graphql.ts +++ b/examples/react/http-executor/src/gql/graphql.ts @@ -3,7 +3,6 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ export type Maybe = T | null; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -12,6 +11,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/examples/react/tanstack-react-query/src/gql/graphql.ts b/examples/react/tanstack-react-query/src/gql/graphql.ts index 09de7d3df15..ff2a86e4044 100644 --- a/examples/react/tanstack-react-query/src/gql/graphql.ts +++ b/examples/react/tanstack-react-query/src/gql/graphql.ts @@ -3,7 +3,6 @@ import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -12,6 +11,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/examples/react/urql/src/gql/graphql.ts b/examples/react/urql/src/gql/graphql.ts index b47ef43d310..aecc6c1bb4b 100644 --- a/examples/react/urql/src/gql/graphql.ts +++ b/examples/react/urql/src/gql/graphql.ts @@ -3,7 +3,6 @@ import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -12,6 +11,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/examples/typescript-esm/src/gql/graphql.ts b/examples/typescript-esm/src/gql/graphql.ts index ba6773932bd..4d3d57b2bd7 100644 --- a/examples/typescript-esm/src/gql/graphql.ts +++ b/examples/typescript-esm/src/gql/graphql.ts @@ -3,7 +3,6 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ export type Maybe = T | null; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -12,6 +11,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/examples/typescript-graphql-request/src/gql/graphql.ts b/examples/typescript-graphql-request/src/gql/graphql.ts index ead1c8a5561..5aec2d4ecbd 100644 --- a/examples/typescript-graphql-request/src/gql/graphql.ts +++ b/examples/typescript-graphql-request/src/gql/graphql.ts @@ -3,7 +3,6 @@ import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -12,6 +11,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/examples/typescript-resolvers/src/type-defs.d.ts b/examples/typescript-resolvers/src/type-defs.d.ts index 485086d8856..d16780792a3 100644 --- a/examples/typescript-resolvers/src/type-defs.d.ts +++ b/examples/typescript-resolvers/src/type-defs.d.ts @@ -2,7 +2,6 @@ import { GraphQLResolveInfo } from 'graphql'; export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { diff --git a/examples/vite/vite-react-cts/src/gql/graphql.ts b/examples/vite/vite-react-cts/src/gql/graphql.ts index bcc0af509d1..eee94661055 100644 --- a/examples/vite/vite-react-cts/src/gql/graphql.ts +++ b/examples/vite/vite-react-cts/src/gql/graphql.ts @@ -3,7 +3,6 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ export type Maybe = T | null; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -12,6 +11,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/examples/vite/vite-react-mts/src/gql/graphql.ts b/examples/vite/vite-react-mts/src/gql/graphql.ts index bcc0af509d1..eee94661055 100644 --- a/examples/vite/vite-react-mts/src/gql/graphql.ts +++ b/examples/vite/vite-react-mts/src/gql/graphql.ts @@ -3,7 +3,6 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ export type Maybe = T | null; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -12,6 +11,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/examples/vite/vite-react-ts/src/gql/graphql.ts b/examples/vite/vite-react-ts/src/gql/graphql.ts index bcc0af509d1..eee94661055 100644 --- a/examples/vite/vite-react-ts/src/gql/graphql.ts +++ b/examples/vite/vite-react-ts/src/gql/graphql.ts @@ -3,7 +3,6 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ export type Maybe = T | null; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -12,6 +11,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/examples/vue/apollo-composable/src/gql/graphql.ts b/examples/vue/apollo-composable/src/gql/graphql.ts index ba3e733af05..609a15d0ac6 100644 --- a/examples/vue/apollo-composable/src/gql/graphql.ts +++ b/examples/vue/apollo-composable/src/gql/graphql.ts @@ -3,7 +3,6 @@ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document- export type Maybe = T | null; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -12,6 +11,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/examples/vue/urql/src/gql/graphql.ts b/examples/vue/urql/src/gql/graphql.ts index ba3e733af05..609a15d0ac6 100644 --- a/examples/vue/urql/src/gql/graphql.ts +++ b/examples/vue/urql/src/gql/graphql.ts @@ -3,7 +3,6 @@ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document- export type Maybe = T | null; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -12,6 +11,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/examples/vue/villus/src/gql/graphql.ts b/examples/vue/villus/src/gql/graphql.ts index ba3e733af05..609a15d0ac6 100644 --- a/examples/vue/villus/src/gql/graphql.ts +++ b/examples/vue/villus/src/gql/graphql.ts @@ -3,7 +3,6 @@ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document- export type Maybe = T | null; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -12,6 +11,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/examples/yoga-tests/src/gql/graphql.ts b/examples/yoga-tests/src/gql/graphql.ts index d7443c95ea4..5f78c6b24c2 100644 --- a/examples/yoga-tests/src/gql/graphql.ts +++ b/examples/yoga-tests/src/gql/graphql.ts @@ -3,7 +3,6 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/ export type Maybe = T | null; export type InputMaybe = T | null | undefined; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { @@ -12,6 +11,7 @@ export type MakeEmpty = export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/packages/plugins/typescript/operations/src/index.ts b/packages/plugins/typescript/operations/src/index.ts index d047ea252be..9d87df73309 100644 --- a/packages/plugins/typescript/operations/src/index.ts +++ b/packages/plugins/typescript/operations/src/index.ts @@ -102,7 +102,11 @@ export const plugin: PluginFunction< } return { - prepend: [...visitor.getImports(), ...visitor.getGlobalDeclarations(visitor.config.noExport)], + prepend: [ + ...visitor.getImports(), + ...visitor.getGlobalDeclarations(visitor.config.noExport), + 'type Exact = { [K in keyof T]: T[K] };', + ], content, }; }; diff --git a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap index 3bdd6ab1a15..99164f06d68 100644 --- a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap +++ b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap @@ -84,7 +84,6 @@ export type QQuery = { __typename?: 'Query', hotel: { __typename?: 'Hotel', id: exports[`TypeScript Operations Plugin > Issues > #3064 - fragments over interfaces causes issues with fields 2`] = ` "export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; @@ -438,7 +437,6 @@ export type UserQueryQuery = ( exports[`TypeScript Operations Plugin > Union & Interfaces > #4216 - handle fragments against unions and interfaces with flattenGeneratedTypes 1`] = ` "export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; @@ -571,7 +569,6 @@ export type UserResultFragment = exports[`TypeScript Operations Plugin > Union & Interfaces > Should handle union selection sets with both FragmentSpreads and InlineFragments with flattenGeneratedTypes 1`] = ` "export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; @@ -670,7 +667,6 @@ export type UserQueryQuery = ( exports[`TypeScript Operations Plugin > Union & Interfaces > Should handle union selection sets with both FragmentSpreads and InlineFragments with flattenGeneratedTypes and directives 1`] = ` "export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts index 44358de8683..93909b6dd53 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts @@ -4481,7 +4481,6 @@ export type Q2Query = { search: Array< expect(output).toBeSimilarStringTo(` export type Maybe = T | null; export type InputMaybe = Maybe; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; @@ -4591,7 +4590,6 @@ export type Q2Query = { search: Array< expect(output).toBeSimilarStringTo(` export type Maybe = T | null; export type InputMaybe = Maybe; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; @@ -4679,7 +4677,6 @@ export type Q2Query = { search: Array< expect(output).toBeSimilarStringTo(` export type Maybe = T | null; export type InputMaybe = Maybe; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts new file mode 100644 index 00000000000..e6385fc03ba --- /dev/null +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -0,0 +1,123 @@ +import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; +// import { validateTs } from '@graphql-codegen/testing'; +import { buildSchema, parse } from 'graphql'; +import { plugin } from '../src/index.js'; + +describe('TypeScript Operations Plugin - Standalone', () => { + it('generates using default config', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + users(input: UsersInput!): UsersResponse! + } + + type ResponseError { + error: ResponseErrorType! + } + + enum ResponseErrorType { + NOT_FOUND + INPUT_VALIDATION_ERROR + FORBIDDEN_ERROR + UNEXPECTED_ERROR + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + input UsersInput { + from: DateTime + to: DateTime + } + + type UsersResponseOk { + result: [User!]! + } + union UsersResponse = UsersResponseOk | ResponseError + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User($id: ID!) { + user(id: $id) { + id + name + role + createdAt + } + } + + query Users($input: UsersInput!) { + users(input: $input) { + ... on UsersResponseOk { + result { + id + } + } + ... on ResponseError { + error + } + } + } + + query UsersWithScalarInput($from: DateTime!, $to: DateTime) { + users(input: { from: $from, to: $to }) { + ... on UsersResponseOk { + result { + __typename + } + } + ... on ResponseError { + __typename + } + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], {})]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type UserQueryVariables = Exact<{ + id: Scalars['ID']['input']; + }>; + + + export type UserQuery = { __typename?: 'Query', user?: { __typename?: 'User', id: string, name: string, role: UserRole, createdAt: any } | null }; + + export type UsersQueryVariables = Exact<{ + input: UsersInput; + }>; + + + export type UsersQuery = { __typename?: 'Query', users: + | { __typename?: 'UsersResponseOk', result: Array<{ __typename?: 'User', id: string }> } + | { __typename?: 'ResponseError', error: ResponseErrorType } + }; + + export type UsersWithScalarInputQueryVariables = Exact<{ + from: Scalars['DateTime']['input']; + to?: InputMaybe; + }>; + + + export type UsersWithScalarInputQuery = { __typename?: 'Query', users: + | { __typename?: 'UsersResponseOk', result: Array<{ __typename: 'User' }> } + | { __typename: 'ResponseError' } + }; + " + `); + + // FIXME: enable this to ensure type correctness + // validateTs(content, undefined, undefined, undefined, undefined, true); + }); +}); diff --git a/packages/plugins/typescript/resolvers/tests/__snapshots__/ts-resolvers.spec.ts.snap b/packages/plugins/typescript/resolvers/tests/__snapshots__/ts-resolvers.spec.ts.snap index 3838c3a15da..b63bc6c726b 100644 --- a/packages/plugins/typescript/resolvers/tests/__snapshots__/ts-resolvers.spec.ts.snap +++ b/packages/plugins/typescript/resolvers/tests/__snapshots__/ts-resolvers.spec.ts.snap @@ -3,7 +3,6 @@ exports[`TypeScript Resolvers Plugin > Config > allowParentTypeOverride - should allow to have less strict resolvers by overrding parent type 1`] = ` "export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; @@ -623,7 +622,6 @@ export type DirectiveResolvers = ResolversObject<{ exports[`TypeScript Resolvers Plugin > Config > optionalInfoArgument - should allow to have optional info argument 1`] = ` "export type Maybe = T | null; export type InputMaybe = Maybe; -export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; diff --git a/packages/plugins/typescript/typescript/src/visitor.ts b/packages/plugins/typescript/typescript/src/visitor.ts index 33f8cf8d8e4..a3bdcd8547f 100644 --- a/packages/plugins/typescript/typescript/src/visitor.ts +++ b/packages/plugins/typescript/typescript/src/visitor.ts @@ -46,7 +46,6 @@ export interface TypeScriptPluginParsedConfig extends ParsedTypesConfig { useImplementingTypes: boolean; } -export const EXACT_SIGNATURE = `type Exact = { [K in keyof T]: T[K] };`; export const MAKE_OPTIONAL_SIGNATURE = `type MakeOptional = Omit & { [SubKey in K]?: Maybe };`; export const MAKE_MAYBE_SIGNATURE = `type MakeMaybe = Omit & { [SubKey in K]: Maybe };`; export const MAKE_EMPTY_SIGNATURE = `type MakeEmpty = { [_ in K]?: never };`; @@ -164,7 +163,6 @@ export class TsVisitor< const definitions: string[] = [ this.getMaybeValue(), this.getInputMaybeValue(), - this.getExactDefinition(), this.getMakeOptionalDefinition(), this.getMakeMaybeDefinition(), this.getMakeEmptyDefinition(), @@ -181,12 +179,6 @@ export class TsVisitor< return definitions; } - public getExactDefinition(): string { - if (this.config.onlyEnums) return ''; - - return `${this.getExportPrefix()}${EXACT_SIGNATURE}`; - } - public getMakeOptionalDefinition(): string { return `${this.getExportPrefix()}${MAKE_OPTIONAL_SIGNATURE}`; } diff --git a/packages/presets/client/tests/client-preset.spec.ts b/packages/presets/client/tests/client-preset.spec.ts index ff77f35dee9..856848faa9a 100644 --- a/packages/presets/client/tests/client-preset.spec.ts +++ b/packages/presets/client/tests/client-preset.spec.ts @@ -365,11 +365,11 @@ export * from "./gql";`); import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -501,11 +501,11 @@ export * from "./gql";`); import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -590,11 +590,11 @@ export * from "./gql";`); import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -707,11 +707,11 @@ export * from "./gql";`); import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -1564,11 +1564,11 @@ export * from "./gql.cjs";`); import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -1644,11 +1644,11 @@ export * from "./gql.cjs";`); import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -1727,11 +1727,11 @@ export * from "./gql.cjs";`); import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -1810,11 +1810,11 @@ export * from "./gql.cjs";`); import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -1893,11 +1893,11 @@ export * from "./gql.cjs";`); import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -1974,11 +1974,11 @@ export * from "./gql.cjs";`); import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -2061,11 +2061,11 @@ export * from "./gql.cjs";`); import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -2149,11 +2149,11 @@ export * from "./gql.cjs";`); import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -2237,11 +2237,11 @@ export * from "./gql.cjs";`); import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -2329,11 +2329,11 @@ export * from "./gql.cjs";`); import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -2408,11 +2408,11 @@ export * from "./gql.cjs";`); import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -2499,11 +2499,11 @@ export * from "./gql.cjs";`); import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -2590,11 +2590,11 @@ export * from "./gql.cjs";`); import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -2754,11 +2754,11 @@ export * from "./gql.cjs";`); import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -2916,11 +2916,11 @@ export * from "./gql.cjs";`); import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -3213,11 +3213,11 @@ export * from "./gql.cjs";`); import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -3322,11 +3322,11 @@ export * from "./gql.cjs";`); import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -3389,11 +3389,11 @@ export * from "./gql.cjs";`); import { MyColor as Color } from './fixtures/with-enum-values'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } @@ -3446,11 +3446,11 @@ export * from "./gql.cjs";`); import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = T | null | undefined; - export type Exact = { [K in keyof T]: T[K] }; export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; export type MakeEmpty = { [_ in K]?: never }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string; } From fd7374e36d16f6392acfaa09530b62e5669c9866 Mon Sep 17 00:00:00 2001 From: Igor Kusakov Date: Mon, 24 Nov 2025 09:18:17 -0500 Subject: [PATCH 04/69] [typescript-operations] Remove inputmaybe and scalars (#10509) * [typescript-operations] Remove generation of InputMaybe and Scalars for variables * Adding support for `config.scalars`, fixing intergation tests --------- Co-authored-by: Igor Kusakov --- .changeset/khaki-turtles-juggle.md | 6 ++ dev-test/githunt/typed-document-nodes.ts | 20 +++---- dev-test/githunt/types.avoidOptionals.ts | 20 +++---- dev-test/githunt/types.d.ts | 20 +++---- dev-test/githunt/types.enumsAsTypes.ts | 20 +++---- .../githunt/types.flatten.preResolveTypes.ts | 20 +++---- dev-test/githunt/types.immutableTypes.ts | 20 +++---- ...ypes.preResolveTypes.onlyOperationTypes.ts | 20 +++---- dev-test/githunt/types.preResolveTypes.ts | 20 +++---- dev-test/githunt/types.ts | 20 +++---- dev-test/star-wars/types.avoidOptionals.ts | 24 ++++---- dev-test/star-wars/types.excludeQueryAlpha.ts | 22 +++---- dev-test/star-wars/types.excludeQueryBeta.ts | 22 +++---- .../star-wars/types.globallyAvailable.d.ts | 24 ++++---- dev-test/star-wars/types.immutableTypes.ts | 24 ++++---- ...ypes.preResolveTypes.onlyOperationTypes.ts | 24 ++++---- dev-test/star-wars/types.preResolveTypes.ts | 24 ++++---- dev-test/star-wars/types.skipSchema.ts | 24 ++++---- dev-test/star-wars/types.ts | 24 ++++---- .../react/apollo-client/src/gql/graphql.ts | 2 +- .../react/http-executor/src/gql/graphql.ts | 2 +- .../tanstack-react-query/src/gql/graphql.ts | 2 +- examples/react/urql/src/gql/graphql.ts | 2 +- examples/typescript-esm/src/gql/graphql.ts | 2 +- .../src/gql/graphql.ts | 2 +- .../vite/vite-react-cts/src/gql/graphql.ts | 2 +- .../vite/vite-react-mts/src/gql/graphql.ts | 2 +- .../vite/vite-react-ts/src/gql/graphql.ts | 2 +- .../vue/apollo-composable/src/gql/graphql.ts | 2 +- examples/vue/urql/src/gql/graphql.ts | 2 +- examples/vue/villus/src/gql/graphql.ts | 2 +- examples/yoga-tests/src/gql/graphql.ts | 2 +- .../src/ts-operation-variables-to-object.ts | 26 +++++++++ .../__snapshots__/ts-documents.spec.ts.snap | 6 +- .../operations/tests/ts-documents.spec.ts | 57 +++++++++---------- .../tests/ts-documents.standalone.spec.ts | 42 +++++++++++++- .../src/typescript-variables-to-object.ts | 2 +- 37 files changed, 312 insertions(+), 245 deletions(-) create mode 100644 .changeset/khaki-turtles-juggle.md diff --git a/.changeset/khaki-turtles-juggle.md b/.changeset/khaki-turtles-juggle.md new file mode 100644 index 00000000000..bb0e0614a6a --- /dev/null +++ b/.changeset/khaki-turtles-juggle.md @@ -0,0 +1,6 @@ +--- +'@graphql-codegen/typescript-operations': major +'@graphql-codegen/typescript': minor +--- + +The `typescript-operations` plugin no longer generates InputMaybe and Scalars types; it now uses native Typescript types instead. diff --git a/dev-test/githunt/typed-document-nodes.ts b/dev-test/githunt/typed-document-nodes.ts index c66776120af..9ca29efb843 100644 --- a/dev-test/githunt/typed-document-nodes.ts +++ b/dev-test/githunt/typed-document-nodes.ts @@ -175,7 +175,7 @@ export enum VoteType { } export type OnCommentAddedSubscriptionVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; }>; export type OnCommentAddedSubscription = { @@ -190,9 +190,9 @@ export type OnCommentAddedSubscription = { }; export type CommentQueryVariables = Exact<{ - repoFullName: Scalars['String']['input']; - limit?: InputMaybe; - offset?: InputMaybe; + repoFullName: string; + limit?: number | null; + offset?: number | null; }>; export type CommentQuery = { @@ -258,8 +258,8 @@ export type FeedEntryFragment = { export type FeedQueryVariables = Exact<{ type: FeedType; - offset?: InputMaybe; - limit?: InputMaybe; + offset?: number | null; + limit?: number | null; }>; export type FeedQuery = { @@ -286,7 +286,7 @@ export type FeedQuery = { }; export type SubmitRepositoryMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; }>; export type SubmitRepositoryMutation = { @@ -307,8 +307,8 @@ export type RepoInfoFragment = { }; export type SubmitCommentMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; - commentContent: Scalars['String']['input']; + repoFullName: string; + commentContent: string; }>; export type SubmitCommentMutation = { @@ -329,7 +329,7 @@ export type VoteButtonsFragment = { }; export type VoteMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; type: VoteType; }>; diff --git a/dev-test/githunt/types.avoidOptionals.ts b/dev-test/githunt/types.avoidOptionals.ts index 2721f037033..0612dfd6890 100644 --- a/dev-test/githunt/types.avoidOptionals.ts +++ b/dev-test/githunt/types.avoidOptionals.ts @@ -173,7 +173,7 @@ export enum VoteType { } export type OnCommentAddedSubscriptionVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; }>; export type OnCommentAddedSubscription = { @@ -188,9 +188,9 @@ export type OnCommentAddedSubscription = { }; export type CommentQueryVariables = Exact<{ - repoFullName: Scalars['String']['input']; - limit: InputMaybe; - offset: InputMaybe; + repoFullName: string; + limit: number | null; + offset: number | null; }>; export type CommentQuery = { @@ -256,8 +256,8 @@ export type FeedEntryFragment = { export type FeedQueryVariables = Exact<{ type: FeedType; - offset: InputMaybe; - limit: InputMaybe; + offset: number | null; + limit: number | null; }>; export type FeedQuery = { @@ -284,7 +284,7 @@ export type FeedQuery = { }; export type SubmitRepositoryMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; }>; export type SubmitRepositoryMutation = { @@ -305,8 +305,8 @@ export type RepoInfoFragment = { }; export type SubmitCommentMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; - commentContent: Scalars['String']['input']; + repoFullName: string; + commentContent: string; }>; export type SubmitCommentMutation = { @@ -327,7 +327,7 @@ export type VoteButtonsFragment = { }; export type VoteMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; type: VoteType; }>; diff --git a/dev-test/githunt/types.d.ts b/dev-test/githunt/types.d.ts index c274281c82a..3e669417bac 100644 --- a/dev-test/githunt/types.d.ts +++ b/dev-test/githunt/types.d.ts @@ -168,7 +168,7 @@ export type Vote = { export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; export type OnCommentAddedSubscriptionVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; }>; export type OnCommentAddedSubscription = { @@ -183,9 +183,9 @@ export type OnCommentAddedSubscription = { }; export type CommentQueryVariables = Exact<{ - repoFullName: Scalars['String']['input']; - limit?: InputMaybe; - offset?: InputMaybe; + repoFullName: string; + limit?: number | null; + offset?: number | null; }>; export type CommentQuery = { @@ -251,8 +251,8 @@ export type FeedEntryFragment = { export type FeedQueryVariables = Exact<{ type: FeedType; - offset?: InputMaybe; - limit?: InputMaybe; + offset?: number | null; + limit?: number | null; }>; export type FeedQuery = { @@ -279,7 +279,7 @@ export type FeedQuery = { }; export type SubmitRepositoryMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; }>; export type SubmitRepositoryMutation = { @@ -300,8 +300,8 @@ export type RepoInfoFragment = { }; export type SubmitCommentMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; - commentContent: Scalars['String']['input']; + repoFullName: string; + commentContent: string; }>; export type SubmitCommentMutation = { @@ -322,7 +322,7 @@ export type VoteButtonsFragment = { }; export type VoteMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; type: VoteType; }>; diff --git a/dev-test/githunt/types.enumsAsTypes.ts b/dev-test/githunt/types.enumsAsTypes.ts index c274281c82a..3e669417bac 100644 --- a/dev-test/githunt/types.enumsAsTypes.ts +++ b/dev-test/githunt/types.enumsAsTypes.ts @@ -168,7 +168,7 @@ export type Vote = { export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; export type OnCommentAddedSubscriptionVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; }>; export type OnCommentAddedSubscription = { @@ -183,9 +183,9 @@ export type OnCommentAddedSubscription = { }; export type CommentQueryVariables = Exact<{ - repoFullName: Scalars['String']['input']; - limit?: InputMaybe; - offset?: InputMaybe; + repoFullName: string; + limit?: number | null; + offset?: number | null; }>; export type CommentQuery = { @@ -251,8 +251,8 @@ export type FeedEntryFragment = { export type FeedQueryVariables = Exact<{ type: FeedType; - offset?: InputMaybe; - limit?: InputMaybe; + offset?: number | null; + limit?: number | null; }>; export type FeedQuery = { @@ -279,7 +279,7 @@ export type FeedQuery = { }; export type SubmitRepositoryMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; }>; export type SubmitRepositoryMutation = { @@ -300,8 +300,8 @@ export type RepoInfoFragment = { }; export type SubmitCommentMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; - commentContent: Scalars['String']['input']; + repoFullName: string; + commentContent: string; }>; export type SubmitCommentMutation = { @@ -322,7 +322,7 @@ export type VoteButtonsFragment = { }; export type VoteMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; type: VoteType; }>; diff --git a/dev-test/githunt/types.flatten.preResolveTypes.ts b/dev-test/githunt/types.flatten.preResolveTypes.ts index 79cfc9907ab..48e7f922615 100644 --- a/dev-test/githunt/types.flatten.preResolveTypes.ts +++ b/dev-test/githunt/types.flatten.preResolveTypes.ts @@ -173,7 +173,7 @@ export enum VoteType { } export type OnCommentAddedSubscriptionVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; }>; export type OnCommentAddedSubscription = { @@ -188,9 +188,9 @@ export type OnCommentAddedSubscription = { }; export type CommentQueryVariables = Exact<{ - repoFullName: Scalars['String']['input']; - limit?: InputMaybe; - offset?: InputMaybe; + repoFullName: string; + limit?: number | null; + offset?: number | null; }>; export type CommentQuery = { @@ -229,8 +229,8 @@ export type CurrentUserForProfileQuery = { export type FeedQueryVariables = Exact<{ type: FeedType; - offset?: InputMaybe; - limit?: InputMaybe; + offset?: number | null; + limit?: number | null; }>; export type FeedQuery = { @@ -257,7 +257,7 @@ export type FeedQuery = { }; export type SubmitRepositoryMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; }>; export type SubmitRepositoryMutation = { @@ -266,8 +266,8 @@ export type SubmitRepositoryMutation = { }; export type SubmitCommentMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; - commentContent: Scalars['String']['input']; + repoFullName: string; + commentContent: string; }>; export type SubmitCommentMutation = { @@ -282,7 +282,7 @@ export type SubmitCommentMutation = { }; export type VoteMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; type: VoteType; }>; diff --git a/dev-test/githunt/types.immutableTypes.ts b/dev-test/githunt/types.immutableTypes.ts index 2699d81cbb8..15205c69630 100644 --- a/dev-test/githunt/types.immutableTypes.ts +++ b/dev-test/githunt/types.immutableTypes.ts @@ -173,7 +173,7 @@ export enum VoteType { } export type OnCommentAddedSubscriptionVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; }>; export type OnCommentAddedSubscription = { @@ -192,9 +192,9 @@ export type OnCommentAddedSubscription = { }; export type CommentQueryVariables = Exact<{ - repoFullName: Scalars['String']['input']; - limit?: InputMaybe; - offset?: InputMaybe; + repoFullName: string; + limit?: number | null; + offset?: number | null; }>; export type CommentQuery = { @@ -284,8 +284,8 @@ export type FeedEntryFragment = { export type FeedQueryVariables = Exact<{ type: FeedType; - offset?: InputMaybe; - limit?: InputMaybe; + offset?: number | null; + limit?: number | null; }>; export type FeedQuery = { @@ -316,7 +316,7 @@ export type FeedQuery = { }; export type SubmitRepositoryMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; }>; export type SubmitRepositoryMutation = { @@ -341,8 +341,8 @@ export type RepoInfoFragment = { }; export type SubmitCommentMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; - commentContent: Scalars['String']['input']; + repoFullName: string; + commentContent: string; }>; export type SubmitCommentMutation = { @@ -367,7 +367,7 @@ export type VoteButtonsFragment = { }; export type VoteMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; type: VoteType; }>; diff --git a/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts index 8694046a546..f83e95365e0 100644 --- a/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts @@ -36,7 +36,7 @@ export enum VoteType { } export type OnCommentAddedSubscriptionVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; }>; export type OnCommentAddedSubscription = { @@ -51,9 +51,9 @@ export type OnCommentAddedSubscription = { }; export type CommentQueryVariables = Exact<{ - repoFullName: Scalars['String']['input']; - limit?: InputMaybe; - offset?: InputMaybe; + repoFullName: string; + limit?: number | null; + offset?: number | null; }>; export type CommentQuery = { @@ -119,8 +119,8 @@ export type FeedEntryFragment = { export type FeedQueryVariables = Exact<{ type: FeedType; - offset?: InputMaybe; - limit?: InputMaybe; + offset?: number | null; + limit?: number | null; }>; export type FeedQuery = { @@ -147,7 +147,7 @@ export type FeedQuery = { }; export type SubmitRepositoryMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; }>; export type SubmitRepositoryMutation = { @@ -168,8 +168,8 @@ export type RepoInfoFragment = { }; export type SubmitCommentMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; - commentContent: Scalars['String']['input']; + repoFullName: string; + commentContent: string; }>; export type SubmitCommentMutation = { @@ -190,7 +190,7 @@ export type VoteButtonsFragment = { }; export type VoteMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; type: VoteType; }>; diff --git a/dev-test/githunt/types.preResolveTypes.ts b/dev-test/githunt/types.preResolveTypes.ts index 89246563df7..7c7f591cd75 100644 --- a/dev-test/githunt/types.preResolveTypes.ts +++ b/dev-test/githunt/types.preResolveTypes.ts @@ -173,7 +173,7 @@ export enum VoteType { } export type OnCommentAddedSubscriptionVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; }>; export type OnCommentAddedSubscription = { @@ -188,9 +188,9 @@ export type OnCommentAddedSubscription = { }; export type CommentQueryVariables = Exact<{ - repoFullName: Scalars['String']['input']; - limit?: InputMaybe; - offset?: InputMaybe; + repoFullName: string; + limit?: number | null; + offset?: number | null; }>; export type CommentQuery = { @@ -256,8 +256,8 @@ export type FeedEntryFragment = { export type FeedQueryVariables = Exact<{ type: FeedType; - offset?: InputMaybe; - limit?: InputMaybe; + offset?: number | null; + limit?: number | null; }>; export type FeedQuery = { @@ -284,7 +284,7 @@ export type FeedQuery = { }; export type SubmitRepositoryMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; }>; export type SubmitRepositoryMutation = { @@ -305,8 +305,8 @@ export type RepoInfoFragment = { }; export type SubmitCommentMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; - commentContent: Scalars['String']['input']; + repoFullName: string; + commentContent: string; }>; export type SubmitCommentMutation = { @@ -327,7 +327,7 @@ export type VoteButtonsFragment = { }; export type VoteMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; type: VoteType; }>; diff --git a/dev-test/githunt/types.ts b/dev-test/githunt/types.ts index 89246563df7..7c7f591cd75 100644 --- a/dev-test/githunt/types.ts +++ b/dev-test/githunt/types.ts @@ -173,7 +173,7 @@ export enum VoteType { } export type OnCommentAddedSubscriptionVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; }>; export type OnCommentAddedSubscription = { @@ -188,9 +188,9 @@ export type OnCommentAddedSubscription = { }; export type CommentQueryVariables = Exact<{ - repoFullName: Scalars['String']['input']; - limit?: InputMaybe; - offset?: InputMaybe; + repoFullName: string; + limit?: number | null; + offset?: number | null; }>; export type CommentQuery = { @@ -256,8 +256,8 @@ export type FeedEntryFragment = { export type FeedQueryVariables = Exact<{ type: FeedType; - offset?: InputMaybe; - limit?: InputMaybe; + offset?: number | null; + limit?: number | null; }>; export type FeedQuery = { @@ -284,7 +284,7 @@ export type FeedQuery = { }; export type SubmitRepositoryMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; }>; export type SubmitRepositoryMutation = { @@ -305,8 +305,8 @@ export type RepoInfoFragment = { }; export type SubmitCommentMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; - commentContent: Scalars['String']['input']; + repoFullName: string; + commentContent: string; }>; export type SubmitCommentMutation = { @@ -327,7 +327,7 @@ export type VoteButtonsFragment = { }; export type VoteMutationVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; type: VoteType; }>; diff --git a/dev-test/star-wars/types.avoidOptionals.ts b/dev-test/star-wars/types.avoidOptionals.ts index 8c6d14b0131..8a218f79265 100644 --- a/dev-test/star-wars/types.avoidOptionals.ts +++ b/dev-test/star-wars/types.avoidOptionals.ts @@ -255,7 +255,7 @@ export type CreateReviewForEpisodeMutation = { }; export type ExcludeQueryAlphaQueryVariables = Exact<{ - episode: InputMaybe; + episode: Episode | null; }>; export type ExcludeQueryAlphaQuery = { @@ -264,7 +264,7 @@ export type ExcludeQueryAlphaQuery = { }; export type ExcludeQueryBetaQueryVariables = Exact<{ - episode: InputMaybe; + episode: Episode | null; }>; export type ExcludeQueryBetaQuery = { @@ -273,7 +273,7 @@ export type ExcludeQueryBetaQuery = { }; export type HeroAndFriendsNamesQueryVariables = Exact<{ - episode: InputMaybe; + episode: Episode | null; }>; export type HeroAndFriendsNamesQuery = { @@ -307,7 +307,7 @@ export type HeroAppearsInQuery = { }; export type HeroDetailsQueryVariables = Exact<{ - episode: InputMaybe; + episode: Episode | null; }>; export type HeroDetailsQuery = { @@ -329,7 +329,7 @@ type HeroDetails_Human_Fragment = { __typename?: 'Human'; height: number | null; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; export type HeroDetailsWithFragmentQueryVariables = Exact<{ - episode: InputMaybe; + episode: Episode | null; }>; export type HeroDetailsWithFragmentQuery = { @@ -341,7 +341,7 @@ export type HeroDetailsWithFragmentQuery = { }; export type HeroNameQueryVariables = Exact<{ - episode: InputMaybe; + episode: Episode | null; }>; export type HeroNameQuery = { @@ -350,8 +350,8 @@ export type HeroNameQuery = { }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ - episode: InputMaybe; - includeName: Scalars['Boolean']['input']; + episode: Episode | null; + includeName: boolean; }>; export type HeroNameConditionalInclusionQuery = { @@ -360,8 +360,8 @@ export type HeroNameConditionalInclusionQuery = { }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ - episode: InputMaybe; - skipName: Scalars['Boolean']['input']; + episode: Episode | null; + skipName: boolean; }>; export type HeroNameConditionalExclusionQuery = { @@ -370,7 +370,7 @@ export type HeroNameConditionalExclusionQuery = { }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ - episode: InputMaybe; + episode: Episode | null; }>; export type HeroParentTypeDependentFieldQuery = { @@ -398,7 +398,7 @@ export type HeroParentTypeDependentFieldQuery = { }; export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ - episode: InputMaybe; + episode: Episode | null; }>; export type HeroTypeDependentAliasedFieldQuery = { diff --git a/dev-test/star-wars/types.excludeQueryAlpha.ts b/dev-test/star-wars/types.excludeQueryAlpha.ts index 738c9d0939e..063e31c3a00 100644 --- a/dev-test/star-wars/types.excludeQueryAlpha.ts +++ b/dev-test/star-wars/types.excludeQueryAlpha.ts @@ -255,7 +255,7 @@ export type CreateReviewForEpisodeMutation = { }; export type ExcludeQueryBetaQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type ExcludeQueryBetaQuery = { @@ -264,7 +264,7 @@ export type ExcludeQueryBetaQuery = { }; export type HeroAndFriendsNamesQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroAndFriendsNamesQuery = { @@ -298,7 +298,7 @@ export type HeroAppearsInQuery = { }; export type HeroDetailsQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroDetailsQuery = { @@ -320,7 +320,7 @@ type HeroDetails_Human_Fragment = { __typename?: 'Human'; height?: number | null export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; export type HeroDetailsWithFragmentQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroDetailsWithFragmentQuery = { @@ -332,7 +332,7 @@ export type HeroDetailsWithFragmentQuery = { }; export type HeroNameQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroNameQuery = { @@ -341,8 +341,8 @@ export type HeroNameQuery = { }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ - episode?: InputMaybe; - includeName: Scalars['Boolean']['input']; + episode?: Episode | null; + includeName: boolean; }>; export type HeroNameConditionalInclusionQuery = { @@ -351,8 +351,8 @@ export type HeroNameConditionalInclusionQuery = { }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ - episode?: InputMaybe; - skipName: Scalars['Boolean']['input']; + episode?: Episode | null; + skipName: boolean; }>; export type HeroNameConditionalExclusionQuery = { @@ -361,7 +361,7 @@ export type HeroNameConditionalExclusionQuery = { }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroParentTypeDependentFieldQuery = { @@ -389,7 +389,7 @@ export type HeroParentTypeDependentFieldQuery = { }; export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroTypeDependentAliasedFieldQuery = { diff --git a/dev-test/star-wars/types.excludeQueryBeta.ts b/dev-test/star-wars/types.excludeQueryBeta.ts index 3d1158736c6..3ea8a6c5617 100644 --- a/dev-test/star-wars/types.excludeQueryBeta.ts +++ b/dev-test/star-wars/types.excludeQueryBeta.ts @@ -255,7 +255,7 @@ export type CreateReviewForEpisodeMutation = { }; export type ExcludeQueryAlphaQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type ExcludeQueryAlphaQuery = { @@ -264,7 +264,7 @@ export type ExcludeQueryAlphaQuery = { }; export type HeroAndFriendsNamesQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroAndFriendsNamesQuery = { @@ -298,7 +298,7 @@ export type HeroAppearsInQuery = { }; export type HeroDetailsQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroDetailsQuery = { @@ -320,7 +320,7 @@ type HeroDetails_Human_Fragment = { __typename?: 'Human'; height?: number | null export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; export type HeroDetailsWithFragmentQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroDetailsWithFragmentQuery = { @@ -332,7 +332,7 @@ export type HeroDetailsWithFragmentQuery = { }; export type HeroNameQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroNameQuery = { @@ -341,8 +341,8 @@ export type HeroNameQuery = { }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ - episode?: InputMaybe; - includeName: Scalars['Boolean']['input']; + episode?: Episode | null; + includeName: boolean; }>; export type HeroNameConditionalInclusionQuery = { @@ -351,8 +351,8 @@ export type HeroNameConditionalInclusionQuery = { }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ - episode?: InputMaybe; - skipName: Scalars['Boolean']['input']; + episode?: Episode | null; + skipName: boolean; }>; export type HeroNameConditionalExclusionQuery = { @@ -361,7 +361,7 @@ export type HeroNameConditionalExclusionQuery = { }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroParentTypeDependentFieldQuery = { @@ -389,7 +389,7 @@ export type HeroParentTypeDependentFieldQuery = { }; export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroTypeDependentAliasedFieldQuery = { diff --git a/dev-test/star-wars/types.globallyAvailable.d.ts b/dev-test/star-wars/types.globallyAvailable.d.ts index 3fdb377c8da..7cdcb977a14 100644 --- a/dev-test/star-wars/types.globallyAvailable.d.ts +++ b/dev-test/star-wars/types.globallyAvailable.d.ts @@ -251,7 +251,7 @@ type CreateReviewForEpisodeMutation = { }; type ExcludeQueryAlphaQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; type ExcludeQueryAlphaQuery = { @@ -260,7 +260,7 @@ type ExcludeQueryAlphaQuery = { }; type ExcludeQueryBetaQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; type ExcludeQueryBetaQuery = { @@ -269,7 +269,7 @@ type ExcludeQueryBetaQuery = { }; type HeroAndFriendsNamesQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; type HeroAndFriendsNamesQuery = { @@ -303,7 +303,7 @@ type HeroAppearsInQuery = { }; type HeroDetailsQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; type HeroDetailsQuery = { @@ -325,7 +325,7 @@ type HeroDetails_Human_Fragment = { __typename?: 'Human'; height?: number | null type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; type HeroDetailsWithFragmentQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; type HeroDetailsWithFragmentQuery = { @@ -337,7 +337,7 @@ type HeroDetailsWithFragmentQuery = { }; type HeroNameQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; type HeroNameQuery = { @@ -346,8 +346,8 @@ type HeroNameQuery = { }; type HeroNameConditionalInclusionQueryVariables = Exact<{ - episode?: InputMaybe; - includeName: Scalars['Boolean']['input']; + episode?: Episode | null; + includeName: boolean; }>; type HeroNameConditionalInclusionQuery = { @@ -356,8 +356,8 @@ type HeroNameConditionalInclusionQuery = { }; type HeroNameConditionalExclusionQueryVariables = Exact<{ - episode?: InputMaybe; - skipName: Scalars['Boolean']['input']; + episode?: Episode | null; + skipName: boolean; }>; type HeroNameConditionalExclusionQuery = { @@ -366,7 +366,7 @@ type HeroNameConditionalExclusionQuery = { }; type HeroParentTypeDependentFieldQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; type HeroParentTypeDependentFieldQuery = { @@ -394,7 +394,7 @@ type HeroParentTypeDependentFieldQuery = { }; type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; type HeroTypeDependentAliasedFieldQuery = { diff --git a/dev-test/star-wars/types.immutableTypes.ts b/dev-test/star-wars/types.immutableTypes.ts index f09f0c3ffe3..a5d194d5c0b 100644 --- a/dev-test/star-wars/types.immutableTypes.ts +++ b/dev-test/star-wars/types.immutableTypes.ts @@ -259,7 +259,7 @@ export type CreateReviewForEpisodeMutation = { }; export type ExcludeQueryAlphaQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type ExcludeQueryAlphaQuery = { @@ -271,7 +271,7 @@ export type ExcludeQueryAlphaQuery = { }; export type ExcludeQueryBetaQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type ExcludeQueryBetaQuery = { @@ -283,7 +283,7 @@ export type ExcludeQueryBetaQuery = { }; export type HeroAndFriendsNamesQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroAndFriendsNamesQuery = { @@ -329,7 +329,7 @@ export type HeroAppearsInQuery = { }; export type HeroDetailsQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroDetailsQuery = { @@ -359,7 +359,7 @@ type HeroDetails_Human_Fragment = { export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; export type HeroDetailsWithFragmentQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroDetailsWithFragmentQuery = { @@ -375,7 +375,7 @@ export type HeroDetailsWithFragmentQuery = { }; export type HeroNameQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroNameQuery = { @@ -387,8 +387,8 @@ export type HeroNameQuery = { }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ - episode?: InputMaybe; - includeName: Scalars['Boolean']['input']; + episode?: Episode | null; + includeName: boolean; }>; export type HeroNameConditionalInclusionQuery = { @@ -400,8 +400,8 @@ export type HeroNameConditionalInclusionQuery = { }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ - episode?: InputMaybe; - skipName: Scalars['Boolean']['input']; + episode?: Episode | null; + skipName: boolean; }>; export type HeroNameConditionalExclusionQuery = { @@ -413,7 +413,7 @@ export type HeroNameConditionalExclusionQuery = { }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroParentTypeDependentFieldQuery = { @@ -449,7 +449,7 @@ export type HeroParentTypeDependentFieldQuery = { }; export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroTypeDependentAliasedFieldQuery = { diff --git a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts index 526d78cd631..6f844783949 100644 --- a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts @@ -64,7 +64,7 @@ export type CreateReviewForEpisodeMutation = { }; export type ExcludeQueryAlphaQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type ExcludeQueryAlphaQuery = { @@ -73,7 +73,7 @@ export type ExcludeQueryAlphaQuery = { }; export type ExcludeQueryBetaQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type ExcludeQueryBetaQuery = { @@ -82,7 +82,7 @@ export type ExcludeQueryBetaQuery = { }; export type HeroAndFriendsNamesQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroAndFriendsNamesQuery = { @@ -116,7 +116,7 @@ export type HeroAppearsInQuery = { }; export type HeroDetailsQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroDetailsQuery = { @@ -138,7 +138,7 @@ type HeroDetails_Human_Fragment = { __typename?: 'Human'; height?: number | null export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; export type HeroDetailsWithFragmentQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroDetailsWithFragmentQuery = { @@ -150,7 +150,7 @@ export type HeroDetailsWithFragmentQuery = { }; export type HeroNameQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroNameQuery = { @@ -159,8 +159,8 @@ export type HeroNameQuery = { }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ - episode?: InputMaybe; - includeName: Scalars['Boolean']['input']; + episode?: Episode | null; + includeName: boolean; }>; export type HeroNameConditionalInclusionQuery = { @@ -169,8 +169,8 @@ export type HeroNameConditionalInclusionQuery = { }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ - episode?: InputMaybe; - skipName: Scalars['Boolean']['input']; + episode?: Episode | null; + skipName: boolean; }>; export type HeroNameConditionalExclusionQuery = { @@ -179,7 +179,7 @@ export type HeroNameConditionalExclusionQuery = { }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroParentTypeDependentFieldQuery = { @@ -207,7 +207,7 @@ export type HeroParentTypeDependentFieldQuery = { }; export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroTypeDependentAliasedFieldQuery = { diff --git a/dev-test/star-wars/types.preResolveTypes.ts b/dev-test/star-wars/types.preResolveTypes.ts index 0875acc793e..e3d32fb9e2e 100644 --- a/dev-test/star-wars/types.preResolveTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.ts @@ -255,7 +255,7 @@ export type CreateReviewForEpisodeMutation = { }; export type ExcludeQueryAlphaQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type ExcludeQueryAlphaQuery = { @@ -264,7 +264,7 @@ export type ExcludeQueryAlphaQuery = { }; export type ExcludeQueryBetaQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type ExcludeQueryBetaQuery = { @@ -273,7 +273,7 @@ export type ExcludeQueryBetaQuery = { }; export type HeroAndFriendsNamesQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroAndFriendsNamesQuery = { @@ -307,7 +307,7 @@ export type HeroAppearsInQuery = { }; export type HeroDetailsQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroDetailsQuery = { @@ -329,7 +329,7 @@ type HeroDetails_Human_Fragment = { __typename?: 'Human'; height?: number | null export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; export type HeroDetailsWithFragmentQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroDetailsWithFragmentQuery = { @@ -341,7 +341,7 @@ export type HeroDetailsWithFragmentQuery = { }; export type HeroNameQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroNameQuery = { @@ -350,8 +350,8 @@ export type HeroNameQuery = { }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ - episode?: InputMaybe; - includeName: Scalars['Boolean']['input']; + episode?: Episode | null; + includeName: boolean; }>; export type HeroNameConditionalInclusionQuery = { @@ -360,8 +360,8 @@ export type HeroNameConditionalInclusionQuery = { }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ - episode?: InputMaybe; - skipName: Scalars['Boolean']['input']; + episode?: Episode | null; + skipName: boolean; }>; export type HeroNameConditionalExclusionQuery = { @@ -370,7 +370,7 @@ export type HeroNameConditionalExclusionQuery = { }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroParentTypeDependentFieldQuery = { @@ -398,7 +398,7 @@ export type HeroParentTypeDependentFieldQuery = { }; export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroTypeDependentAliasedFieldQuery = { diff --git a/dev-test/star-wars/types.skipSchema.ts b/dev-test/star-wars/types.skipSchema.ts index 0875acc793e..e3d32fb9e2e 100644 --- a/dev-test/star-wars/types.skipSchema.ts +++ b/dev-test/star-wars/types.skipSchema.ts @@ -255,7 +255,7 @@ export type CreateReviewForEpisodeMutation = { }; export type ExcludeQueryAlphaQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type ExcludeQueryAlphaQuery = { @@ -264,7 +264,7 @@ export type ExcludeQueryAlphaQuery = { }; export type ExcludeQueryBetaQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type ExcludeQueryBetaQuery = { @@ -273,7 +273,7 @@ export type ExcludeQueryBetaQuery = { }; export type HeroAndFriendsNamesQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroAndFriendsNamesQuery = { @@ -307,7 +307,7 @@ export type HeroAppearsInQuery = { }; export type HeroDetailsQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroDetailsQuery = { @@ -329,7 +329,7 @@ type HeroDetails_Human_Fragment = { __typename?: 'Human'; height?: number | null export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; export type HeroDetailsWithFragmentQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroDetailsWithFragmentQuery = { @@ -341,7 +341,7 @@ export type HeroDetailsWithFragmentQuery = { }; export type HeroNameQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroNameQuery = { @@ -350,8 +350,8 @@ export type HeroNameQuery = { }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ - episode?: InputMaybe; - includeName: Scalars['Boolean']['input']; + episode?: Episode | null; + includeName: boolean; }>; export type HeroNameConditionalInclusionQuery = { @@ -360,8 +360,8 @@ export type HeroNameConditionalInclusionQuery = { }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ - episode?: InputMaybe; - skipName: Scalars['Boolean']['input']; + episode?: Episode | null; + skipName: boolean; }>; export type HeroNameConditionalExclusionQuery = { @@ -370,7 +370,7 @@ export type HeroNameConditionalExclusionQuery = { }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroParentTypeDependentFieldQuery = { @@ -398,7 +398,7 @@ export type HeroParentTypeDependentFieldQuery = { }; export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroTypeDependentAliasedFieldQuery = { diff --git a/dev-test/star-wars/types.ts b/dev-test/star-wars/types.ts index 0875acc793e..e3d32fb9e2e 100644 --- a/dev-test/star-wars/types.ts +++ b/dev-test/star-wars/types.ts @@ -255,7 +255,7 @@ export type CreateReviewForEpisodeMutation = { }; export type ExcludeQueryAlphaQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type ExcludeQueryAlphaQuery = { @@ -264,7 +264,7 @@ export type ExcludeQueryAlphaQuery = { }; export type ExcludeQueryBetaQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type ExcludeQueryBetaQuery = { @@ -273,7 +273,7 @@ export type ExcludeQueryBetaQuery = { }; export type HeroAndFriendsNamesQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroAndFriendsNamesQuery = { @@ -307,7 +307,7 @@ export type HeroAppearsInQuery = { }; export type HeroDetailsQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroDetailsQuery = { @@ -329,7 +329,7 @@ type HeroDetails_Human_Fragment = { __typename?: 'Human'; height?: number | null export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; export type HeroDetailsWithFragmentQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroDetailsWithFragmentQuery = { @@ -341,7 +341,7 @@ export type HeroDetailsWithFragmentQuery = { }; export type HeroNameQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroNameQuery = { @@ -350,8 +350,8 @@ export type HeroNameQuery = { }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ - episode?: InputMaybe; - includeName: Scalars['Boolean']['input']; + episode?: Episode | null; + includeName: boolean; }>; export type HeroNameConditionalInclusionQuery = { @@ -360,8 +360,8 @@ export type HeroNameConditionalInclusionQuery = { }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ - episode?: InputMaybe; - skipName: Scalars['Boolean']['input']; + episode?: Episode | null; + skipName: boolean; }>; export type HeroNameConditionalExclusionQuery = { @@ -370,7 +370,7 @@ export type HeroNameConditionalExclusionQuery = { }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroParentTypeDependentFieldQuery = { @@ -398,7 +398,7 @@ export type HeroParentTypeDependentFieldQuery = { }; export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ - episode?: InputMaybe; + episode?: Episode | null; }>; export type HeroTypeDependentAliasedFieldQuery = { diff --git a/examples/react/apollo-client/src/gql/graphql.ts b/examples/react/apollo-client/src/gql/graphql.ts index 6375a217610..e6603fce09d 100644 --- a/examples/react/apollo-client/src/gql/graphql.ts +++ b/examples/react/apollo-client/src/gql/graphql.ts @@ -1281,7 +1281,7 @@ export type VehiclesEdge = { }; export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ - first: Scalars['Int']['input']; + first: number; }>; export type AllFilmsWithVariablesQueryQuery = { diff --git a/examples/react/http-executor/src/gql/graphql.ts b/examples/react/http-executor/src/gql/graphql.ts index 6375a217610..e6603fce09d 100644 --- a/examples/react/http-executor/src/gql/graphql.ts +++ b/examples/react/http-executor/src/gql/graphql.ts @@ -1281,7 +1281,7 @@ export type VehiclesEdge = { }; export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ - first: Scalars['Int']['input']; + first: number; }>; export type AllFilmsWithVariablesQueryQuery = { diff --git a/examples/react/tanstack-react-query/src/gql/graphql.ts b/examples/react/tanstack-react-query/src/gql/graphql.ts index ff2a86e4044..afc9b7af363 100644 --- a/examples/react/tanstack-react-query/src/gql/graphql.ts +++ b/examples/react/tanstack-react-query/src/gql/graphql.ts @@ -1281,7 +1281,7 @@ export type VehiclesEdge = { }; export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ - first: Scalars['Int']['input']; + first: number; }>; export type AllFilmsWithVariablesQueryQuery = { diff --git a/examples/react/urql/src/gql/graphql.ts b/examples/react/urql/src/gql/graphql.ts index aecc6c1bb4b..baf11154cf0 100644 --- a/examples/react/urql/src/gql/graphql.ts +++ b/examples/react/urql/src/gql/graphql.ts @@ -1281,7 +1281,7 @@ export type VehiclesEdge = { }; export type AllFilmsWithVariablesQuery199QueryVariables = Exact<{ - first: Scalars['Int']['input']; + first: number; }>; export type AllFilmsWithVariablesQuery199Query = { diff --git a/examples/typescript-esm/src/gql/graphql.ts b/examples/typescript-esm/src/gql/graphql.ts index 4d3d57b2bd7..daf56fdeeb8 100644 --- a/examples/typescript-esm/src/gql/graphql.ts +++ b/examples/typescript-esm/src/gql/graphql.ts @@ -1298,7 +1298,7 @@ export type AllPeopleQueryQuery = { }; export type AllPeopleWithVariablesQueryQueryVariables = Exact<{ - first: Scalars['Int']['input']; + first: number; }>; export type AllPeopleWithVariablesQueryQuery = { diff --git a/examples/typescript-graphql-request/src/gql/graphql.ts b/examples/typescript-graphql-request/src/gql/graphql.ts index 5aec2d4ecbd..87f7239f348 100644 --- a/examples/typescript-graphql-request/src/gql/graphql.ts +++ b/examples/typescript-graphql-request/src/gql/graphql.ts @@ -1298,7 +1298,7 @@ export type AllPeopleQueryQuery = { }; export type AllPeopleWithVariablesQueryQueryVariables = Exact<{ - first: Scalars['Int']['input']; + first: number; }>; export type AllPeopleWithVariablesQueryQuery = { diff --git a/examples/vite/vite-react-cts/src/gql/graphql.ts b/examples/vite/vite-react-cts/src/gql/graphql.ts index eee94661055..9e980a0030e 100644 --- a/examples/vite/vite-react-cts/src/gql/graphql.ts +++ b/examples/vite/vite-react-cts/src/gql/graphql.ts @@ -1289,7 +1289,7 @@ export type FilmItemFragment = { } & { ' $fragmentName'?: 'FilmItemFragment' }; export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ - first: Scalars['Int']['input']; + first: number; }>; export type AllFilmsWithVariablesQueryQuery = { diff --git a/examples/vite/vite-react-mts/src/gql/graphql.ts b/examples/vite/vite-react-mts/src/gql/graphql.ts index eee94661055..9e980a0030e 100644 --- a/examples/vite/vite-react-mts/src/gql/graphql.ts +++ b/examples/vite/vite-react-mts/src/gql/graphql.ts @@ -1289,7 +1289,7 @@ export type FilmItemFragment = { } & { ' $fragmentName'?: 'FilmItemFragment' }; export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ - first: Scalars['Int']['input']; + first: number; }>; export type AllFilmsWithVariablesQueryQuery = { diff --git a/examples/vite/vite-react-ts/src/gql/graphql.ts b/examples/vite/vite-react-ts/src/gql/graphql.ts index eee94661055..9e980a0030e 100644 --- a/examples/vite/vite-react-ts/src/gql/graphql.ts +++ b/examples/vite/vite-react-ts/src/gql/graphql.ts @@ -1289,7 +1289,7 @@ export type FilmItemFragment = { } & { ' $fragmentName'?: 'FilmItemFragment' }; export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ - first: Scalars['Int']['input']; + first: number; }>; export type AllFilmsWithVariablesQueryQuery = { diff --git a/examples/vue/apollo-composable/src/gql/graphql.ts b/examples/vue/apollo-composable/src/gql/graphql.ts index 609a15d0ac6..9d071c8d1df 100644 --- a/examples/vue/apollo-composable/src/gql/graphql.ts +++ b/examples/vue/apollo-composable/src/gql/graphql.ts @@ -1281,7 +1281,7 @@ export type VehiclesEdge = { }; export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ - first: Scalars['Int']['input']; + first: number; }>; export type AllFilmsWithVariablesQueryQuery = { diff --git a/examples/vue/urql/src/gql/graphql.ts b/examples/vue/urql/src/gql/graphql.ts index 609a15d0ac6..9d071c8d1df 100644 --- a/examples/vue/urql/src/gql/graphql.ts +++ b/examples/vue/urql/src/gql/graphql.ts @@ -1281,7 +1281,7 @@ export type VehiclesEdge = { }; export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ - first: Scalars['Int']['input']; + first: number; }>; export type AllFilmsWithVariablesQueryQuery = { diff --git a/examples/vue/villus/src/gql/graphql.ts b/examples/vue/villus/src/gql/graphql.ts index 609a15d0ac6..9d071c8d1df 100644 --- a/examples/vue/villus/src/gql/graphql.ts +++ b/examples/vue/villus/src/gql/graphql.ts @@ -1281,7 +1281,7 @@ export type VehiclesEdge = { }; export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ - first: Scalars['Int']['input']; + first: number; }>; export type AllFilmsWithVariablesQueryQuery = { diff --git a/examples/yoga-tests/src/gql/graphql.ts b/examples/yoga-tests/src/gql/graphql.ts index 5f78c6b24c2..ed3cd2a2646 100644 --- a/examples/yoga-tests/src/gql/graphql.ts +++ b/examples/yoga-tests/src/gql/graphql.ts @@ -40,7 +40,7 @@ export type HelloQueryQueryVariables = Exact<{ [key: string]: never }>; export type HelloQueryQuery = { __typename?: 'Query'; hello: string }; export type EchoMutationMutationVariables = Exact<{ - message: Scalars['String']['input']; + message: string; }>; export type EchoMutationMutation = { __typename?: 'Mutation'; echo: string }; diff --git a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts index 4448bfc28e6..55941798944 100644 --- a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts +++ b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts @@ -1,5 +1,15 @@ import { TypeScriptOperationVariablesToObject as TSOperationVariablesToObject } from '@graphql-codegen/typescript'; +const SCALARS = { + ID: 'string | number', + String: 'string', + Int: 'number', + Float: 'number', + Boolean: 'boolean', +}; + +const MAYBE_SUFFIX = ' | null'; + export class TypeScriptOperationVariablesToObject extends TSOperationVariablesToObject { protected formatTypeString( fieldType: string, @@ -8,4 +18,20 @@ export class TypeScriptOperationVariablesToObject extends TSOperationVariablesTo ): string { return fieldType; } + + protected clearOptional(str: string): string { + if (str?.endsWith(MAYBE_SUFFIX)) { + return (str = str.substring(0, str.length - MAYBE_SUFFIX.length)); + } + + return str; + } + + protected wrapMaybe(type: string): string { + return type?.endsWith(MAYBE_SUFFIX) ? type : `${type}${MAYBE_SUFFIX}`; + } + + protected getScalar(name: string): string { + return this._scalars?.[name]?.input ?? SCALARS[name] ?? 'any'; + } } diff --git a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap index 99164f06d68..f364438cc65 100644 --- a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap +++ b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap @@ -5,15 +5,15 @@ exports[`TypeScript Operations Plugin > Config > should include fragment variabl export type TextNotificationFragmentFragmentVariables = Exact<{ - skip: Scalars['Boolean']['input']; + skip: boolean; }>; " `; exports[`TypeScript Operations Plugin > Issues > #2699 - Issues with multiple interfaces and unions 1`] = ` "export type GetEntityBrandDataQueryVariables = Exact<{ - gid: Scalars['ID']['input']; - brand: Scalars['ID']['input']; + gid: string; + brand: string; }>; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts index 93909b6dd53..9d981d0c877 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts @@ -13,7 +13,7 @@ describe('TypeScript Operations Plugin', () => { config: any = {}, pluginSchema = schema, usage = '', - suspenseErrors = [], + suspenseErrors: string[] = [], ) => { const m = mergeOutputs([ await tsPlugin(pluginSchema, [], config, { outputFile: '' }), @@ -379,7 +379,7 @@ describe('TypeScript Operations Plugin', () => { expect(content).toBeSimilarStringTo(` export type UserQueryVariables = Exact<{ - showProperty: Scalars['Boolean']['input']; + showProperty: boolean; }> | undefined; `); }); @@ -2811,7 +2811,7 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo( `export type MeQueryVariables = Exact<{ - repoFullName: Scalars['String']['input']; + repoFullName: string; }>;`, ); expect(content).toBeSimilarStringTo(` @@ -3244,18 +3244,17 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo( - `export type TestQueryQueryVariables = Exact<{ - username?: InputMaybe; - email?: InputMaybe; - password: Scalars['String']['input']; - input?: InputMaybe; + expect(content).toBeSimilarStringTo(` + export type TestQueryQueryVariables = Exact<{ + username?: string | null; + email?: string | null; + password: string; + input?: InputType | null; mandatoryInput: InputType; - testArray?: InputMaybe> | InputMaybe>; - requireString: Array> | InputMaybe; - innerRequired: Array | Scalars['String']['input']; - }>;`, - ); + testArray?: Array | string | null; + requireString: Array | string; + innerRequired: Array | string; + }>;`); await validate(content, config, schema); }); @@ -3277,7 +3276,7 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo( `export type TestQueryQueryVariables = Exact<{ - test?: InputMaybe; + test?: any | null; }>;`, ); await validate(content, config); @@ -3638,7 +3637,7 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo(` export type UsersQueryVariables = Exact<{ - reverse?: InputMaybe; + reverse?: boolean | null; }>; `); }); @@ -5920,9 +5919,9 @@ function test(q: GetEntityBrandDataQuery): void { expect(content).toBeSimilarStringTo(` export type UserQueryVariables = Exact<{ - testArray?: InputMaybe> | InputMaybe>; - requireString: Array> | InputMaybe; - innerRequired: Array | Scalars['String']['input']; + testArray?: Array | string | null; + requireString: Array | string; + innerRequired: Array | string; }>;`); await validate(content, config); }); @@ -5956,9 +5955,9 @@ function test(q: GetEntityBrandDataQuery): void { expect(content).toBeSimilarStringTo(` export type UserQueryVariables = Exact<{ - testArray?: InputMaybe>>; - requireString: Array>; - innerRequired: Array; + testArray?: Array | null; + requireString: Array; + innerRequired: Array; }>;`); await validate(content, config); }); @@ -6504,8 +6503,8 @@ function test(q: GetEntityBrandDataQuery): void { expect(content).toBeSimilarStringTo(` export type UserQueryQueryVariables = Exact<{ - skipFirstName: Scalars['Boolean']['input']; - skipAddress: Scalars['Boolean']['input']; + skipFirstName: boolean; + skipAddress: boolean; }>; export type UserQueryQuery = { @@ -6563,7 +6562,7 @@ function test(q: GetEntityBrandDataQuery): void { expect(content).toBeSimilarStringTo(` export type UserQueryVariables = Exact<{ - showAddress: Scalars['Boolean']['input']; + showAddress: boolean; }>; export type UserQuery = { __typename?: 'Query', user: { __typename?: 'User', name: string, address?: string, nicknames?: Array | null, parents?: Array } };`); @@ -6616,8 +6615,8 @@ function test(q: GetEntityBrandDataQuery): void { expect(content).toBeSimilarStringTo(` export type UserQueryVariables = Exact<{ - showAddress: Scalars['Boolean']['input']; - showName: Scalars['Boolean']['input']; + showAddress: boolean; + showName: boolean; }>; export type UserQuery = { __typename?: 'Query', user: { __typename?: 'User', id: string, name?: string, address?: { __typename?: 'Address', city: string }, friends?: Array<{ __typename?: 'User', id: string }> } };`); }); @@ -6664,8 +6663,8 @@ function test(q: GetEntityBrandDataQuery): void { expect(content).toBeSimilarStringTo(` export type UserQueryVariables = Exact<{ - showAddress: Scalars['Boolean']['input']; - showName: Scalars['Boolean']['input']; + showAddress: boolean; + showName: boolean; }>; export type UserQuery = ( diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts index e6385fc03ba..50057f007c6 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -88,7 +88,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; export type UserQueryVariables = Exact<{ - id: Scalars['ID']['input']; + id: string; }>; @@ -105,8 +105,8 @@ describe('TypeScript Operations Plugin - Standalone', () => { }; export type UsersWithScalarInputQueryVariables = Exact<{ - from: Scalars['DateTime']['input']; - to?: InputMaybe; + from: any; + to?: any | null; }>; @@ -120,4 +120,40 @@ describe('TypeScript Operations Plugin - Standalone', () => { // FIXME: enable this to ensure type correctness // validateTs(content, undefined, undefined, undefined, undefined, true); }); + + it('test overrdiding config.scalars', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + } + + type User { + id: ID! + name: String! + } + `); + const document = parse(/* GraphQL */ ` + query User($id: ID!) { + user(id: $id) { + id + name + } + } + `); + + const result = mergeOutputs([ + await plugin(schema, [{ document }], { scalars: { ID: 'string | number | boolean' } }), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type UserQueryVariables = Exact<{ + id: string | number | boolean; + }>; + + + export type UserQuery = { __typename?: 'Query', user?: { __typename?: 'User', id: string | number | boolean, name: string } | null }; + " + `); + }); }); diff --git a/packages/plugins/typescript/typescript/src/typescript-variables-to-object.ts b/packages/plugins/typescript/typescript/src/typescript-variables-to-object.ts index d5e1dbf3fe7..ad2740b17a2 100644 --- a/packages/plugins/typescript/typescript/src/typescript-variables-to-object.ts +++ b/packages/plugins/typescript/typescript/src/typescript-variables-to-object.ts @@ -36,7 +36,7 @@ export class TypeScriptOperationVariablesToObject extends OperationVariablesToOb ); } - private clearOptional(str: string): string { + protected clearOptional(str: string): string { const prefix = this._namespacedImportName ? `${this._namespacedImportName}.` : ''; const rgx = new RegExp(`^${this.wrapMaybe(`(.*?)`)}$`, 'i'); From 8553b622fefb63e3e0e579c36be044551727ac43 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 24 Nov 2025 14:18:39 +0000 Subject: [PATCH 05/69] chore(dependencies): updated changesets for modified dependencies --- .changeset/@graphql-codegen_cli-10496-dependencies.md | 6 ++++++ ...graphql-codegen_client-preset-10496-dependencies.md | 10 ++++++++++ ...ql-codegen_gql-tag-operations-10496-dependencies.md | 6 ++++++ ...odegen_graphql-modules-preset-10496-dependencies.md | 6 ++++++ ...l-codegen_typed-document-node-10496-dependencies.md | 6 ++++++ .../@graphql-codegen_typescript-10496-dependencies.md | 6 ++++++ ...gen_typescript-document-nodes-10496-dependencies.md | 6 ++++++ ...codegen_typescript-operations-10496-dependencies.md | 7 +++++++ ...-codegen_typescript-resolvers-10496-dependencies.md | 7 +++++++ ...codegen_visitor-plugin-common-10496-dependencies.md | 5 +++++ 10 files changed, 65 insertions(+) create mode 100644 .changeset/@graphql-codegen_cli-10496-dependencies.md create mode 100644 .changeset/@graphql-codegen_client-preset-10496-dependencies.md create mode 100644 .changeset/@graphql-codegen_gql-tag-operations-10496-dependencies.md create mode 100644 .changeset/@graphql-codegen_graphql-modules-preset-10496-dependencies.md create mode 100644 .changeset/@graphql-codegen_typed-document-node-10496-dependencies.md create mode 100644 .changeset/@graphql-codegen_typescript-10496-dependencies.md create mode 100644 .changeset/@graphql-codegen_typescript-document-nodes-10496-dependencies.md create mode 100644 .changeset/@graphql-codegen_typescript-operations-10496-dependencies.md create mode 100644 .changeset/@graphql-codegen_typescript-resolvers-10496-dependencies.md create mode 100644 .changeset/@graphql-codegen_visitor-plugin-common-10496-dependencies.md diff --git a/.changeset/@graphql-codegen_cli-10496-dependencies.md b/.changeset/@graphql-codegen_cli-10496-dependencies.md new file mode 100644 index 00000000000..1da26fe3256 --- /dev/null +++ b/.changeset/@graphql-codegen_cli-10496-dependencies.md @@ -0,0 +1,6 @@ +--- +"@graphql-codegen/cli": patch +--- +dependencies updates: + - Updated dependency [`@graphql-codegen/client-preset@^5.2.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/client-preset/v/5.2.0) (from `^5.1.2`, in `dependencies`) + - Updated dependency [`@graphql-codegen/plugin-helpers@^6.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers/v/6.1.0) (from `^6.0.0`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_client-preset-10496-dependencies.md b/.changeset/@graphql-codegen_client-preset-10496-dependencies.md new file mode 100644 index 00000000000..aa76a06c453 --- /dev/null +++ b/.changeset/@graphql-codegen_client-preset-10496-dependencies.md @@ -0,0 +1,10 @@ +--- +"@graphql-codegen/client-preset": patch +--- +dependencies updates: + - Updated dependency [`@graphql-codegen/typed-document-node@^6.1.3` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typed-document-node/v/6.1.3) (from `^6.1.2`, in `dependencies`) + - Updated dependency [`@graphql-codegen/typescript@^5.0.5` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.5) (from `^5.0.4`, in `dependencies`) + - Updated dependency [`@graphql-codegen/typescript-operations@^5.0.5` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript-operations/v/5.0.5) (from `^5.0.4`, in `dependencies`) + - Updated dependency [`@graphql-codegen/gql-tag-operations@5.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/gql-tag-operations/v/5.1.0) (from `5.0.5`, in `dependencies`) + - Updated dependency [`@graphql-codegen/plugin-helpers@^6.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers/v/6.1.0) (from `^6.0.0`, in `dependencies`) + - Updated dependency [`@graphql-codegen/visitor-plugin-common@^6.2.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/visitor-plugin-common/v/6.2.0) (from `^6.1.2`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_gql-tag-operations-10496-dependencies.md b/.changeset/@graphql-codegen_gql-tag-operations-10496-dependencies.md new file mode 100644 index 00000000000..8b556536d8a --- /dev/null +++ b/.changeset/@graphql-codegen_gql-tag-operations-10496-dependencies.md @@ -0,0 +1,6 @@ +--- +"@graphql-codegen/gql-tag-operations": patch +--- +dependencies updates: + - Updated dependency [`@graphql-codegen/plugin-helpers@^6.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers/v/6.1.0) (from `^6.0.0`, in `dependencies`) + - Updated dependency [`@graphql-codegen/visitor-plugin-common@6.2.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/visitor-plugin-common/v/6.2.0) (from `6.1.2`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_graphql-modules-preset-10496-dependencies.md b/.changeset/@graphql-codegen_graphql-modules-preset-10496-dependencies.md new file mode 100644 index 00000000000..5251ebebfdb --- /dev/null +++ b/.changeset/@graphql-codegen_graphql-modules-preset-10496-dependencies.md @@ -0,0 +1,6 @@ +--- +"@graphql-codegen/graphql-modules-preset": patch +--- +dependencies updates: + - Updated dependency [`@graphql-codegen/plugin-helpers@^6.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers/v/6.1.0) (from `^6.0.0`, in `dependencies`) + - Updated dependency [`@graphql-codegen/visitor-plugin-common@6.2.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/visitor-plugin-common/v/6.2.0) (from `6.1.2`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typed-document-node-10496-dependencies.md b/.changeset/@graphql-codegen_typed-document-node-10496-dependencies.md new file mode 100644 index 00000000000..ffc6eb27d68 --- /dev/null +++ b/.changeset/@graphql-codegen_typed-document-node-10496-dependencies.md @@ -0,0 +1,6 @@ +--- +"@graphql-codegen/typed-document-node": patch +--- +dependencies updates: + - Updated dependency [`@graphql-codegen/plugin-helpers@^6.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers/v/6.1.0) (from `^6.0.0`, in `dependencies`) + - Updated dependency [`@graphql-codegen/visitor-plugin-common@6.2.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/visitor-plugin-common/v/6.2.0) (from `6.1.2`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typescript-10496-dependencies.md b/.changeset/@graphql-codegen_typescript-10496-dependencies.md new file mode 100644 index 00000000000..7f1cbc7a52e --- /dev/null +++ b/.changeset/@graphql-codegen_typescript-10496-dependencies.md @@ -0,0 +1,6 @@ +--- +"@graphql-codegen/typescript": patch +--- +dependencies updates: + - Updated dependency [`@graphql-codegen/plugin-helpers@^6.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers/v/6.1.0) (from `^6.0.0`, in `dependencies`) + - Updated dependency [`@graphql-codegen/visitor-plugin-common@6.2.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/visitor-plugin-common/v/6.2.0) (from `6.1.2`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typescript-document-nodes-10496-dependencies.md b/.changeset/@graphql-codegen_typescript-document-nodes-10496-dependencies.md new file mode 100644 index 00000000000..e26048ceb9c --- /dev/null +++ b/.changeset/@graphql-codegen_typescript-document-nodes-10496-dependencies.md @@ -0,0 +1,6 @@ +--- +"@graphql-codegen/typescript-document-nodes": patch +--- +dependencies updates: + - Updated dependency [`@graphql-codegen/plugin-helpers@^6.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers/v/6.1.0) (from `^6.0.0`, in `dependencies`) + - Updated dependency [`@graphql-codegen/visitor-plugin-common@6.2.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/visitor-plugin-common/v/6.2.0) (from `6.1.2`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md b/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md new file mode 100644 index 00000000000..f987ce2292c --- /dev/null +++ b/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md @@ -0,0 +1,7 @@ +--- +"@graphql-codegen/typescript-operations": patch +--- +dependencies updates: + - Updated dependency [`@graphql-codegen/plugin-helpers@^6.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers/v/6.1.0) (from `^6.0.0`, in `dependencies`) + - Updated dependency [`@graphql-codegen/typescript@^5.0.5` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.5) (from `^5.0.4`, in `dependencies`) + - Updated dependency [`@graphql-codegen/visitor-plugin-common@6.2.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/visitor-plugin-common/v/6.2.0) (from `6.1.2`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typescript-resolvers-10496-dependencies.md b/.changeset/@graphql-codegen_typescript-resolvers-10496-dependencies.md new file mode 100644 index 00000000000..90c2beaf989 --- /dev/null +++ b/.changeset/@graphql-codegen_typescript-resolvers-10496-dependencies.md @@ -0,0 +1,7 @@ +--- +"@graphql-codegen/typescript-resolvers": patch +--- +dependencies updates: + - Updated dependency [`@graphql-codegen/plugin-helpers@^6.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers/v/6.1.0) (from `^6.0.0`, in `dependencies`) + - Updated dependency [`@graphql-codegen/typescript@^5.0.5` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.5) (from `^5.0.4`, in `dependencies`) + - Updated dependency [`@graphql-codegen/visitor-plugin-common@6.2.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/visitor-plugin-common/v/6.2.0) (from `6.1.2`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_visitor-plugin-common-10496-dependencies.md b/.changeset/@graphql-codegen_visitor-plugin-common-10496-dependencies.md new file mode 100644 index 00000000000..7e6a61d5d42 --- /dev/null +++ b/.changeset/@graphql-codegen_visitor-plugin-common-10496-dependencies.md @@ -0,0 +1,5 @@ +--- +"@graphql-codegen/visitor-plugin-common": patch +--- +dependencies updates: + - Updated dependency [`@graphql-codegen/plugin-helpers@^6.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers/v/6.1.0) (from `^6.0.0`, in `dependencies`) From f561b7854495ecdc5c7e92169fbee048a8c56842 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Tue, 25 Nov 2025 23:32:38 +1100 Subject: [PATCH 06/69] [typescript-operations] Extract convertSchemaEnumToDeclarationBlockString and getNodeComment to `visitor-plugin-common` (#10520) * Extract convertSchemaEnumToDeclarationBlockString and getNodeComment to visitor-plugin-common to re-use in next major version * Create major breaking changeset for @graphql-codegen/visitor-plugin-common * Fix naming * Replace buildEnumValuesBlock method in base-types-visitor with a utility version * Fix changeset * Fix import path * Fix getNodeComment import issue by moving to utils.ts --- .changeset/proud-cougars-hear.md | 5 + .changeset/silly-kiwis-sip.md | 5 + .../src/base-types-visitor.ts | 92 ++---- ...schema-enum-to-declaration-block-string.ts | 268 ++++++++++++++++++ .../other/visitor-plugin-common/src/index.ts | 1 + .../other/visitor-plugin-common/src/utils.ts | 27 ++ .../typescript/typescript/src/visitor.ts | 143 +++------- 7 files changed, 360 insertions(+), 181 deletions(-) create mode 100644 .changeset/proud-cougars-hear.md create mode 100644 .changeset/silly-kiwis-sip.md create mode 100644 packages/plugins/other/visitor-plugin-common/src/convert-schema-enum-to-declaration-block-string.ts diff --git a/.changeset/proud-cougars-hear.md b/.changeset/proud-cougars-hear.md new file mode 100644 index 00000000000..f02764b32ff --- /dev/null +++ b/.changeset/proud-cougars-hear.md @@ -0,0 +1,5 @@ +--- +'@graphql-codegen/visitor-plugin-common': major +--- + +BREAKING CHANGE: `@graphql-codegen/visitor-plugin-common`'s `base-types-visitor` no longer has `getNodeComment` or `buildEnumValuesBlock` method. diff --git a/.changeset/silly-kiwis-sip.md b/.changeset/silly-kiwis-sip.md new file mode 100644 index 00000000000..31295846e7e --- /dev/null +++ b/.changeset/silly-kiwis-sip.md @@ -0,0 +1,5 @@ +--- +'@graphql-codegen/typescript': patch +--- + +Extract utilities from base-type-visitor to be shared with other plugins later: convertSchemaEnumToDeclarationBlockString, getNodeComment diff --git a/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts index 58f7031796d..3a3cb290a01 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts @@ -2,9 +2,7 @@ import { DirectiveDefinitionNode, DirectiveNode, EnumTypeDefinitionNode, - EnumValueDefinitionNode, FieldDefinitionNode, - GraphQLEnumType, GraphQLSchema, InputObjectTypeDefinitionNode, InputValueDefinitionNode, @@ -19,6 +17,7 @@ import { UnionTypeDefinitionNode, } from 'graphql'; import { BaseVisitor, ParsedConfig, RawConfig } from './base-visitor.js'; +import { buildEnumValuesBlock } from './convert-schema-enum-to-declaration-block-string.js'; import { normalizeDeclarationKind } from './declaration-kinds.js'; import { parseEnumValues } from './enum-values.js'; import { transformDirectiveArgumentAndInputFieldMappings } from './mappers.js'; @@ -37,6 +36,7 @@ import { DeclarationBlock, DeclarationBlockConfig, getConfigValue, + getNodeComment, indent, isOneOfInputObjectType, transformComment, @@ -493,8 +493,6 @@ export interface RawTypesConfig extends RawConfig { directiveArgumentAndInputFieldMappingTypeSuffix?: string; } -const onlyUnderscoresPattern = /^_+$/; - export class BaseTypesVisitor< TRawConfig extends RawTypesConfig = RawTypesConfig, TPluginConfig extends ParsedTypesConfig = ParsedTypesConfig, @@ -723,7 +721,7 @@ export class BaseTypesVisitor< const typeString = node.type as any as string; const { type } = this._parsedConfig.declarationKind; - const comment = this.getNodeComment(node); + const comment = getNodeComment(node); return comment + indent(`${node.name.value}: ${typeString}${this.getPunctuation(type)}`); } @@ -932,7 +930,23 @@ export class BaseTypesVisitor< }), ) .withComment(node.description.value) - .withBlock(this.buildEnumValuesBlock(enumName, node.values)).string; + .withBlock( + buildEnumValuesBlock({ + typeName: enumName, + values: node.values, + schema: this._schema, + naming: { + convert: this.config.convert, + typesPrefix: this.config.typesPrefix, + useTypesPrefix: this.config.enumPrefix, + typesSuffix: this.config.typesSuffix, + useTypesSuffix: this.config.enumSuffix, + }, + ignoreEnumValuesFromSchema: this.config.ignoreEnumValuesFromSchema, + declarationBlockConfig: this._declarationBlockConfig, + enumValues: this.config.enumValues, + }), + ).string; } protected makeValidEnumIdentifier(identifier: string): string { @@ -942,48 +956,6 @@ export class BaseTypesVisitor< return identifier; } - protected buildEnumValuesBlock( - typeName: string, - values: ReadonlyArray, - ): string { - const schemaEnumType: GraphQLEnumType | undefined = this._schema - ? (this._schema.getType(typeName) as GraphQLEnumType) - : undefined; - - return values - .map(enumOption => { - const optionName = this.makeValidEnumIdentifier( - this.convertName(enumOption, { - useTypesPrefix: false, - // We can only strip out the underscores if the value contains other - // characters. Otherwise we'll generate syntactically invalid code. - transformUnderscore: !onlyUnderscoresPattern.test(enumOption.name.value), - }), - ); - const comment = this.getNodeComment(enumOption); - const schemaEnumValue = - schemaEnumType && !this.config.ignoreEnumValuesFromSchema - ? schemaEnumType.getValue(enumOption.name.value).value - : undefined; - let enumValue: string | number = - typeof schemaEnumValue === 'undefined' ? enumOption.name.value : schemaEnumValue; - - if (typeof this.config.enumValues[typeName]?.mappedValues?.[enumValue] !== 'undefined') { - enumValue = this.config.enumValues[typeName].mappedValues[enumValue]; - } - - return ( - comment + - indent( - `${optionName}${ - this._declarationBlockConfig.enumNameValueSeparator - } ${wrapWithSingleQuotes(enumValue, typeof schemaEnumValue !== 'undefined')}`, - ) - ); - }) - .join(',\n'); - } - DirectiveDefinition(_node: DirectiveDefinitionNode): string { return ''; } @@ -1100,30 +1072,6 @@ export class BaseTypesVisitor< return null; } - getNodeComment( - node: FieldDefinitionNode | EnumValueDefinitionNode | InputValueDefinitionNode, - ): string { - let commentText = node.description?.value; - const deprecationDirective = node.directives.find(v => v.name.value === 'deprecated'); - if (deprecationDirective) { - const deprecationReason = this.getDeprecationReason(deprecationDirective); - commentText = `${commentText ? `${commentText}\n` : ''}@deprecated ${deprecationReason}`; - } - const comment = transformComment(commentText, 1); - return comment; - } - - protected getDeprecationReason(directive: DirectiveNode): string | void { - if (directive.name.value === 'deprecated') { - let reason = 'Field no longer supported'; - const deprecatedReason = directive.arguments[0]; - if (deprecatedReason && deprecatedReason.value.kind === Kind.STRING) { - reason = deprecatedReason.value.value; - } - return reason; - } - } - protected wrapWithListType(str: string): string { return `Array<${str}>`; } diff --git a/packages/plugins/other/visitor-plugin-common/src/convert-schema-enum-to-declaration-block-string.ts b/packages/plugins/other/visitor-plugin-common/src/convert-schema-enum-to-declaration-block-string.ts new file mode 100644 index 00000000000..2e456b50df3 --- /dev/null +++ b/packages/plugins/other/visitor-plugin-common/src/convert-schema-enum-to-declaration-block-string.ts @@ -0,0 +1,268 @@ +import type { EnumTypeDefinitionNode, EnumValueDefinitionNode, GraphQLEnumType, GraphQLSchema } from 'graphql'; +import type { ConvertFn, ParsedEnumValuesMap } from './types.js'; +import { + DeclarationBlock, + type DeclarationBlockConfig, + indent, + transformComment, + getNodeComment, + wrapWithSingleQuotes, +} from './utils.js'; + +interface ConvertSchemaEnumToDeclarationBlockString { + schema: GraphQLSchema; + node: EnumTypeDefinitionNode; + enumName: string; + enumValues: ParsedEnumValuesMap; + futureProofEnums: boolean; + ignoreEnumValuesFromSchema: boolean; + naming: { + convert: ConvertFn; + typesPrefix: string; + typesSuffix: string; + useTypesPrefix?: boolean; + useTypesSuffix?: boolean; + }; + + outputType: 'string-literal' | 'native-numeric' | 'const' | 'native-const' | 'native'; + declarationBlockConfig: DeclarationBlockConfig; +} + +export const convertSchemaEnumToDeclarationBlockString = ({ + schema, + node, + enumName, + enumValues, + futureProofEnums, + ignoreEnumValuesFromSchema, + outputType, + declarationBlockConfig, + naming, +}: ConvertSchemaEnumToDeclarationBlockString): string => { + if (enumValues[enumName]?.sourceFile) { + return `export { ${enumValues[enumName].typeIdentifier} };\n`; + } + + const getValueFromConfig = (enumValue: string | number) => { + if (typeof enumValues[enumName]?.mappedValues?.[enumValue] !== 'undefined') { + return enumValues[enumName].mappedValues[enumValue]; + } + return null; + }; + + const withFutureAddedValue = [futureProofEnums ? [indent('| ' + wrapWithSingleQuotes('%future added value'))] : []]; + + const enumTypeName = convertName({ + options: { + typesPrefix: naming.typesPrefix, + typesSuffix: naming.typesSuffix, + useTypesPrefix: naming.useTypesPrefix, + useTypesSuffix: naming.useTypesSuffix, + }, + convert: () => naming.convert(node), + }); + + if (outputType === 'string-literal') { + return new DeclarationBlock(declarationBlockConfig) + .export() + .asKind('type') + .withComment(node.description?.value) + .withName(enumTypeName) + .withContent( + '\n' + + node.values + .map(enumOption => { + const name = enumOption.name.value; + const enumValue: string | number = getValueFromConfig(name) ?? name; + const comment = transformComment(enumOption.description?.value, 1); + + return comment + indent('| ' + wrapWithSingleQuotes(enumValue)); + }) + .concat(...withFutureAddedValue) + .join('\n') + ).string; + } + + if (outputType === 'native-numeric') { + return new DeclarationBlock(declarationBlockConfig) + .export() + .withComment(node.description?.value) + .withName(enumTypeName) + .asKind('enum') + .withBlock( + node.values + .map((enumOption, i) => { + const valueFromConfig = getValueFromConfig(enumOption.name.value); + const enumValue: string | number = valueFromConfig ?? i; + const comment = transformComment(enumOption.description?.value, 1); + const optionName = makeValidEnumIdentifier( + convertName({ + options: { + typesPrefix: naming.typesPrefix, + typesSuffix: naming.typesSuffix, + useTypesPrefix: false, + }, + convert: () => naming.convert(enumOption, { transformUnderscore: true }), + }) + ); + return comment + indent(optionName) + ` = ${enumValue}`; + }) + .concat(...withFutureAddedValue) + .join(',\n') + ).string; + } + + if (outputType === 'const') { + const typeName = `export type ${enumTypeName} = typeof ${enumTypeName}[keyof typeof ${enumTypeName}];`; + const enumAsConst = new DeclarationBlock({ + ...declarationBlockConfig, + blockTransformer: block => { + return block + ' as const'; + }, + }) + .export() + .asKind('const') + .withName(enumTypeName) + .withComment(node.description?.value) + .withBlock( + node.values + .map(enumOption => { + const optionName = makeValidEnumIdentifier( + convertName({ + options: { + typesPrefix: naming.typesPrefix, + typesSuffix: naming.typesPrefix, + }, + convert: () => + naming.convert(enumOption, { + transformUnderscore: true, + }), + }) + ); + const comment = transformComment(enumOption.description?.value, 1); + const name = enumOption.name.value; + const enumValue: string | number = getValueFromConfig(name) ?? name; + + return comment + indent(`${optionName}: ${wrapWithSingleQuotes(enumValue)}`); + }) + .join(',\n') + ).string; + + return [enumAsConst, typeName].join('\n'); + } + + return new DeclarationBlock(declarationBlockConfig) + .export() + .asKind(outputType === 'native-const' ? 'const enum' : 'enum') + .withName(enumTypeName) + .withComment(node.description?.value) + .withBlock( + buildEnumValuesBlock({ + typeName: enumName, + values: node.values, + schema, + naming, + ignoreEnumValuesFromSchema, + declarationBlockConfig, + enumValues, + }) + ).string; +}; + +export const buildEnumValuesBlock = ({ + typeName, + values, + schema, + naming, + ignoreEnumValuesFromSchema, + declarationBlockConfig, + enumValues, +}: Pick< + ConvertSchemaEnumToDeclarationBlockString, + 'schema' | 'naming' | 'ignoreEnumValuesFromSchema' | 'declarationBlockConfig' | 'enumValues' +> & { + typeName: string; + values: ReadonlyArray; +}): string => { + const schemaEnumType: GraphQLEnumType | undefined = schema + ? (schema.getType(typeName) as GraphQLEnumType) + : undefined; + + return values + .map(enumOption => { + const onlyUnderscoresPattern = /^_+$/; + const optionName = makeValidEnumIdentifier( + convertName({ + options: { + useTypesPrefix: false, + typesPrefix: naming.typesPrefix, + typesSuffix: naming.typesSuffix, + }, + convert: () => + naming.convert(enumOption, { + // We can only strip out the underscores if the value contains other + // characters. Otherwise we'll generate syntactically invalid code. + transformUnderscore: !onlyUnderscoresPattern.test(enumOption.name.value), + }), + }) + ); + const comment = getNodeComment(enumOption); + const schemaEnumValue = + schemaEnumType && !ignoreEnumValuesFromSchema + ? schemaEnumType.getValue(enumOption.name.value).value + : undefined; + let enumValue: string | number = typeof schemaEnumValue === 'undefined' ? enumOption.name.value : schemaEnumValue; + + if (typeof enumValues[typeName]?.mappedValues?.[enumValue] !== 'undefined') { + enumValue = enumValues[typeName].mappedValues[enumValue]; + } + + return ( + comment + + indent( + `${optionName}${declarationBlockConfig.enumNameValueSeparator} ${wrapWithSingleQuotes( + enumValue, + typeof schemaEnumValue !== 'undefined' + )}` + ) + ); + }) + .join(',\n'); +}; + +const makeValidEnumIdentifier = (identifier: string): string => { + if (/^[0-9]/.exec(identifier)) { + return wrapWithSingleQuotes(identifier, true); + } + return identifier; +}; + +const convertName = ({ + convert, + options, +}: { + options: { + typesPrefix: string; + useTypesPrefix?: boolean; + typesSuffix: string; + useTypesSuffix?: boolean; + }; + convert: () => string; +}): string => { + const useTypesPrefix = typeof options.useTypesPrefix === 'boolean' ? options.useTypesPrefix : true; + const useTypesSuffix = typeof options.useTypesSuffix === 'boolean' ? options.useTypesSuffix : true; + + let convertedName = ''; + + if (useTypesPrefix) { + convertedName += options.typesPrefix; + } + + convertedName += convert(); + + if (useTypesSuffix) { + convertedName += options.typesSuffix; + } + + return convertedName; +}; diff --git a/packages/plugins/other/visitor-plugin-common/src/index.ts b/packages/plugins/other/visitor-plugin-common/src/index.ts index a196546db4f..bdb72829a17 100644 --- a/packages/plugins/other/visitor-plugin-common/src/index.ts +++ b/packages/plugins/other/visitor-plugin-common/src/index.ts @@ -17,3 +17,4 @@ export * from './selection-set-to-object.js'; export * from './types.js'; export * from './utils.js'; export * from './variables-to-object.js'; +export * from './convert-schema-enum-to-declaration-block-string.js'; diff --git a/packages/plugins/other/visitor-plugin-common/src/utils.ts b/packages/plugins/other/visitor-plugin-common/src/utils.ts index 81f74bbc24a..75c9ebf4c14 100644 --- a/packages/plugins/other/visitor-plugin-common/src/utils.ts +++ b/packages/plugins/other/visitor-plugin-common/src/utils.ts @@ -1,5 +1,7 @@ import { DirectiveNode, + EnumValueDefinitionNode, + FieldDefinitionNode, FieldNode, FragmentSpreadNode, GraphQLInputObjectType, @@ -9,6 +11,7 @@ import { GraphQLScalarType, GraphQLSchema, InlineFragmentNode, + InputValueDefinitionNode, isAbstractType, isInputObjectType, isListType, @@ -721,3 +724,27 @@ export const getFieldNames = ({ } return fieldNames; }; + +export const getNodeComment = ( + node: FieldDefinitionNode | EnumValueDefinitionNode | InputValueDefinitionNode, +): string => { + let commentText = node.description?.value; + const deprecationDirective = node.directives.find(v => v.name.value === 'deprecated'); + if (deprecationDirective) { + const deprecationReason = getDeprecationReason(deprecationDirective); + commentText = `${commentText ? `${commentText}\n` : ''}@deprecated ${deprecationReason}`; + } + const comment = transformComment(commentText, 1); + return comment; +}; + +const getDeprecationReason = (directive: DirectiveNode): string | void => { + if (directive.name.value === 'deprecated') { + let reason = 'Field no longer supported'; + const deprecatedReason = directive.arguments[0]; + if (deprecatedReason && deprecatedReason.value.kind === Kind.STRING) { + reason = deprecatedReason.value.value; + } + return reason; + } +}; diff --git a/packages/plugins/typescript/typescript/src/visitor.ts b/packages/plugins/typescript/typescript/src/visitor.ts index a3bdcd8547f..363dac5ffab 100644 --- a/packages/plugins/typescript/typescript/src/visitor.ts +++ b/packages/plugins/typescript/typescript/src/visitor.ts @@ -15,16 +15,16 @@ import { } from 'graphql'; import { BaseTypesVisitor, + convertSchemaEnumToDeclarationBlockString, DeclarationBlock, DeclarationKind, getConfigValue, + getNodeComment, indent, isOneOfInputObjectType, normalizeAvoidOptionals, NormalizedAvoidOptionalsConfig, ParsedTypesConfig, - transformComment, - wrapWithSingleQuotes, } from '@graphql-codegen/visitor-plugin-common'; import { TypeScriptPluginConfig } from './config.js'; import { TypeScriptOperationVariablesToObject } from './typescript-variables-to-object.js'; @@ -300,7 +300,7 @@ export class TsVisitor< const originalFieldNode = parent[key] as FieldDefinitionNode; const addOptionalSign = !this.config.avoidOptionals.field && originalFieldNode.type.kind !== Kind.NON_NULL_TYPE; - const comment = this.getNodeComment(node); + const comment = getNodeComment(node); const { type } = this.config.declarationKind; return ( @@ -326,7 +326,7 @@ export class TsVisitor< !this.config.avoidOptionals.inputValue && (originalFieldNode.type.kind !== Kind.NON_NULL_TYPE || (!this.config.avoidOptionals.defaultValue && node.defaultValue !== undefined)); - const comment = this.getNodeComment(node); + const comment = getNodeComment(node); const declarationKind = this.config.declarationKind.type; let type: string = node.type as any as string; @@ -370,116 +370,41 @@ export class TsVisitor< EnumTypeDefinition(node: EnumTypeDefinitionNode): string { const enumName = node.name.value; - // In case of mapped external enum string - if (this.config.enumValues[enumName]?.sourceFile) { - return `export { ${this.config.enumValues[enumName].typeIdentifier} };\n`; - } - - const getValueFromConfig = (enumValue: string | number) => { - if (typeof this.config.enumValues[enumName]?.mappedValues?.[enumValue] !== 'undefined') { - return this.config.enumValues[enumName].mappedValues[enumValue]; + const outputType = ((): Parameters< + typeof convertSchemaEnumToDeclarationBlockString + >[0]['outputType'] => { + if (this.config.enumsAsTypes) { + return 'string-literal'; } - return null; - }; - - const withFutureAddedValue = [ - this.config.futureProofEnums - ? [indent('| ' + wrapWithSingleQuotes('%future added value'))] - : [], - ]; - const enumTypeName = this.convertName(node, { - useTypesPrefix: this.config.enumPrefix, - useTypesSuffix: this.config.enumSuffix, - }); - - if (this.config.enumsAsTypes) { - return new DeclarationBlock(this._declarationBlockConfig) - .export() - .asKind('type') - .withComment(node.description?.value) - .withName(enumTypeName) - .withContent( - '\n' + - node.values - .map(enumOption => { - const name = enumOption.name.value; - const enumValue: string | number = getValueFromConfig(name) ?? name; - const comment = transformComment(enumOption.description?.value, 1); - - return comment + indent('| ' + wrapWithSingleQuotes(enumValue)); - }) - .concat(...withFutureAddedValue) - .join('\n'), - ).string; - } + if (this.config.numericEnums) { + return 'native-numeric'; + } - if (this.config.numericEnums) { - const block = new DeclarationBlock(this._declarationBlockConfig) - .export() - .withComment(node.description?.value) - .withName(enumTypeName) - .asKind('enum') - .withBlock( - node.values - .map((enumOption, i) => { - const valueFromConfig = getValueFromConfig(enumOption.name.value); - const enumValue: string | number = valueFromConfig ?? i; - const comment = transformComment(enumOption.description?.value, 1); - const optionName = this.makeValidEnumIdentifier( - this.convertName(enumOption, { - useTypesPrefix: false, - transformUnderscore: true, - }), - ); - return comment + indent(optionName) + ` = ${enumValue}`; - }) - .concat(...withFutureAddedValue) - .join(',\n'), - ).string; - - return block; - } + if (this.config.enumsAsConst) { + return 'const'; + } - if (this.config.enumsAsConst) { - const typeName = `export type ${enumTypeName} = typeof ${enumTypeName}[keyof typeof ${enumTypeName}];`; - const enumAsConst = new DeclarationBlock({ - ...this._declarationBlockConfig, - blockTransformer: block => { - return block + ' as const'; - }, - }) - .export() - .asKind('const') - .withName(enumTypeName) - .withComment(node.description?.value) - .withBlock( - node.values - .map(enumOption => { - const optionName = this.makeValidEnumIdentifier( - this.convertName(enumOption, { - useTypesPrefix: false, - transformUnderscore: true, - }), - ); - const comment = transformComment(enumOption.description?.value, 1); - const name = enumOption.name.value; - const enumValue: string | number = getValueFromConfig(name) ?? name; - - return comment + indent(`${optionName}: ${wrapWithSingleQuotes(enumValue)}`); - }) - .join(',\n'), - ).string; - - return [enumAsConst, typeName].join('\n'); - } + return this.config.constEnums ? 'native-const' : 'native'; + })(); - return new DeclarationBlock(this._declarationBlockConfig) - .export() - .asKind(this.config.constEnums ? 'const enum' : 'enum') - .withName(enumTypeName) - .withComment(node.description?.value) - .withBlock(this.buildEnumValuesBlock(enumName, node.values)).string; + return convertSchemaEnumToDeclarationBlockString({ + schema: this._schema, + node, + declarationBlockConfig: this._declarationBlockConfig, + enumName, + enumValues: this.config.enumValues, + futureProofEnums: this.config.futureProofEnums, + ignoreEnumValuesFromSchema: this.config.ignoreEnumValuesFromSchema, + outputType, + naming: { + convert: this.config.convert, + typesPrefix: this.config.typesPrefix, + typesSuffix: this.config.typesSuffix, + useTypesPrefix: this.config.enumPrefix, + useTypesSuffix: this.config.enumSuffix, + }, + }); } protected getPunctuation(_declarationKind: DeclarationKind): string { From 7352cf280856a9bdf32a26ba8125e75faffd8986 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Wed, 26 Nov 2025 00:47:46 +1100 Subject: [PATCH 07/69] [typescript-operations] Generate enums referenced in operation Variables (#10508) * Collect used enums * Use enum converter for Enum * Add changeset * Add doc * Update dev tests * Fix return type issue --- .changeset/curly-trees-lead.md | 5 + dev-test/githunt/typed-document-nodes.ts | 12 ++ dev-test/githunt/types.avoidOptionals.ts | 12 ++ dev-test/githunt/types.d.ts | 12 ++ dev-test/githunt/types.enumsAsTypes.ts | 12 ++ .../githunt/types.flatten.preResolveTypes.ts | 12 ++ dev-test/githunt/types.immutableTypes.ts | 12 ++ ...ypes.preResolveTypes.onlyOperationTypes.ts | 12 ++ dev-test/githunt/types.preResolveTypes.ts | 12 ++ dev-test/githunt/types.ts | 12 ++ dev-test/star-wars/types.avoidOptionals.ts | 9 ++ dev-test/star-wars/types.excludeQueryAlpha.ts | 9 ++ dev-test/star-wars/types.excludeQueryBeta.ts | 9 ++ .../star-wars/types.globallyAvailable.d.ts | 9 ++ dev-test/star-wars/types.immutableTypes.ts | 9 ++ ...ypes.preResolveTypes.onlyOperationTypes.ts | 9 ++ dev-test/star-wars/types.preResolveTypes.ts | 9 ++ dev-test/star-wars/types.skipSchema.ts | 9 ++ dev-test/star-wars/types.ts | 9 ++ ...schema-enum-to-declaration-block-string.ts | 2 +- .../typescript/operations/src/config.ts | 124 +++++++++++++++++- .../typescript/operations/src/index.ts | 45 +++---- .../typescript/operations/src/visitor.ts | 107 ++++++++++++++- .../tests/ts-documents.standalone.spec.ts | 20 ++- 24 files changed, 460 insertions(+), 32 deletions(-) create mode 100644 .changeset/curly-trees-lead.md diff --git a/.changeset/curly-trees-lead.md b/.changeset/curly-trees-lead.md new file mode 100644 index 00000000000..e6aab78bdca --- /dev/null +++ b/.changeset/curly-trees-lead.md @@ -0,0 +1,5 @@ +--- +'@graphql-codegen/typescript-operations': major +--- + +BREAKING CHANGE: typescript-operations plugin now generates enum if it is used in operation. diff --git a/dev-test/githunt/typed-document-nodes.ts b/dev-test/githunt/typed-document-nodes.ts index 9ca29efb843..ae4afad33b9 100644 --- a/dev-test/githunt/typed-document-nodes.ts +++ b/dev-test/githunt/typed-document-nodes.ts @@ -174,6 +174,18 @@ export enum VoteType { Up = 'UP', } +/** A list of options for the sort order of the feed */ +export type FeedType = + /** Sort by a combination of freshness and score, using Reddit's algorithm */ + | 'HOT' + /** Newest entries first */ + | 'NEW' + /** Highest score entries first */ + | 'TOP'; + +/** The type of vote to record, when submitting a vote */ +export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; + export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.avoidOptionals.ts b/dev-test/githunt/types.avoidOptionals.ts index 0612dfd6890..dc858460296 100644 --- a/dev-test/githunt/types.avoidOptionals.ts +++ b/dev-test/githunt/types.avoidOptionals.ts @@ -172,6 +172,18 @@ export enum VoteType { Up = 'UP', } +/** A list of options for the sort order of the feed */ +export type FeedType = + /** Sort by a combination of freshness and score, using Reddit's algorithm */ + | 'HOT' + /** Newest entries first */ + | 'NEW' + /** Highest score entries first */ + | 'TOP'; + +/** The type of vote to record, when submitting a vote */ +export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; + export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.d.ts b/dev-test/githunt/types.d.ts index 3e669417bac..3da7a693cf2 100644 --- a/dev-test/githunt/types.d.ts +++ b/dev-test/githunt/types.d.ts @@ -167,6 +167,18 @@ export type Vote = { /** The type of vote to record, when submitting a vote */ export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; +/** A list of options for the sort order of the feed */ +export type FeedType = + /** Sort by a combination of freshness and score, using Reddit's algorithm */ + | 'HOT' + /** Newest entries first */ + | 'NEW' + /** Highest score entries first */ + | 'TOP'; + +/** The type of vote to record, when submitting a vote */ +export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; + export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.enumsAsTypes.ts b/dev-test/githunt/types.enumsAsTypes.ts index 3e669417bac..3da7a693cf2 100644 --- a/dev-test/githunt/types.enumsAsTypes.ts +++ b/dev-test/githunt/types.enumsAsTypes.ts @@ -167,6 +167,18 @@ export type Vote = { /** The type of vote to record, when submitting a vote */ export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; +/** A list of options for the sort order of the feed */ +export type FeedType = + /** Sort by a combination of freshness and score, using Reddit's algorithm */ + | 'HOT' + /** Newest entries first */ + | 'NEW' + /** Highest score entries first */ + | 'TOP'; + +/** The type of vote to record, when submitting a vote */ +export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; + export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.flatten.preResolveTypes.ts b/dev-test/githunt/types.flatten.preResolveTypes.ts index 48e7f922615..bad10699b35 100644 --- a/dev-test/githunt/types.flatten.preResolveTypes.ts +++ b/dev-test/githunt/types.flatten.preResolveTypes.ts @@ -172,6 +172,18 @@ export enum VoteType { Up = 'UP', } +/** A list of options for the sort order of the feed */ +export type FeedType = + /** Sort by a combination of freshness and score, using Reddit's algorithm */ + | 'HOT' + /** Newest entries first */ + | 'NEW' + /** Highest score entries first */ + | 'TOP'; + +/** The type of vote to record, when submitting a vote */ +export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; + export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.immutableTypes.ts b/dev-test/githunt/types.immutableTypes.ts index 15205c69630..8ad47a574a7 100644 --- a/dev-test/githunt/types.immutableTypes.ts +++ b/dev-test/githunt/types.immutableTypes.ts @@ -172,6 +172,18 @@ export enum VoteType { Up = 'UP', } +/** A list of options for the sort order of the feed */ +export type FeedType = + /** Sort by a combination of freshness and score, using Reddit's algorithm */ + | 'HOT' + /** Newest entries first */ + | 'NEW' + /** Highest score entries first */ + | 'TOP'; + +/** The type of vote to record, when submitting a vote */ +export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; + export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts index f83e95365e0..12e97f9c499 100644 --- a/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts @@ -35,6 +35,18 @@ export enum VoteType { Up = 'UP', } +/** A list of options for the sort order of the feed */ +export type FeedType = + /** Sort by a combination of freshness and score, using Reddit's algorithm */ + | 'HOT' + /** Newest entries first */ + | 'NEW' + /** Highest score entries first */ + | 'TOP'; + +/** The type of vote to record, when submitting a vote */ +export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; + export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.preResolveTypes.ts b/dev-test/githunt/types.preResolveTypes.ts index 7c7f591cd75..74b2740044d 100644 --- a/dev-test/githunt/types.preResolveTypes.ts +++ b/dev-test/githunt/types.preResolveTypes.ts @@ -172,6 +172,18 @@ export enum VoteType { Up = 'UP', } +/** A list of options for the sort order of the feed */ +export type FeedType = + /** Sort by a combination of freshness and score, using Reddit's algorithm */ + | 'HOT' + /** Newest entries first */ + | 'NEW' + /** Highest score entries first */ + | 'TOP'; + +/** The type of vote to record, when submitting a vote */ +export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; + export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.ts b/dev-test/githunt/types.ts index 7c7f591cd75..74b2740044d 100644 --- a/dev-test/githunt/types.ts +++ b/dev-test/githunt/types.ts @@ -172,6 +172,18 @@ export enum VoteType { Up = 'UP', } +/** A list of options for the sort order of the feed */ +export type FeedType = + /** Sort by a combination of freshness and score, using Reddit's algorithm */ + | 'HOT' + /** Newest entries first */ + | 'NEW' + /** Highest score entries first */ + | 'TOP'; + +/** The type of vote to record, when submitting a vote */ +export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; + export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/star-wars/types.avoidOptionals.ts b/dev-test/star-wars/types.avoidOptionals.ts index 8a218f79265..a95a43c2d9f 100644 --- a/dev-test/star-wars/types.avoidOptionals.ts +++ b/dev-test/star-wars/types.avoidOptionals.ts @@ -244,6 +244,15 @@ export type StarshipLengthArgs = { unit?: InputMaybe; }; +/** The episodes in the Star Wars trilogy */ +export type Episode = + /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ + | 'EMPIRE' + /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ + | 'JEDI' + /** Star Wars Episode IV: A New Hope, released in 1977. */ + | 'NEWHOPE'; + export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.excludeQueryAlpha.ts b/dev-test/star-wars/types.excludeQueryAlpha.ts index 063e31c3a00..9dd975c83e7 100644 --- a/dev-test/star-wars/types.excludeQueryAlpha.ts +++ b/dev-test/star-wars/types.excludeQueryAlpha.ts @@ -244,6 +244,15 @@ export type StarshipLengthArgs = { unit?: InputMaybe; }; +/** The episodes in the Star Wars trilogy */ +export type Episode = + /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ + | 'EMPIRE' + /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ + | 'JEDI' + /** Star Wars Episode IV: A New Hope, released in 1977. */ + | 'NEWHOPE'; + export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.excludeQueryBeta.ts b/dev-test/star-wars/types.excludeQueryBeta.ts index 3ea8a6c5617..82abe1489d1 100644 --- a/dev-test/star-wars/types.excludeQueryBeta.ts +++ b/dev-test/star-wars/types.excludeQueryBeta.ts @@ -244,6 +244,15 @@ export type StarshipLengthArgs = { unit?: InputMaybe; }; +/** The episodes in the Star Wars trilogy */ +export type Episode = + /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ + | 'EMPIRE' + /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ + | 'JEDI' + /** Star Wars Episode IV: A New Hope, released in 1977. */ + | 'NEWHOPE'; + export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.globallyAvailable.d.ts b/dev-test/star-wars/types.globallyAvailable.d.ts index 7cdcb977a14..54fee1cf66e 100644 --- a/dev-test/star-wars/types.globallyAvailable.d.ts +++ b/dev-test/star-wars/types.globallyAvailable.d.ts @@ -240,6 +240,15 @@ type StarshipLengthArgs = { unit?: InputMaybe; }; +/** The episodes in the Star Wars trilogy */ +type Episode = + /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ + | 'EMPIRE' + /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ + | 'JEDI' + /** Star Wars Episode IV: A New Hope, released in 1977. */ + | 'NEWHOPE'; + type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.immutableTypes.ts b/dev-test/star-wars/types.immutableTypes.ts index a5d194d5c0b..d052e77ce91 100644 --- a/dev-test/star-wars/types.immutableTypes.ts +++ b/dev-test/star-wars/types.immutableTypes.ts @@ -244,6 +244,15 @@ export type StarshipLengthArgs = { unit?: InputMaybe; }; +/** The episodes in the Star Wars trilogy */ +export type Episode = + /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ + | 'EMPIRE' + /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ + | 'JEDI' + /** Star Wars Episode IV: A New Hope, released in 1977. */ + | 'NEWHOPE'; + export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts index 6f844783949..7cc36a1451e 100644 --- a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts @@ -53,6 +53,15 @@ export type ReviewInput = { stars: Scalars['Int']['input']; }; +/** The episodes in the Star Wars trilogy */ +export type Episode = + /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ + | 'EMPIRE' + /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ + | 'JEDI' + /** Star Wars Episode IV: A New Hope, released in 1977. */ + | 'NEWHOPE'; + export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.preResolveTypes.ts b/dev-test/star-wars/types.preResolveTypes.ts index e3d32fb9e2e..2d8f0be51e8 100644 --- a/dev-test/star-wars/types.preResolveTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.ts @@ -244,6 +244,15 @@ export type StarshipLengthArgs = { unit?: InputMaybe; }; +/** The episodes in the Star Wars trilogy */ +export type Episode = + /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ + | 'EMPIRE' + /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ + | 'JEDI' + /** Star Wars Episode IV: A New Hope, released in 1977. */ + | 'NEWHOPE'; + export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.skipSchema.ts b/dev-test/star-wars/types.skipSchema.ts index e3d32fb9e2e..2d8f0be51e8 100644 --- a/dev-test/star-wars/types.skipSchema.ts +++ b/dev-test/star-wars/types.skipSchema.ts @@ -244,6 +244,15 @@ export type StarshipLengthArgs = { unit?: InputMaybe; }; +/** The episodes in the Star Wars trilogy */ +export type Episode = + /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ + | 'EMPIRE' + /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ + | 'JEDI' + /** Star Wars Episode IV: A New Hope, released in 1977. */ + | 'NEWHOPE'; + export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.ts b/dev-test/star-wars/types.ts index e3d32fb9e2e..2d8f0be51e8 100644 --- a/dev-test/star-wars/types.ts +++ b/dev-test/star-wars/types.ts @@ -244,6 +244,15 @@ export type StarshipLengthArgs = { unit?: InputMaybe; }; +/** The episodes in the Star Wars trilogy */ +export type Episode = + /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ + | 'EMPIRE' + /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ + | 'JEDI' + /** Star Wars Episode IV: A New Hope, released in 1977. */ + | 'NEWHOPE'; + export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/packages/plugins/other/visitor-plugin-common/src/convert-schema-enum-to-declaration-block-string.ts b/packages/plugins/other/visitor-plugin-common/src/convert-schema-enum-to-declaration-block-string.ts index 2e456b50df3..30279ebed3a 100644 --- a/packages/plugins/other/visitor-plugin-common/src/convert-schema-enum-to-declaration-block-string.ts +++ b/packages/plugins/other/visitor-plugin-common/src/convert-schema-enum-to-declaration-block-string.ts @@ -9,7 +9,7 @@ import { wrapWithSingleQuotes, } from './utils.js'; -interface ConvertSchemaEnumToDeclarationBlockString { +export interface ConvertSchemaEnumToDeclarationBlockString { schema: GraphQLSchema; node: EnumTypeDefinitionNode; enumName: string; diff --git a/packages/plugins/typescript/operations/src/config.ts b/packages/plugins/typescript/operations/src/config.ts index ec83928eecc..44fb213b786 100644 --- a/packages/plugins/typescript/operations/src/config.ts +++ b/packages/plugins/typescript/operations/src/config.ts @@ -1,4 +1,9 @@ -import { AvoidOptionalsConfig, RawDocumentsConfig } from '@graphql-codegen/visitor-plugin-common'; +import { + AvoidOptionalsConfig, + type ConvertSchemaEnumToDeclarationBlockString, + type EnumValuesMap, + RawDocumentsConfig, +} from '@graphql-codegen/visitor-plugin-common'; /** * @description This plugin generates TypeScript types based on your GraphQLSchema _and_ your GraphQL operations and fragments. @@ -336,4 +341,121 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { nullability?: { errorHandlingClient: boolean; }; + + /** + * @description Controls the enum output type. Options: `string-literal` | `native-numeric` | `const` | `native-const` | `native`; + * @default `string-literal` + * + * @exampleMarkdown + * ```ts filename="codegen.ts" + * import type { CodegenConfig } from '@graphql-codegen/cli' + * + * const config: CodegenConfig = { + * // ... + * generates: { + * 'path/to/file.ts': { + * plugins: ['typescript-operations'], + * config: { + * enumType: 'string-literal', + * } + * } + * } + * } + * export default config + */ + enumType?: ConvertSchemaEnumToDeclarationBlockString['outputType']; + + /** + * @description Overrides the default value of enum values declared in your GraphQL schema. + * You can also map the entire enum to an external type by providing a string that of `module#type`. + * + * @exampleMarkdown + * ## With Custom Values + * ```ts filename="codegen.ts" + * import type { CodegenConfig } from '@graphql-codegen/cli'; + * + * const config: CodegenConfig = { + * // ... + * generates: { + * 'path/to/file': { + * // plugins... + * config: { + * enumValues: { + * MyEnum: { + * A: 'foo' + * } + * } + * }, + * }, + * }, + * }; + * export default config; + * ``` + * + * ## With External Enum + * ```ts filename="codegen.ts" + * import type { CodegenConfig } from '@graphql-codegen/cli'; + * + * const config: CodegenConfig = { + * // ... + * generates: { + * 'path/to/file': { + * // plugins... + * config: { + * enumValues: { + * MyEnum: './my-file#MyCustomEnum', + * } + * }, + * }, + * }, + * }; + * export default config; + * ``` + * + * ## Import All Enums from a file + * ```ts filename="codegen.ts" + * import type { CodegenConfig } from '@graphql-codegen/cli'; + * + * const config: CodegenConfig = { + * // ... + * generates: { + * 'path/to/file': { + * // plugins... + * config: { + * enumValues: { + * MyEnum: './my-file', + * } + * }, + * }, + * }, + * }; + * export default config; + * ``` + */ + enumValues?: EnumValuesMap; + + /** + * @description This option controls whether or not a catch-all entry is added to enum type definitions for values that may be added in the future. + * This is useful if you are using `relay`. + * @default false + * + * @exampleMarkdown + * ```ts filename="codegen.ts" + * import type { CodegenConfig } from '@graphql-codegen/cli' + * + * const config: CodegenConfig = { + * // ... + * generates: { + * 'path/to/file.ts': { + * plugins: ['typescript-operations'], + * config: { + * futureProofEnums: true + * } + * } + * } + * } + * export default config + * ``` + */ + futureProofEnums?: boolean; } diff --git a/packages/plugins/typescript/operations/src/index.ts b/packages/plugins/typescript/operations/src/index.ts index 9d87df73309..7e3705fdfbf 100644 --- a/packages/plugins/typescript/operations/src/index.ts +++ b/packages/plugins/typescript/operations/src/index.ts @@ -1,6 +1,7 @@ -import { concatAST, FragmentDefinitionNode, GraphQLSchema, Kind, type DocumentNode } from 'graphql'; +import { concatAST, GraphQLSchema, type DocumentNode } from 'graphql'; import { oldVisit, PluginFunction, Types } from '@graphql-codegen/plugin-helpers'; -import { LoadedFragment, optimizeOperations } from '@graphql-codegen/visitor-plugin-common'; +import { transformSchemaAST } from '@graphql-codegen/schema-ast'; +import { optimizeOperations } from '@graphql-codegen/visitor-plugin-common'; import { TypeScriptDocumentsPluginConfig } from './config.js'; import { TypeScriptDocumentsVisitor } from './visitor.js'; @@ -57,43 +58,39 @@ export const plugin: PluginFunction< // For Fragment types to resolve correctly, we must get read all docs (`standard` and `external`) // Fragment types are usually (but not always) in `external` files in certain setup, like a monorepo. const allDocumentsAST = concatAST(parsedDocuments.all.documentNodes); - const allFragments: LoadedFragment[] = [ - ...( - allDocumentsAST.definitions.filter( - d => d.kind === Kind.FRAGMENT_DEFINITION, - ) as FragmentDefinitionNode[] - ).map(fragmentDef => ({ - node: fragmentDef, - name: fragmentDef.name.value, - onType: fragmentDef.typeCondition.name.value, - isExternal: false, - })), - ...(config.externalFragments || []), - ]; - - const visitor = new TypeScriptDocumentsVisitor(schema, config, allFragments); + const visitor = new TypeScriptDocumentsVisitor(schema, config, allDocumentsAST); // We only visit `standard` documents to generate types. // `external` documents are included as references for typechecking and completeness i.e. only used for reading purposes, no writing. const documentsToVisitAST = concatAST(parsedDocuments.standard.documentNodes); - const visitorResult = oldVisit(documentsToVisitAST, { + const operationsResult = oldVisit(documentsToVisitAST, { leave: visitor, }); - let content = visitorResult.definitions.join('\n'); + const operationsDefinitions = operationsResult.definitions; if (config.addOperationExport) { - const exportConsts = []; - for (const d of allDocumentsAST.definitions) { if ('name' in d) { - exportConsts.push(`export declare const ${d.name.value}: import("graphql").DocumentNode;`); + operationsDefinitions.push( + `export declare const ${d.name.value}: import("graphql").DocumentNode;`, + ); } } - - content = visitorResult.definitions.concat(exportConsts).join('\n'); } + const schemaTypes = oldVisit(transformSchemaAST(schema, config).ast, { leave: visitor }); + + // IMPORTANT: when a visitor leaves a node with no transformation logic, + // It will leave the node as an object. + // Here, we filter in nodes that have been turned into strings, i.e. they have been transformed + // This way, we do not have to explicitly declare a method for every node type to convert them to null + const schemaTypesDefinitions = schemaTypes.definitions + .filter(def => typeof def === 'string') + .join('\n'); + + let content = [...schemaTypesDefinitions, ...operationsDefinitions].join('\n'); + if (config.globalNamespace) { content = ` declare global { diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 845e692dadf..1164d7dd4ab 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -1,13 +1,23 @@ import autoBind from 'auto-bind'; import { - GraphQLNamedType, - GraphQLOutputType, - GraphQLSchema, + EnumTypeDefinitionNode, + GraphQLEnumType, + GraphQLInputObjectType, + GraphQLScalarType, isEnumType, isNonNullType, + Kind, + visit, + type DocumentNode, + type FragmentDefinitionNode, + type GraphQLNamedInputType, + type GraphQLNamedType, + type GraphQLOutputType, + type GraphQLSchema, } from 'graphql'; import { BaseDocumentsVisitor, + convertSchemaEnumToDeclarationBlockString, DeclarationKind, generateFragmentImportStatement, getConfigValue, @@ -15,10 +25,13 @@ import { normalizeAvoidOptionals, NormalizedAvoidOptionalsConfig, ParsedDocumentsConfig, + parseEnumValues, PreResolveTypesProcessor, SelectionSetProcessorConfig, SelectionSetToObject, wrapTypeWithModifiers, + type ConvertSchemaEnumToDeclarationBlockString, + type ParsedEnumValuesMap, } from '@graphql-codegen/visitor-plugin-common'; import { TypeScriptDocumentsPluginConfig } from './config.js'; import { TypeScriptOperationVariablesToObject } from './ts-operation-variables-to-object.js'; @@ -31,16 +44,22 @@ export interface TypeScriptDocumentsParsedConfig extends ParsedDocumentsConfig { noExport: boolean; maybeValue: string; allowUndefinedQueryVariables: boolean; + enumType: ConvertSchemaEnumToDeclarationBlockString['outputType']; + futureProofEnums: boolean; + enumValues: ParsedEnumValuesMap; } +type UsedNamedInputTypes = Record; + export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< TypeScriptDocumentsPluginConfig, TypeScriptDocumentsParsedConfig > { + protected _usedNamedInputTypes: UsedNamedInputTypes = {}; constructor( schema: GraphQLSchema, config: TypeScriptDocumentsPluginConfig, - allFragments: LoadedFragment[], + documentNode: DocumentNode, ) { super( config, @@ -53,6 +72,13 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< preResolveTypes: getConfigValue(config.preResolveTypes, true), mergeFragmentTypes: getConfigValue(config.mergeFragmentTypes, false), allowUndefinedQueryVariables: getConfigValue(config.allowUndefinedQueryVariables, false), + enumType: getConfigValue(config.enumType, 'string-literal'), + enumValues: parseEnumValues({ + schema, + mapOrStr: config.enumValues, + ignoreEnumValuesFromSchema: config.ignoreEnumValuesFromSchema, + }), + futureProofEnums: getConfigValue(config.futureProofEnums, false), } as TypeScriptDocumentsParsedConfig, schema, ); @@ -88,6 +114,22 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< return (this.config.immutableTypes ? `readonly ${name}` : name) + (optional ? '?' : ''); }; + const allFragments: LoadedFragment[] = [ + ...( + documentNode.definitions.filter( + d => d.kind === Kind.FRAGMENT_DEFINITION, + ) as FragmentDefinitionNode[] + ).map(fragmentDef => ({ + node: fragmentDef, + name: fragmentDef.name.value, + onType: fragmentDef.typeCondition.name.value, + isExternal: false, + })), + ...(config.externalFragments || []), + ]; + + this._usedNamedInputTypes = this.collectUsedInputTypes({ schema, documentNode }); + const processorConfig: SelectionSetProcessorConfig = { namespacedImportName: this.config.namespacedImportName, convertName: this.convertName.bind(this), @@ -142,6 +184,31 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< }; } + EnumTypeDefinition(node: EnumTypeDefinitionNode): string | null { + const enumName = node.name.value; + if (!this._usedNamedInputTypes[enumName]) { + return null; + } + + return convertSchemaEnumToDeclarationBlockString({ + schema: this._schema, + node, + declarationBlockConfig: this._declarationBlockConfig, + enumName, + enumValues: this.config.enumValues, + futureProofEnums: this.config.futureProofEnums, + ignoreEnumValuesFromSchema: this.config.ignoreEnumValuesFromSchema, + outputType: this.config.enumType, + naming: { + convert: this.config.convert, + typesPrefix: this.config.typesPrefix, + typesSuffix: this.config.typesSuffix, + useTypesPrefix: this.config.enumPrefix, + useTypesSuffix: this.config.enumSuffix, + }, + }); + } + public getImports(): Array { return !this.config.globalNamespace && (this.config.inlineFragmentTypes === 'combine' || this.config.inlineFragmentTypes === 'mask') @@ -164,4 +231,36 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< variablesBlock === '{}' ? `{ [key: string]: never; }` : variablesBlock }>${extraType}`; } + + private collectUsedInputTypes({ + schema, + documentNode, + }: { + schema: GraphQLSchema; + documentNode: DocumentNode; + }): UsedNamedInputTypes { + const schemaTypes = schema.getTypeMap(); + + const usedInputTypes: UsedNamedInputTypes = {}; + + visit(documentNode, { + VariableDefinition: variableDefinitionNode => { + visit(variableDefinitionNode, { + NamedType: namedTypeNode => { + const foundInputType = schemaTypes[namedTypeNode.name.value]; + if ( + foundInputType && + (foundInputType instanceof GraphQLInputObjectType || + foundInputType instanceof GraphQLScalarType || + foundInputType instanceof GraphQLEnumType) + ) { + usedInputTypes[namedTypeNode.name.value] = foundInputType; + } + }, + }); + }, + }); + + return usedInputTypes; + } } diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts index 50057f007c6..06dd1752443 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -37,6 +37,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { input UsersInput { from: DateTime to: DateTime + role: UserRole } type UsersResponseOk { @@ -69,8 +70,8 @@ describe('TypeScript Operations Plugin - Standalone', () => { } } - query UsersWithScalarInput($from: DateTime!, $to: DateTime) { - users(input: { from: $from, to: $to }) { + query UsersWithScalarInput($from: DateTime!, $to: DateTime, $role: UserRole) { + users(input: { from: $from, to: $to, role: $role }) { ... on UsersResponseOk { result { __typename @@ -87,6 +88,10 @@ describe('TypeScript Operations Plugin - Standalone', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type UserRole = + | 'ADMIN' + | 'CUSTOMER'; + export type UserQueryVariables = Exact<{ id: string; }>; @@ -107,6 +112,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { export type UsersWithScalarInputQueryVariables = Exact<{ from: any; to?: any | null; + role?: UserRole | null; }>; @@ -157,3 +163,13 @@ describe('TypeScript Operations Plugin - Standalone', () => { `); }); }); + +describe('TypeScript Operations Plugin - Enum', () => { + it.todo('does not generate unused enum in variables and result'); + it.todo('handles native numeric enum correctly'); + it.todo('handles const enum correctly'); + it.todo('handles native const enum correctly'); + it.todo('handles native enum correctly'); + it.todo('handles EnumValues correctly'); + // Bring over tests from https://github.com/dotansimha/graphql-code-generator/blob/accdab69106605241933e9d66d64dc7077656f30/packages/plugins/typescript/typescript/tests/typescript.spec.ts +}); From 92a0a562e0c01bd18aa6b3bd285f410a1973c0f3 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Thu, 4 Dec 2025 01:05:10 +1100 Subject: [PATCH 08/69] [typescript-operations] Add missing enum tests & fix enum generating logic for standalone approach (#10525) * Add tests for enum * Baselin tests * Ensure correctness of enumValues import * Split enum tests * Abstract import printing functions * Add missing enum tests * Format to minimise conflict * Add changeset --- .changeset/tidy-jobs-unite.md | 9 + .../src/base-types-visitor.ts | 87 +- .../visitor-plugin-common/src/imports.ts | 86 ++ .../typescript/operations/src/index.ts | 1 + .../typescript/operations/src/visitor.ts | 9 + .../ts-documents.standalone.enum.spec.ts | 1350 +++++++++++++++++ .../tests/ts-documents.standalone.spec.ts | 19 +- 7 files changed, 1487 insertions(+), 74 deletions(-) create mode 100644 .changeset/tidy-jobs-unite.md create mode 100644 packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts diff --git a/.changeset/tidy-jobs-unite.md b/.changeset/tidy-jobs-unite.md new file mode 100644 index 00000000000..c4eb57e9cd1 --- /dev/null +++ b/.changeset/tidy-jobs-unite.md @@ -0,0 +1,9 @@ +--- +'@graphql-codegen/visitor-plugin-common': patch +'@graphql-codegen/typescript-operations': patch +'@graphql-codegen/typescript': patch +'@graphql-codegen/typescript-resolvers': patch +'@graphql-codegen/client-preset': patch +--- + +Abstract how enum imports are generated into visitor-plugin-common package diff --git a/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts index 3a3cb290a01..536dc70adcd 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts @@ -20,6 +20,7 @@ import { BaseVisitor, ParsedConfig, RawConfig } from './base-visitor.js'; import { buildEnumValuesBlock } from './convert-schema-enum-to-declaration-block-string.js'; import { normalizeDeclarationKind } from './declaration-kinds.js'; import { parseEnumValues } from './enum-values.js'; +import { buildTypeImport, getEnumsImports } from './imports.js'; import { transformDirectiveArgumentAndInputFieldMappings } from './mappers.js'; import { DEFAULT_SCALARS } from './scalars.js'; import { @@ -562,21 +563,23 @@ export class BaseTypesVisitor< if (mappedValue.input.isExternal) { res.push( - this._buildTypeImport( - mappedValue.input.import, - mappedValue.input.source, - mappedValue.input.default, - ), + buildTypeImport({ + identifier: mappedValue.input.import, + source: mappedValue.input.source, + asDefault: mappedValue.input.default, + useTypeImports: this.config.useTypeImports, + }), ); } if (mappedValue.output.isExternal) { res.push( - this._buildTypeImport( - mappedValue.output.import, - mappedValue.output.source, - mappedValue.output.default, - ), + buildTypeImport({ + identifier: mappedValue.output.import, + source: mappedValue.output.source, + asDefault: mappedValue.output.default, + useTypeImports: this.config.useTypeImports, + }), ); } @@ -590,7 +593,12 @@ export class BaseTypesVisitor< const mappedValue = this.config.directiveArgumentAndInputFieldMappings[directive]; if (mappedValue.isExternal) { - return this._buildTypeImport(mappedValue.import, mappedValue.source, mappedValue.default); + return buildTypeImport({ + identifier: mappedValue.import, + source: mappedValue.source, + asDefault: mappedValue.default, + useTypeImports: this.config.useTypeImports, + }); } return null; @@ -856,60 +864,11 @@ export class BaseTypesVisitor< return ''; } - protected _buildTypeImport(identifier: string, source: string, asDefault = false): string { - const { useTypeImports } = this.config; - if (asDefault) { - if (useTypeImports) { - return `import type { default as ${identifier} } from '${source}';`; - } - return `import ${identifier} from '${source}';`; - } - return `import${useTypeImports ? ' type' : ''} { ${identifier} } from '${source}';`; - } - - protected handleEnumValueMapper( - typeIdentifier: string, - importIdentifier: string | null, - sourceIdentifier: string | null, - sourceFile: string | null, - ): string[] { - if (importIdentifier !== sourceIdentifier) { - // use namespace import to dereference nested enum - // { enumValues: { MyEnum: './my-file#NS.NestedEnum' } } - return [ - this._buildTypeImport(importIdentifier || sourceIdentifier, sourceFile), - `import ${typeIdentifier} = ${sourceIdentifier};`, - ]; - } - if (sourceIdentifier !== typeIdentifier) { - return [this._buildTypeImport(`${sourceIdentifier} as ${typeIdentifier}`, sourceFile)]; - } - return [this._buildTypeImport(importIdentifier || sourceIdentifier, sourceFile)]; - } - public getEnumsImports(): string[] { - return Object.keys(this.config.enumValues) - .flatMap(enumName => { - const mappedValue = this.config.enumValues[enumName]; - - if (mappedValue.sourceFile) { - if (mappedValue.isDefault) { - return [ - this._buildTypeImport(mappedValue.typeIdentifier, mappedValue.sourceFile, true), - ]; - } - - return this.handleEnumValueMapper( - mappedValue.typeIdentifier, - mappedValue.importIdentifier, - mappedValue.sourceIdentifier, - mappedValue.sourceFile, - ); - } - - return []; - }) - .filter(Boolean); + return getEnumsImports({ + enumValues: this.config.enumValues, + useTypeImports: this.config.useTypeImports, + }); } EnumTypeDefinition(node: EnumTypeDefinitionNode): string { diff --git a/packages/plugins/other/visitor-plugin-common/src/imports.ts b/packages/plugins/other/visitor-plugin-common/src/imports.ts index 7287975cedf..7ad9247d1fd 100644 --- a/packages/plugins/other/visitor-plugin-common/src/imports.ts +++ b/packages/plugins/other/visitor-plugin-common/src/imports.ts @@ -1,6 +1,7 @@ import { dirname, isAbsolute, join, relative, resolve } from 'path'; import parse from 'parse-filepath'; import { normalizeImportExtension } from '@graphql-codegen/plugin-helpers'; +import type { ParsedEnumValuesMap } from './types'; export type ImportDeclaration = { outputPath: string; @@ -105,3 +106,88 @@ export function clearExtension(path: string): string { export function fixLocalFilePath(path: string): string { return path.startsWith('..') ? path : `./${path}`; } + +export function getEnumsImports({ + enumValues, + useTypeImports, +}: { + enumValues: ParsedEnumValuesMap; + useTypeImports: boolean; +}): string[] { + function handleEnumValueMapper({ + typeIdentifier, + importIdentifier, + sourceIdentifier, + sourceFile, + useTypeImports, + }: { + typeIdentifier: string; + importIdentifier: string | null; + sourceIdentifier: string | null; + sourceFile: string | null; + useTypeImports: boolean; + }): string[] { + if (importIdentifier !== sourceIdentifier) { + // use namespace import to dereference nested enum + // { enumValues: { MyEnum: './my-file#NS.NestedEnum' } } + return [ + buildTypeImport({ identifier: importIdentifier || sourceIdentifier, source: sourceFile, useTypeImports }), + `import ${typeIdentifier} = ${sourceIdentifier};`, + ]; + } + if (sourceIdentifier !== typeIdentifier) { + return [ + buildTypeImport({ identifier: `${sourceIdentifier} as ${typeIdentifier}`, source: sourceFile, useTypeImports }), + ]; + } + return [buildTypeImport({ identifier: importIdentifier || sourceIdentifier, source: sourceFile, useTypeImports })]; + } + + return Object.keys(enumValues) + .flatMap(enumName => { + const mappedValue = enumValues[enumName]; + if (mappedValue.sourceFile) { + if (mappedValue.isDefault) { + return [ + buildTypeImport({ + identifier: mappedValue.typeIdentifier, + source: mappedValue.sourceFile, + asDefault: true, + useTypeImports, + }), + ]; + } + + return handleEnumValueMapper({ + typeIdentifier: mappedValue.typeIdentifier, + importIdentifier: mappedValue.importIdentifier, + sourceIdentifier: mappedValue.sourceIdentifier, + sourceFile: mappedValue.sourceFile, + useTypeImports, + }); + } + + return []; + }) + .filter(Boolean); +} + +export function buildTypeImport({ + identifier, + source, + useTypeImports, + asDefault = false, +}: { + identifier: string; + source: string; + useTypeImports: boolean; + asDefault?: boolean; +}): string { + if (asDefault) { + if (useTypeImports) { + return `import type { default as ${identifier} } from '${source}';`; + } + return `import ${identifier} from '${source}';`; + } + return `import${useTypeImports ? ' type' : ''} { ${identifier} } from '${source}';`; +} diff --git a/packages/plugins/typescript/operations/src/index.ts b/packages/plugins/typescript/operations/src/index.ts index 7e3705fdfbf..fd976d26cb4 100644 --- a/packages/plugins/typescript/operations/src/index.ts +++ b/packages/plugins/typescript/operations/src/index.ts @@ -101,6 +101,7 @@ export const plugin: PluginFunction< return { prepend: [ ...visitor.getImports(), + ...visitor.getEnumsImports(), ...visitor.getGlobalDeclarations(visitor.config.noExport), 'type Exact = { [K in keyof T]: T[K] };', ], diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 1164d7dd4ab..081e764cbe1 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -21,6 +21,7 @@ import { DeclarationKind, generateFragmentImportStatement, getConfigValue, + getEnumsImports, LoadedFragment, normalizeAvoidOptionals, NormalizedAvoidOptionalsConfig, @@ -181,6 +182,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< ); this._declarationBlockConfig = { ignoreExport: this.config.noExport, + enumNameValueSeparator: ' =', }; } @@ -263,4 +265,11 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< return usedInputTypes; } + + public getEnumsImports(): string[] { + return getEnumsImports({ + enumValues: this.config.enumValues, + useTypeImports: this.config.useTypeImports, + }); + } } diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts new file mode 100644 index 00000000000..b00857d7364 --- /dev/null +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts @@ -0,0 +1,1350 @@ +import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; +import { validateTs } from '@graphql-codegen/testing'; +import { buildSchema, parse } from 'graphql'; +import { plugin } from '../src/index.js'; + +describe('TypeScript Operations Plugin - Enum', () => { + it('does not generate enums if not used in variables and result', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query Me { + me { + id + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], {})]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type MeQueryVariables = Exact<{ [key: string]: never; }>; + + + export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('handles `native-numeric` enum', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native-numeric' })]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export enum UserRole { + Admin = 0, + Customer = 1 + } + + export type MeQueryVariables = Exact<{ + role: UserRole; + }>; + + + export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('handles `const` enum', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + A_B_C + X_Y_Z + _TEST + My_Value + _123 + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'const' })]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export const UserRole = { + ABC: 'A_B_C', + XYZ: 'X_Y_Z', + Test: '_TEST', + MyValue: 'My_Value', + '123': '_123' + } as const; + + export type UserRole = typeof UserRole[keyof typeof UserRole]; + export type MeQueryVariables = Exact<{ + role: UserRole; + }>; + + + export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('handles `native-const` enum', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + """ + Multiline comment test + """ + enum UserRole { + ADMIN + CUSTOMER @deprecated(reason: "Enum value CUSTOMER has been deprecated.") + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native-const' })]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + /** Multiline comment test */ + export const enum UserRole { + Admin = 'ADMIN', + /** @deprecated Enum value CUSTOMER has been deprecated. */ + Customer = 'CUSTOMER' + }; + + export type MeQueryVariables = Exact<{ + role: UserRole; + }>; + + + export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('handles `native` enum', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' })]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export enum UserRole { + Admin = 'ADMIN', + Customer = 'CUSTOMER' + } + + export type MeQueryVariables = Exact<{ + role: UserRole; + }>; + + + export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('handles `enumValues` with `string-literal` enum', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + A_B_C + X_Y_Z + _TEST + My_Value + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([ + await plugin(schema, [{ document }], { + enumType: 'string-literal', + enumValues: { + UserRole: { + A_B_C: 0, + X_Y_Z: 'Foo', + _TEST: 'Bar', + My_Value: 1, + }, + }, + }), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type UserRole = + | 0 + | 'Foo' + | 'Bar' + | 1; + + export type MeQueryVariables = Exact<{ + role: UserRole; + }>; + + + export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('handles `enumValues` with `const` enum', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + A_B_C + X_Y_Z + _TEST + My_Value + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([ + await plugin(schema, [{ document }], { + enumType: 'const', + enumValues: { + UserRole: { + A_B_C: 0, + X_Y_Z: 'Foo', + _TEST: 'Bar', + My_Value: 1, + }, + }, + }), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export const UserRole = { + ABC: 0, + XYZ: 'Foo', + Test: 'Bar', + MyValue: 1 + } as const; + + export type UserRole = typeof UserRole[keyof typeof UserRole]; + export type MeQueryVariables = Exact<{ + role: UserRole; + }>; + + + export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('handles `enumValues` with `native` enum', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([ + await plugin(schema, [{ document }], { + enumType: 'native', + enumValues: { + UserRole: { + ADMIN: 0, + CUSTOMER: 'test', + }, + }, + }), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export enum UserRole { + Admin = 0, + Customer = 'test' + } + + export type MeQueryVariables = Exact<{ + role: UserRole; + }>; + + + export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('handles `enumValues` as file import', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + scalar DateTime + `); + + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([ + await plugin(schema, [{ document }], { + enumValues: { + UserRole: './my-file#MyEnum', + }, + }), + ]); + + expect(result).toMatchInlineSnapshot(` + "import { MyEnum as UserRole } from './my-file'; + type Exact = { [K in keyof T]: T[K] }; + export { UserRole }; + + export type MeQueryVariables = Exact<{ + role: UserRole; + }>; + + + export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('handles `enumValues` with custom imported enum from namespace with different name', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + scalar DateTime + `); + + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([ + await plugin(schema, [{ document }], { + enumValues: { + UserRole: './my-file#NS.ETest', + }, + }), + ]); + + expect(result).toMatchInlineSnapshot(` + "import { NS } from './my-file'; + import UserRole = NS.ETest; + type Exact = { [K in keyof T]: T[K] }; + export { UserRole }; + + export type MeQueryVariables = Exact<{ + role: UserRole; + }>; + + + export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('handles `enumValues` with custom imported enum from namespace with the same name', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + scalar DateTime + `); + + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([ + await plugin(schema, [{ document }], { + enumValues: { + UserRole: './my-file#NS.UserRole', + }, + }), + ]); + + expect(result).toMatchInlineSnapshot(` + "import { NS } from './my-file'; + import UserRole = NS.UserRole; + type Exact = { [K in keyof T]: T[K] }; + export { UserRole }; + + export type MeQueryVariables = Exact<{ + role: UserRole; + }>; + + + export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('handles `enumValues` from a single file', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + enum UserStatus { + ACTIVE + PENDING + } + + scalar DateTime + `); + + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!, $status: UserStatus!) { + me { + id + } + } + `); + + const result = mergeOutputs([ + await plugin(schema, [{ document }], { + enumType: 'native', + enumValues: './my-file', + }), + ]); + + expect(result).toMatchInlineSnapshot(` + "import { UserRole } from './my-file'; + import { UserStatus } from './my-file'; + type Exact = { [K in keyof T]: T[K] }; + export { UserRole }; + + export { UserStatus }; + + export type MeQueryVariables = Exact<{ + role: UserRole; + status: UserStatus; + }>; + + + export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('handles `enumValues` from a single file when specified as string', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + enum UserStatus { + ACTIVE + PENDING + } + + scalar DateTime + `); + + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!, $status: UserStatus!) { + me { + id + } + } + `); + + const result = mergeOutputs([ + await plugin(schema, [{ document }], { + enumType: 'native', + enumValues: { UserRole: './my-file#UserRole', UserStatus: './my-file#UserStatus2X' }, + }), + ]); + + expect(result).toMatchInlineSnapshot(` + "import { UserRole } from './my-file'; + import { UserStatus2X as UserStatus } from './my-file'; + type Exact = { [K in keyof T]: T[K] }; + export { UserRole }; + + export { UserStatus }; + + export type MeQueryVariables = Exact<{ + role: UserRole; + status: UserStatus; + }>; + + + export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('removes underscore from enum values', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + A_B_C + X_Y_Z + _TEST + My_Value + } + + scalar DateTime + `); + + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' })]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export enum UserRole { + ABC = 'A_B_C', + XYZ = 'X_Y_Z', + Test = '_TEST', + MyValue = 'My_Value' + } + + export type MeQueryVariables = Exact<{ + role: UserRole; + }>; + + + export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('keeps underscores in enum values when the value is only underscores', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + _ + __ + _TEST + } + + scalar DateTime + `); + + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' })]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export enum UserRole { + _ = '_', + __ = '__', + Test = '_TEST' + } + + export type MeQueryVariables = Exact<{ + role: UserRole; + }>; + + + export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('adds typesPrefix to enum when enumPrefix is true', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + scalar DateTime + `); + + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], { typesPrefix: 'I', enumPrefix: true })]); + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type IUserRole = + | 'ADMIN' + | 'CUSTOMER'; + + export type IMeQueryVariables = Exact<{ + role: IUserRole; + }>; + + + export type IMeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('does not add typesPrefix to enum when enumPrefix is false', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + scalar DateTime + `); + + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], { typesPrefix: 'I', enumPrefix: false })]); + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type UserRole = + | 'ADMIN' + | 'CUSTOMER'; + + export type IMeQueryVariables = Exact<{ + role: UserRole; + }>; + + + export type IMeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('adds typesSuffix to enum when enumSuffix is true', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + scalar DateTime + `); + + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], { typesSuffix: 'Z', enumSuffix: true })]); + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type UserRoleZ = + | 'ADMIN' + | 'CUSTOMER'; + + export type MeQueryVariablesZ = Exact<{ + role: UserRoleZ; + }>; + + + export type MeQueryZ = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('does not add typesSuffix to enum when enumSuffix is false', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + scalar DateTime + `); + + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], { typesSuffix: 'Z', enumSuffix: false })]); + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type UserRole = + | 'ADMIN' + | 'CUSTOMER'; + + export type MeQueryVariablesZ = Exact<{ + role: UserRole; + }>; + + + export type MeQueryZ = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('keeps enum value naming convention when namingConvention.enumValues is `keep`', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + scalar DateTime + `); + + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([ + await plugin(schema, [{ document }], { + namingConvention: { + typeNames: 'change-case-all#lowerCase', + enumValues: 'keep', + }, + }), + ]); + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type userrole = + | 'ADMIN' + | 'CUSTOMER'; + + export type mequeryvariables = Exact<{ + role: userrole; + }>; + + + export type mequery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('uses custom enum naming convention when namingConvention.enumValues is provided and enumType is native', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + scalar DateTime + `); + + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([ + await plugin(schema, [{ document }], { + enumType: 'native', + namingConvention: { + typeNames: 'keep', + enumValues: 'change-case-all#lowerCase', + }, + }), + ]); + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export enum UserRole { + admin = 'ADMIN', + customer = 'CUSTOMER' + } + + export type MeQueryVariables = Exact<{ + role: UserRole; + }>; + + + export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('does not contain "export" when noExport is set to true', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + scalar DateTime + `); + + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([ + await plugin(schema, [{ document }], { + noExport: true, + }), + ]); + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + type UserRole = + | 'ADMIN' + | 'CUSTOMER'; + + type MeQueryVariables = Exact<{ + role: UserRole; + }>; + + + type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('handles enumValues and named default import', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + scalar DateTime + `); + + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([ + await plugin(schema, [{ document }], { + typesPrefix: 'I', + namingConvention: { enumValues: 'change-case-all#constantCase' }, + enumValues: { + UserRole: './files#default as UserRole', + }, + }), + ]); + + expect(result).toMatchInlineSnapshot(` + "import UserRole from './files'; + type Exact = { [K in keyof T]: T[K] }; + export { UserRole }; + + export type IMeQueryVariables = Exact<{ + role: UserRole; + }>; + + + export type IMeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + }); + + it('enum members should be quoted if numeric when enumType is native', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + AXB + _1X2 + _3X4 + } + + scalar DateTime + `); + + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' })]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export enum UserRole { + Axb = 'AXB', + '1X2' = '_1X2', + '3X4' = '_3X4' + } + + export type MeQueryVariables = Exact<{ + role: UserRole; + }>; + + + export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + }); +}); + +describe('TypeScript Operations Plugin - Enum `%future added value`', () => { + it('adds `%future added value` to the type when enumType is `string-literal` and futureProofEnums is true', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query Me($role: UserRole!) { + me { + id + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], { futureProofEnums: true })]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type UserRole = + | 'ADMIN' + | 'CUSTOMER' + | '%future added value'; + + export type MeQueryVariables = Exact<{ + role: UserRole; + }>; + + + export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); +}); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts index 06dd1752443..f3106cf72a1 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -29,13 +29,19 @@ describe('TypeScript Operations Plugin - Standalone', () => { createdAt: DateTime! } + "UserRole Description" enum UserRole { + "UserRole ADMIN" ADMIN + "UserRole CUSTOMER" CUSTOMER } + "UsersInput Description" input UsersInput { + "UsersInput from" from: DateTime + "UsersInput to" to: DateTime role: UserRole } @@ -88,8 +94,11 @@ describe('TypeScript Operations Plugin - Standalone', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + /** UserRole Description */ export type UserRole = + /** UserRole ADMIN */ | 'ADMIN' + /** UserRole CUSTOMER */ | 'CUSTOMER'; export type UserQueryVariables = Exact<{ @@ -163,13 +172,3 @@ describe('TypeScript Operations Plugin - Standalone', () => { `); }); }); - -describe('TypeScript Operations Plugin - Enum', () => { - it.todo('does not generate unused enum in variables and result'); - it.todo('handles native numeric enum correctly'); - it.todo('handles const enum correctly'); - it.todo('handles native const enum correctly'); - it.todo('handles native enum correctly'); - it.todo('handles EnumValues correctly'); - // Bring over tests from https://github.com/dotansimha/graphql-code-generator/blob/accdab69106605241933e9d66d64dc7077656f30/packages/plugins/typescript/typescript/tests/typescript.spec.ts -}); From 56c2be512e5f4746ae57887f99d58599e21638e6 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Fri, 5 Dec 2025 00:08:40 +1100 Subject: [PATCH 09/69] Add generatesOperationTypes config option to generate shared types only (#10529) --- .changeset/proud-jobs-decide.md | 6 + .../src/base-documents-visitor.ts | 35 ++++- .../typescript/operations/src/index.ts | 2 +- .../typescript/operations/src/visitor.ts | 8 ++ .../tests/ts-documents.standalone.spec.ts | 130 +++++++++++++++++- 5 files changed, 178 insertions(+), 3 deletions(-) create mode 100644 .changeset/proud-jobs-decide.md diff --git a/.changeset/proud-jobs-decide.md b/.changeset/proud-jobs-decide.md new file mode 100644 index 00000000000..36c3a298ac4 --- /dev/null +++ b/.changeset/proud-jobs-decide.md @@ -0,0 +1,6 @@ +--- +'@graphql-codegen/visitor-plugin-common': minor +'@graphql-codegen/typescript-operations': minor +--- + +Add generatesOperationTypes to typescript-operations to allow omitting operation types such as Variables, Query/Mutation/Subscription selection set, and Fragment types diff --git a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts index a7972d6fb96..abe64383e52 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts @@ -46,6 +46,7 @@ export interface ParsedDocumentsConfig extends ParsedTypesConfig { experimentalFragmentVariables: boolean; mergeFragmentTypes: boolean; customDirectives: CustomDirectivesConfig; + generatesOperationTypes: boolean; } export interface RawDocumentsConfig extends RawTypesConfig { @@ -180,6 +181,29 @@ export interface RawDocumentsConfig extends RawTypesConfig { * ``` */ customDirectives?: CustomDirectivesConfig; + + /** + * @description Whether to generate operation types such as Variables, Query/Mutation/Subscription selection set, and Fragment types + * @default true + * @exampleMarkdown + * ```ts filename="codegen.ts" + * import type { CodegenConfig } from '@graphql-codegen/cli'; + * + * const config: CodegenConfig = { + * // ... + * generates: { + * 'path/to/file.ts': { + * plugins: ['typescript-operations'], + * config: { + * generatesOperationTypes: false, + * }, + * }, + * }, + * }; + * export default config; + * ``` + */ + generatesOperationTypes?: boolean; } export class BaseDocumentsVisitor< @@ -214,6 +238,7 @@ export class BaseDocumentsVisitor< customDirectives: getConfigValue(rawConfig.customDirectives, { apolloUnmask: false, }), + generatesOperationTypes: getConfigValue(rawConfig.generatesOperationTypes, true), ...((additionalConfig || {}) as any), }); @@ -268,6 +293,10 @@ export class BaseDocumentsVisitor< } FragmentDefinition(node: FragmentDefinitionNode): string { + if (!this.config.generatesOperationTypes) { + return null; + } + const fragmentRootType = this._schema.getType(node.typeCondition.name.value); const selectionSet = this._selectionSetToObject.createNext(fragmentRootType, node.selectionSet); const fragmentSuffix = this.getFragmentSuffix(node); @@ -300,7 +329,11 @@ export class BaseDocumentsVisitor< return variablesBlock; } - OperationDefinition(node: OperationDefinitionNode): string { + OperationDefinition(node: OperationDefinitionNode): string | null { + if (!this.config.generatesOperationTypes) { + return null; + } + const name = this.handleAnonymousOperation(node); const operationRootType = getRootType(node.operation, this._schema); diff --git a/packages/plugins/typescript/operations/src/index.ts b/packages/plugins/typescript/operations/src/index.ts index fd976d26cb4..272da57712b 100644 --- a/packages/plugins/typescript/operations/src/index.ts +++ b/packages/plugins/typescript/operations/src/index.ts @@ -103,7 +103,7 @@ export const plugin: PluginFunction< ...visitor.getImports(), ...visitor.getEnumsImports(), ...visitor.getGlobalDeclarations(visitor.config.noExport), - 'type Exact = { [K in keyof T]: T[K] };', + visitor.getExactUtilityType(), ], content, }; diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 081e764cbe1..83f607de948 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -272,4 +272,12 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< useTypeImports: this.config.useTypeImports, }); } + + getExactUtilityType(): string | null { + if (!this.config.generatesOperationTypes) { + return null; + } + + return 'type Exact = { [K in keyof T]: T[K] };'; + } } diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts index f3106cf72a1..2f1cb9a5485 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -1,5 +1,5 @@ import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; -// import { validateTs } from '@graphql-codegen/testing'; +import { validateTs } from '@graphql-codegen/testing'; import { buildSchema, parse } from 'graphql'; import { plugin } from '../src/index.js'; @@ -171,4 +171,132 @@ describe('TypeScript Operations Plugin - Standalone', () => { " `); }); + + it('does not generate Variables, Result or Fragments when generatesOperationTypes is false', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + users(input: UsersInput!): UsersResponse! + } + + type Mutation { + makeUserAdmin(id: ID!): User! + } + + type Subscription { + userChanges(id: ID!): User! + } + + type ResponseError { + error: ResponseErrorType! + } + + enum ResponseErrorType { + NOT_FOUND + INPUT_VALIDATION_ERROR + FORBIDDEN_ERROR + UNEXPECTED_ERROR + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + "UserRole Description" + enum UserRole { + "UserRole ADMIN" + ADMIN + "UserRole CUSTOMER" + CUSTOMER + } + + "UsersInput Description" + input UsersInput { + "UsersInput from" + from: DateTime + "UsersInput to" + to: DateTime + role: UserRole + } + + type UsersResponseOk { + result: [User!]! + } + union UsersResponse = UsersResponseOk | ResponseError + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User($id: ID!) { + user(id: $id) { + id + name + role + createdAt + } + } + + query Users($input: UsersInput!) { + users(input: $input) { + ... on UsersResponseOk { + result { + ...UserFragment + } + } + ... on ResponseError { + error + } + } + } + + query UsersWithScalarInput($from: DateTime!, $to: DateTime, $role: UserRole) { + users(input: { from: $from, to: $to, role: $role }) { + ... on UsersResponseOk { + result { + __typename + } + } + ... on ResponseError { + __typename + } + } + } + + mutation MakeAdmin { + makeUserAdmin(id: "100") { + ...UserFragment + } + } + + subscription UserChanges { + makeUserAdmin(id: "100") { + ...UserFragment + } + } + + fragment UserFragment on User { + id + role + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], { generatesOperationTypes: false })]); + + expect(result).toMatchInlineSnapshot(` + " + /** UserRole Description */ + export type UserRole = + /** UserRole ADMIN */ + | 'ADMIN' + /** UserRole CUSTOMER */ + | 'CUSTOMER'; + + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); }); From 72451550a49e2a5e985b0409317c077bd41741a7 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Tue, 9 Dec 2025 00:56:10 +1100 Subject: [PATCH 10/69] [typescript-operations] Add importSchemaTypesFrom to import user-defined+used input/enum types externally (#10534) * Draft importSchemaTypesFrom * Minor test fixes * Fix test name * Update dev-tests * Baseline dev-test for importSchemaTypesFrom * Implement relative import paths correctly * Update tests to handle outputDir correctly * Add test for absolute importSchemaTypesFrom * Remove unncessary files * Add test about unused things * Remove comment * Add comments * Add changeset --- .changeset/clever-loops-crash.md | 6 + dev-test/codegen.ts | 20 + dev-test/githunt/typed-document-nodes.ts | 12 - dev-test/githunt/types.avoidOptionals.ts | 12 - dev-test/githunt/types.d.ts | 12 - dev-test/githunt/types.enumsAsTypes.ts | 12 - .../githunt/types.flatten.preResolveTypes.ts | 12 - dev-test/githunt/types.immutableTypes.ts | 12 - ...ypes.preResolveTypes.onlyOperationTypes.ts | 12 - dev-test/githunt/types.preResolveTypes.ts | 12 - dev-test/githunt/types.ts | 12 - .../import-schema-types/_base.generated.ts | 6 + .../import-schema-types/_types.generated.ts | 11 + .../import-schema-types/query.graphql | 6 + dev-test/standalone-operations/schema.graphql | 17 + dev-test/star-wars/types.avoidOptionals.ts | 9 - dev-test/star-wars/types.excludeQueryAlpha.ts | 9 - dev-test/star-wars/types.excludeQueryBeta.ts | 9 - .../star-wars/types.globallyAvailable.d.ts | 9 - dev-test/star-wars/types.immutableTypes.ts | 9 - ...ypes.preResolveTypes.onlyOperationTypes.ts | 9 - dev-test/star-wars/types.preResolveTypes.ts | 9 - dev-test/star-wars/types.skipSchema.ts | 9 - dev-test/star-wars/types.ts | 9 - .../src/base-documents-visitor.ts | 27 ++ .../src/graphql-type-utils.ts | 13 + .../other/visitor-plugin-common/src/index.ts | 1 + .../typescript/operations/src/index.ts | 9 +- .../typescript/operations/src/visitor.ts | 44 ++- .../__snapshots__/ts-documents.spec.ts.snap | 2 +- .../tests/ts-documents.nullability.spec.ts | 26 +- .../ts-documents.standalone.enum.spec.ts | 228 +++++++---- ...-documents.standalone.import-types.spec.ts | 371 ++++++++++++++++++ .../tests/ts-documents.standalone.spec.ts | 85 +++- 34 files changed, 770 insertions(+), 291 deletions(-) create mode 100644 .changeset/clever-loops-crash.md create mode 100644 dev-test/standalone-operations/import-schema-types/_base.generated.ts create mode 100644 dev-test/standalone-operations/import-schema-types/_types.generated.ts create mode 100644 dev-test/standalone-operations/import-schema-types/query.graphql create mode 100644 dev-test/standalone-operations/schema.graphql create mode 100644 packages/plugins/other/visitor-plugin-common/src/graphql-type-utils.ts create mode 100644 packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts diff --git a/.changeset/clever-loops-crash.md b/.changeset/clever-loops-crash.md new file mode 100644 index 00000000000..c28b7d69057 --- /dev/null +++ b/.changeset/clever-loops-crash.md @@ -0,0 +1,6 @@ +--- +'@graphql-codegen/visitor-plugin-common': minor +'@graphql-codegen/typescript-operations': minor +--- + +Add importSchemaTypesFrom support diff --git a/dev-test/codegen.ts b/dev-test/codegen.ts index 0e8fa26cc2b..aa9ab6104dc 100644 --- a/dev-test/codegen.ts +++ b/dev-test/codegen.ts @@ -273,6 +273,26 @@ const config: CodegenConfig = { plugins: ['typescript-operations'], }, // #endregion + + // standalone-operations + './dev-test/standalone-operations/import-schema-types/_base.generated.ts': { + schema: './dev-test/standalone-operations/schema.graphql', + documents: ['./dev-test/standalone-operations/import-schema-types/*.graphql'], + plugins: ['typescript-operations'], + config: { + generatesOperationTypes: false, + }, + }, + './dev-test/standalone-operations/import-schema-types/_types.generated.ts': { + schema: './dev-test/standalone-operations/schema.graphql', + documents: ['./dev-test/standalone-operations/import-schema-types/*.graphql'], + plugins: ['typescript-operations'], + config: { + importSchemaTypesFrom: + './dev-test/standalone-operations/import-schema-types/_base.generated.ts', + namespacedImportName: 'Types', + }, + }, }, }; diff --git a/dev-test/githunt/typed-document-nodes.ts b/dev-test/githunt/typed-document-nodes.ts index ae4afad33b9..9ca29efb843 100644 --- a/dev-test/githunt/typed-document-nodes.ts +++ b/dev-test/githunt/typed-document-nodes.ts @@ -174,18 +174,6 @@ export enum VoteType { Up = 'UP', } -/** A list of options for the sort order of the feed */ -export type FeedType = - /** Sort by a combination of freshness and score, using Reddit's algorithm */ - | 'HOT' - /** Newest entries first */ - | 'NEW' - /** Highest score entries first */ - | 'TOP'; - -/** The type of vote to record, when submitting a vote */ -export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; - export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.avoidOptionals.ts b/dev-test/githunt/types.avoidOptionals.ts index dc858460296..0612dfd6890 100644 --- a/dev-test/githunt/types.avoidOptionals.ts +++ b/dev-test/githunt/types.avoidOptionals.ts @@ -172,18 +172,6 @@ export enum VoteType { Up = 'UP', } -/** A list of options for the sort order of the feed */ -export type FeedType = - /** Sort by a combination of freshness and score, using Reddit's algorithm */ - | 'HOT' - /** Newest entries first */ - | 'NEW' - /** Highest score entries first */ - | 'TOP'; - -/** The type of vote to record, when submitting a vote */ -export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; - export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.d.ts b/dev-test/githunt/types.d.ts index 3da7a693cf2..3e669417bac 100644 --- a/dev-test/githunt/types.d.ts +++ b/dev-test/githunt/types.d.ts @@ -167,18 +167,6 @@ export type Vote = { /** The type of vote to record, when submitting a vote */ export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; -/** A list of options for the sort order of the feed */ -export type FeedType = - /** Sort by a combination of freshness and score, using Reddit's algorithm */ - | 'HOT' - /** Newest entries first */ - | 'NEW' - /** Highest score entries first */ - | 'TOP'; - -/** The type of vote to record, when submitting a vote */ -export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; - export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.enumsAsTypes.ts b/dev-test/githunt/types.enumsAsTypes.ts index 3da7a693cf2..3e669417bac 100644 --- a/dev-test/githunt/types.enumsAsTypes.ts +++ b/dev-test/githunt/types.enumsAsTypes.ts @@ -167,18 +167,6 @@ export type Vote = { /** The type of vote to record, when submitting a vote */ export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; -/** A list of options for the sort order of the feed */ -export type FeedType = - /** Sort by a combination of freshness and score, using Reddit's algorithm */ - | 'HOT' - /** Newest entries first */ - | 'NEW' - /** Highest score entries first */ - | 'TOP'; - -/** The type of vote to record, when submitting a vote */ -export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; - export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.flatten.preResolveTypes.ts b/dev-test/githunt/types.flatten.preResolveTypes.ts index bad10699b35..48e7f922615 100644 --- a/dev-test/githunt/types.flatten.preResolveTypes.ts +++ b/dev-test/githunt/types.flatten.preResolveTypes.ts @@ -172,18 +172,6 @@ export enum VoteType { Up = 'UP', } -/** A list of options for the sort order of the feed */ -export type FeedType = - /** Sort by a combination of freshness and score, using Reddit's algorithm */ - | 'HOT' - /** Newest entries first */ - | 'NEW' - /** Highest score entries first */ - | 'TOP'; - -/** The type of vote to record, when submitting a vote */ -export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; - export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.immutableTypes.ts b/dev-test/githunt/types.immutableTypes.ts index 8ad47a574a7..15205c69630 100644 --- a/dev-test/githunt/types.immutableTypes.ts +++ b/dev-test/githunt/types.immutableTypes.ts @@ -172,18 +172,6 @@ export enum VoteType { Up = 'UP', } -/** A list of options for the sort order of the feed */ -export type FeedType = - /** Sort by a combination of freshness and score, using Reddit's algorithm */ - | 'HOT' - /** Newest entries first */ - | 'NEW' - /** Highest score entries first */ - | 'TOP'; - -/** The type of vote to record, when submitting a vote */ -export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; - export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts index 12e97f9c499..f83e95365e0 100644 --- a/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts @@ -35,18 +35,6 @@ export enum VoteType { Up = 'UP', } -/** A list of options for the sort order of the feed */ -export type FeedType = - /** Sort by a combination of freshness and score, using Reddit's algorithm */ - | 'HOT' - /** Newest entries first */ - | 'NEW' - /** Highest score entries first */ - | 'TOP'; - -/** The type of vote to record, when submitting a vote */ -export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; - export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.preResolveTypes.ts b/dev-test/githunt/types.preResolveTypes.ts index 74b2740044d..7c7f591cd75 100644 --- a/dev-test/githunt/types.preResolveTypes.ts +++ b/dev-test/githunt/types.preResolveTypes.ts @@ -172,18 +172,6 @@ export enum VoteType { Up = 'UP', } -/** A list of options for the sort order of the feed */ -export type FeedType = - /** Sort by a combination of freshness and score, using Reddit's algorithm */ - | 'HOT' - /** Newest entries first */ - | 'NEW' - /** Highest score entries first */ - | 'TOP'; - -/** The type of vote to record, when submitting a vote */ -export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; - export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.ts b/dev-test/githunt/types.ts index 74b2740044d..7c7f591cd75 100644 --- a/dev-test/githunt/types.ts +++ b/dev-test/githunt/types.ts @@ -172,18 +172,6 @@ export enum VoteType { Up = 'UP', } -/** A list of options for the sort order of the feed */ -export type FeedType = - /** Sort by a combination of freshness and score, using Reddit's algorithm */ - | 'HOT' - /** Newest entries first */ - | 'NEW' - /** Highest score entries first */ - | 'TOP'; - -/** The type of vote to record, when submitting a vote */ -export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; - export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/standalone-operations/import-schema-types/_base.generated.ts b/dev-test/standalone-operations/import-schema-types/_base.generated.ts new file mode 100644 index 00000000000..8df53ac5f67 --- /dev/null +++ b/dev-test/standalone-operations/import-schema-types/_base.generated.ts @@ -0,0 +1,6 @@ +/** UserRole Description */ +export type UserRole = + /** UserRole ADMIN */ + | 'ADMIN' + /** UserRole CUSTOMER */ + | 'CUSTOMER'; diff --git a/dev-test/standalone-operations/import-schema-types/_types.generated.ts b/dev-test/standalone-operations/import-schema-types/_types.generated.ts new file mode 100644 index 00000000000..f51c326a287 --- /dev/null +++ b/dev-test/standalone-operations/import-schema-types/_types.generated.ts @@ -0,0 +1,11 @@ +import type * as Types from './_base.generated'; + +type Exact = { [K in keyof T]: T[K] }; +export type WithVariablesQueryVariables = Exact<{ + role?: Types.UserRole | null; +}>; + +export type WithVariablesQuery = { + __typename?: 'Query'; + user?: { __typename?: 'User'; id: string; name: string } | null; +}; diff --git a/dev-test/standalone-operations/import-schema-types/query.graphql b/dev-test/standalone-operations/import-schema-types/query.graphql new file mode 100644 index 00000000000..e8de0b4506d --- /dev/null +++ b/dev-test/standalone-operations/import-schema-types/query.graphql @@ -0,0 +1,6 @@ +query WithVariables($role: UserRole) { + user(id: "100") { + id + name + } +} diff --git a/dev-test/standalone-operations/schema.graphql b/dev-test/standalone-operations/schema.graphql new file mode 100644 index 00000000000..2fd2cb04bc6 --- /dev/null +++ b/dev-test/standalone-operations/schema.graphql @@ -0,0 +1,17 @@ +type Query { + user(id: ID!, role: UserRole): User +} + +type User { + id: ID! + name: String! + role: UserRole! +} + +"UserRole Description" +enum UserRole { + "UserRole ADMIN" + ADMIN + "UserRole CUSTOMER" + CUSTOMER +} diff --git a/dev-test/star-wars/types.avoidOptionals.ts b/dev-test/star-wars/types.avoidOptionals.ts index a95a43c2d9f..8a218f79265 100644 --- a/dev-test/star-wars/types.avoidOptionals.ts +++ b/dev-test/star-wars/types.avoidOptionals.ts @@ -244,15 +244,6 @@ export type StarshipLengthArgs = { unit?: InputMaybe; }; -/** The episodes in the Star Wars trilogy */ -export type Episode = - /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ - | 'EMPIRE' - /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ - | 'JEDI' - /** Star Wars Episode IV: A New Hope, released in 1977. */ - | 'NEWHOPE'; - export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.excludeQueryAlpha.ts b/dev-test/star-wars/types.excludeQueryAlpha.ts index 9dd975c83e7..063e31c3a00 100644 --- a/dev-test/star-wars/types.excludeQueryAlpha.ts +++ b/dev-test/star-wars/types.excludeQueryAlpha.ts @@ -244,15 +244,6 @@ export type StarshipLengthArgs = { unit?: InputMaybe; }; -/** The episodes in the Star Wars trilogy */ -export type Episode = - /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ - | 'EMPIRE' - /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ - | 'JEDI' - /** Star Wars Episode IV: A New Hope, released in 1977. */ - | 'NEWHOPE'; - export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.excludeQueryBeta.ts b/dev-test/star-wars/types.excludeQueryBeta.ts index 82abe1489d1..3ea8a6c5617 100644 --- a/dev-test/star-wars/types.excludeQueryBeta.ts +++ b/dev-test/star-wars/types.excludeQueryBeta.ts @@ -244,15 +244,6 @@ export type StarshipLengthArgs = { unit?: InputMaybe; }; -/** The episodes in the Star Wars trilogy */ -export type Episode = - /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ - | 'EMPIRE' - /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ - | 'JEDI' - /** Star Wars Episode IV: A New Hope, released in 1977. */ - | 'NEWHOPE'; - export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.globallyAvailable.d.ts b/dev-test/star-wars/types.globallyAvailable.d.ts index 54fee1cf66e..7cdcb977a14 100644 --- a/dev-test/star-wars/types.globallyAvailable.d.ts +++ b/dev-test/star-wars/types.globallyAvailable.d.ts @@ -240,15 +240,6 @@ type StarshipLengthArgs = { unit?: InputMaybe; }; -/** The episodes in the Star Wars trilogy */ -type Episode = - /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ - | 'EMPIRE' - /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ - | 'JEDI' - /** Star Wars Episode IV: A New Hope, released in 1977. */ - | 'NEWHOPE'; - type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.immutableTypes.ts b/dev-test/star-wars/types.immutableTypes.ts index d052e77ce91..a5d194d5c0b 100644 --- a/dev-test/star-wars/types.immutableTypes.ts +++ b/dev-test/star-wars/types.immutableTypes.ts @@ -244,15 +244,6 @@ export type StarshipLengthArgs = { unit?: InputMaybe; }; -/** The episodes in the Star Wars trilogy */ -export type Episode = - /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ - | 'EMPIRE' - /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ - | 'JEDI' - /** Star Wars Episode IV: A New Hope, released in 1977. */ - | 'NEWHOPE'; - export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts index 7cc36a1451e..6f844783949 100644 --- a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts @@ -53,15 +53,6 @@ export type ReviewInput = { stars: Scalars['Int']['input']; }; -/** The episodes in the Star Wars trilogy */ -export type Episode = - /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ - | 'EMPIRE' - /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ - | 'JEDI' - /** Star Wars Episode IV: A New Hope, released in 1977. */ - | 'NEWHOPE'; - export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.preResolveTypes.ts b/dev-test/star-wars/types.preResolveTypes.ts index 2d8f0be51e8..e3d32fb9e2e 100644 --- a/dev-test/star-wars/types.preResolveTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.ts @@ -244,15 +244,6 @@ export type StarshipLengthArgs = { unit?: InputMaybe; }; -/** The episodes in the Star Wars trilogy */ -export type Episode = - /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ - | 'EMPIRE' - /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ - | 'JEDI' - /** Star Wars Episode IV: A New Hope, released in 1977. */ - | 'NEWHOPE'; - export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.skipSchema.ts b/dev-test/star-wars/types.skipSchema.ts index 2d8f0be51e8..e3d32fb9e2e 100644 --- a/dev-test/star-wars/types.skipSchema.ts +++ b/dev-test/star-wars/types.skipSchema.ts @@ -244,15 +244,6 @@ export type StarshipLengthArgs = { unit?: InputMaybe; }; -/** The episodes in the Star Wars trilogy */ -export type Episode = - /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ - | 'EMPIRE' - /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ - | 'JEDI' - /** Star Wars Episode IV: A New Hope, released in 1977. */ - | 'NEWHOPE'; - export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.ts b/dev-test/star-wars/types.ts index 2d8f0be51e8..e3d32fb9e2e 100644 --- a/dev-test/star-wars/types.ts +++ b/dev-test/star-wars/types.ts @@ -244,15 +244,6 @@ export type StarshipLengthArgs = { unit?: InputMaybe; }; -/** The episodes in the Star Wars trilogy */ -export type Episode = - /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ - | 'EMPIRE' - /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ - | 'JEDI' - /** Star Wars Episode IV: A New Hope, released in 1977. */ - | 'NEWHOPE'; - export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts index abe64383e52..5ad05f464cc 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts @@ -47,6 +47,7 @@ export interface ParsedDocumentsConfig extends ParsedTypesConfig { mergeFragmentTypes: boolean; customDirectives: CustomDirectivesConfig; generatesOperationTypes: boolean; + importSchemaTypesFrom: string; } export interface RawDocumentsConfig extends RawTypesConfig { @@ -184,6 +185,7 @@ export interface RawDocumentsConfig extends RawTypesConfig { /** * @description Whether to generate operation types such as Variables, Query/Mutation/Subscription selection set, and Fragment types + * This can be used with `importSchemaTypesFrom` to generate shared used Enums and Input. * @default true * @exampleMarkdown * ```ts filename="codegen.ts" @@ -204,6 +206,30 @@ export interface RawDocumentsConfig extends RawTypesConfig { * ``` */ generatesOperationTypes?: boolean; + + /** + * @description The absolute (prefixed with `~`) or relative path from `cwd` to the shared used Enums and Input (See `generatesOperationTypes`). + * @default true + * @exampleMarkdown + * ```ts filename="codegen.ts" + * import type { CodegenConfig } from '@graphql-codegen/cli'; + * + * const config: CodegenConfig = { + * // ... + * generates: { + * 'path/to/file.ts': { + * plugins: ['typescript-operations'], + * config: { + * importSchemaTypesFrom: './path/to/shared-types.ts', // relative + * importSchemaTypesFrom: '~@my-org/package' // absolute + * }, + * }, + * }, + * }; + * export default config; + * ``` + */ + importSchemaTypesFrom?: string; } export class BaseDocumentsVisitor< @@ -239,6 +265,7 @@ export class BaseDocumentsVisitor< apolloUnmask: false, }), generatesOperationTypes: getConfigValue(rawConfig.generatesOperationTypes, true), + importSchemaTypesFrom: getConfigValue(rawConfig.importSchemaTypesFrom, ''), ...((additionalConfig || {}) as any), }); diff --git a/packages/plugins/other/visitor-plugin-common/src/graphql-type-utils.ts b/packages/plugins/other/visitor-plugin-common/src/graphql-type-utils.ts new file mode 100644 index 00000000000..82634cd2849 --- /dev/null +++ b/packages/plugins/other/visitor-plugin-common/src/graphql-type-utils.ts @@ -0,0 +1,13 @@ +import { type GraphQLNamedType, isIntrospectionType, isSpecifiedScalarType } from 'graphql'; + +export const isNativeNamedType = (namedType: GraphQLNamedType): boolean => { + // "Native" NamedType in this context means the following: + // 1. introspection types i.e. with `__` prefixes + // 2. base scalars e.g. Boolean, Int, etc. + // 3. Other natives (mostly base scalars) which was not defined in the schema i.e. no `astNode` + if (isSpecifiedScalarType(namedType) || isIntrospectionType(namedType) || !namedType.astNode) { + return true; + } + + return false; +}; diff --git a/packages/plugins/other/visitor-plugin-common/src/index.ts b/packages/plugins/other/visitor-plugin-common/src/index.ts index bdb72829a17..f645aa973c3 100644 --- a/packages/plugins/other/visitor-plugin-common/src/index.ts +++ b/packages/plugins/other/visitor-plugin-common/src/index.ts @@ -18,3 +18,4 @@ export * from './types.js'; export * from './utils.js'; export * from './variables-to-object.js'; export * from './convert-schema-enum-to-declaration-block-string.js'; +export * from './graphql-type-utils.js'; diff --git a/packages/plugins/typescript/operations/src/index.ts b/packages/plugins/typescript/operations/src/index.ts index 272da57712b..cf257624180 100644 --- a/packages/plugins/typescript/operations/src/index.ts +++ b/packages/plugins/typescript/operations/src/index.ts @@ -10,11 +10,7 @@ export { TypeScriptDocumentsPluginConfig } from './config.js'; export const plugin: PluginFunction< TypeScriptDocumentsPluginConfig, Types.ComplexPluginOutput -> = async ( - inputSchema: GraphQLSchema, - rawDocuments: Types.DocumentFile[], - config: TypeScriptDocumentsPluginConfig, -) => { +> = async (inputSchema, rawDocuments, config, { outputFile }) => { const schema = config.nullability?.errorHandlingClient ? await semanticToStrict(inputSchema) : inputSchema; @@ -58,7 +54,7 @@ export const plugin: PluginFunction< // For Fragment types to resolve correctly, we must get read all docs (`standard` and `external`) // Fragment types are usually (but not always) in `external` files in certain setup, like a monorepo. const allDocumentsAST = concatAST(parsedDocuments.all.documentNodes); - const visitor = new TypeScriptDocumentsVisitor(schema, config, allDocumentsAST); + const visitor = new TypeScriptDocumentsVisitor(schema, config, allDocumentsAST, outputFile); // We only visit `standard` documents to generate types. // `external` documents are included as references for typechecking and completeness i.e. only used for reading purposes, no writing. @@ -101,6 +97,7 @@ export const plugin: PluginFunction< return { prepend: [ ...visitor.getImports(), + ...visitor.getExternalSchemaTypeImports(), ...visitor.getEnumsImports(), ...visitor.getGlobalDeclarations(visitor.config.noExport), visitor.getExactUtilityType(), diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 83f607de948..1d1335f26c3 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -20,8 +20,10 @@ import { convertSchemaEnumToDeclarationBlockString, DeclarationKind, generateFragmentImportStatement, + generateImportStatement, getConfigValue, getEnumsImports, + isNativeNamedType, LoadedFragment, normalizeAvoidOptionals, NormalizedAvoidOptionalsConfig, @@ -57,10 +59,13 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< TypeScriptDocumentsParsedConfig > { protected _usedNamedInputTypes: UsedNamedInputTypes = {}; + private _outputPath: string; + constructor( schema: GraphQLSchema, config: TypeScriptDocumentsPluginConfig, documentNode: DocumentNode, + outputPath: string, ) { super( config, @@ -84,6 +89,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< schema, ); + this._outputPath = outputPath; autoBind(this); const preResolveTypes = getConfigValue(config.preResolveTypes, true); @@ -188,7 +194,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< EnumTypeDefinition(node: EnumTypeDefinitionNode): string | null { const enumName = node.name.value; - if (!this._usedNamedInputTypes[enumName]) { + if (!this._usedNamedInputTypes[enumName] || this.config.importSchemaTypesFrom) { return null; } @@ -220,18 +226,43 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< : []; } + public getExternalSchemaTypeImports(): Array { + if (!this.config.importSchemaTypesFrom) { + return []; + } + + const hasTypesToImport = Object.keys(this._usedNamedInputTypes).length > 0; + + if (!hasTypesToImport) { + return []; + } + + return [ + generateImportStatement({ + baseDir: process.cwd(), + baseOutputDir: '', + outputPath: this._outputPath, + importSource: { + path: this.config.importSchemaTypesFrom, + namespace: this.config.namespacedImportName, + identifiers: [], + }, + typesImport: true, + // FIXME: rebase with master for the new extension + emitLegacyCommonJSImports: true, + }), + ]; + } + protected getPunctuation(_declarationKind: DeclarationKind): string { return ';'; } protected applyVariablesWrapper(variablesBlock: string, operationType: string): string { - const prefix = this.config.namespacedImportName ? `${this.config.namespacedImportName}.` : ''; const extraType = this.config.allowUndefinedQueryVariables && operationType === 'Query' ? ' | undefined' : ''; - return `${prefix}Exact<${ - variablesBlock === '{}' ? `{ [key: string]: never; }` : variablesBlock - }>${extraType}`; + return `Exact<${variablesBlock === '{}' ? `{ [key: string]: never; }` : variablesBlock}>${extraType}`; } private collectUsedInputTypes({ @@ -254,7 +285,8 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< foundInputType && (foundInputType instanceof GraphQLInputObjectType || foundInputType instanceof GraphQLScalarType || - foundInputType instanceof GraphQLEnumType) + foundInputType instanceof GraphQLEnumType) && + !isNativeNamedType(foundInputType) ) { usedInputTypes[namedTypeNode.name.value] = foundInputType; } diff --git a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap index f364438cc65..b9d144384f1 100644 --- a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap +++ b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap @@ -57,7 +57,7 @@ export type ElementMetadataFragment = `; exports[`TypeScript Operations Plugin > Issues > #2916 - Missing import prefix with preResolveTypes: true and near-operation-file preset 1`] = ` -"export type UserQueryVariables = Types.Exact<{ [key: string]: never; }>; +"export type UserQueryVariables = Exact<{ [key: string]: never; }>; export type UserQuery = { user: { id: string, username: string, email: string, dep: Types.Department } }; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.nullability.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.nullability.spec.ts index df6c18e18d3..631b879b198 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.nullability.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.nullability.spec.ts @@ -62,11 +62,16 @@ const document = parse(/* GraphQL */ ` describe('TypeScript Operations Plugin - nullability', () => { it('converts semanticNonNull to nonNull when nullability.errorHandlingClient=true', async () => { - const result = await plugin(schema, [{ document }], { - nullability: { - errorHandlingClient: true, + const result = await plugin( + schema, + [{ document }], + { + nullability: { + errorHandlingClient: true, + }, }, - }); + { outputFile: '' } + ); const formattedContent = await prettier.format(result.content, { parser: 'typescript', @@ -105,11 +110,16 @@ describe('TypeScript Operations Plugin - nullability', () => { }); it('does not convert nullability to nonNull when nullability.errorHandlingClient=false', async () => { - const result = await plugin(schema, [{ document }], { - nullability: { - errorHandlingClient: false, + const result = await plugin( + schema, + [{ document }], + { + nullability: { + errorHandlingClient: false, + }, }, - }); + { outputFile: '' } + ); const formattedContent = await prettier.format(result.content, { parser: 'typescript', diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts index b00857d7364..d058165b47e 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts @@ -32,7 +32,7 @@ describe('TypeScript Operations Plugin - Enum', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], {})]); + const result = mergeOutputs([await plugin(schema, [{ document }], {}, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; @@ -74,7 +74,9 @@ describe('TypeScript Operations Plugin - Enum', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native-numeric' })]); + const result = mergeOutputs([ + await plugin(schema, [{ document }], { enumType: 'native-numeric' }, { outputFile: '' }), + ]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; @@ -126,7 +128,7 @@ describe('TypeScript Operations Plugin - Enum', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'const' })]); + const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'const' }, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; @@ -182,7 +184,9 @@ describe('TypeScript Operations Plugin - Enum', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native-const' })]); + const result = mergeOutputs([ + await plugin(schema, [{ document }], { enumType: 'native-const' }, { outputFile: '' }), + ]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; @@ -233,7 +237,7 @@ describe('TypeScript Operations Plugin - Enum', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' })]); + const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' }, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; @@ -285,17 +289,22 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { - enumType: 'string-literal', - enumValues: { - UserRole: { - A_B_C: 0, - X_Y_Z: 'Foo', - _TEST: 'Bar', - My_Value: 1, + await plugin( + schema, + [{ document }], + { + enumType: 'string-literal', + enumValues: { + UserRole: { + A_B_C: 0, + X_Y_Z: 'Foo', + _TEST: 'Bar', + My_Value: 1, + }, }, }, - }), + { outputFile: '' } + ), ]); expect(result).toMatchInlineSnapshot(` @@ -349,17 +358,22 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { - enumType: 'const', - enumValues: { - UserRole: { - A_B_C: 0, - X_Y_Z: 'Foo', - _TEST: 'Bar', - My_Value: 1, + await plugin( + schema, + [{ document }], + { + enumType: 'const', + enumValues: { + UserRole: { + A_B_C: 0, + X_Y_Z: 'Foo', + _TEST: 'Bar', + My_Value: 1, + }, }, }, - }), + { outputFile: '' } + ), ]); expect(result).toMatchInlineSnapshot(` @@ -413,15 +427,20 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { - enumType: 'native', - enumValues: { - UserRole: { - ADMIN: 0, - CUSTOMER: 'test', + await plugin( + schema, + [{ document }], + { + enumType: 'native', + enumValues: { + UserRole: { + ADMIN: 0, + CUSTOMER: 'test', + }, }, }, - }), + { outputFile: '' } + ), ]); expect(result).toMatchInlineSnapshot(` @@ -473,11 +492,16 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { - enumValues: { - UserRole: './my-file#MyEnum', + await plugin( + schema, + [{ document }], + { + enumValues: { + UserRole: './my-file#MyEnum', + }, }, - }), + { outputFile: '' } + ), ]); expect(result).toMatchInlineSnapshot(` @@ -527,11 +551,16 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { - enumValues: { - UserRole: './my-file#NS.ETest', + await plugin( + schema, + [{ document }], + { + enumValues: { + UserRole: './my-file#NS.ETest', + }, }, - }), + { outputFile: '' } + ), ]); expect(result).toMatchInlineSnapshot(` @@ -582,11 +611,16 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { - enumValues: { - UserRole: './my-file#NS.UserRole', + await plugin( + schema, + [{ document }], + { + enumValues: { + UserRole: './my-file#NS.UserRole', + }, }, - }), + { outputFile: '' } + ), ]); expect(result).toMatchInlineSnapshot(` @@ -642,10 +676,15 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { - enumType: 'native', - enumValues: './my-file', - }), + await plugin( + schema, + [{ document }], + { + enumType: 'native', + enumValues: './my-file', + }, + { outputFile: '' } + ), ]); expect(result).toMatchInlineSnapshot(` @@ -704,10 +743,15 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { - enumType: 'native', - enumValues: { UserRole: './my-file#UserRole', UserStatus: './my-file#UserStatus2X' }, - }), + await plugin( + schema, + [{ document }], + { + enumType: 'native', + enumValues: { UserRole: './my-file#UserRole', UserStatus: './my-file#UserStatus2X' }, + }, + { outputFile: '' } + ), ]); expect(result).toMatchInlineSnapshot(` @@ -762,7 +806,7 @@ describe('TypeScript Operations Plugin - Enum', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' })]); + const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' }, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; @@ -815,7 +859,7 @@ describe('TypeScript Operations Plugin - Enum', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' })]); + const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' }, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; @@ -866,7 +910,9 @@ describe('TypeScript Operations Plugin - Enum', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { typesPrefix: 'I', enumPrefix: true })]); + const result = mergeOutputs([ + await plugin(schema, [{ document }], { typesPrefix: 'I', enumPrefix: true }, { outputFile: '' }), + ]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; export type IUserRole = @@ -914,7 +960,9 @@ describe('TypeScript Operations Plugin - Enum', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { typesPrefix: 'I', enumPrefix: false })]); + const result = mergeOutputs([ + await plugin(schema, [{ document }], { typesPrefix: 'I', enumPrefix: false }, { outputFile: '' }), + ]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; export type UserRole = @@ -962,7 +1010,9 @@ describe('TypeScript Operations Plugin - Enum', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { typesSuffix: 'Z', enumSuffix: true })]); + const result = mergeOutputs([ + await plugin(schema, [{ document }], { typesSuffix: 'Z', enumSuffix: true }, { outputFile: '' }), + ]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; export type UserRoleZ = @@ -1010,7 +1060,9 @@ describe('TypeScript Operations Plugin - Enum', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { typesSuffix: 'Z', enumSuffix: false })]); + const result = mergeOutputs([ + await plugin(schema, [{ document }], { typesSuffix: 'Z', enumSuffix: false }, { outputFile: '' }), + ]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; export type UserRole = @@ -1059,12 +1111,17 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { - namingConvention: { - typeNames: 'change-case-all#lowerCase', - enumValues: 'keep', + await plugin( + schema, + [{ document }], + { + namingConvention: { + typeNames: 'change-case-all#lowerCase', + enumValues: 'keep', + }, }, - }), + { outputFile: '' } + ), ]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; @@ -1114,13 +1171,18 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { - enumType: 'native', - namingConvention: { - typeNames: 'keep', - enumValues: 'change-case-all#lowerCase', + await plugin( + schema, + [{ document }], + { + enumType: 'native', + namingConvention: { + typeNames: 'keep', + enumValues: 'change-case-all#lowerCase', + }, }, - }), + { outputFile: '' } + ), ]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; @@ -1171,9 +1233,14 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { - noExport: true, - }), + await plugin( + schema, + [{ document }], + { + noExport: true, + }, + { outputFile: '' } + ), ]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; @@ -1223,13 +1290,18 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { - typesPrefix: 'I', - namingConvention: { enumValues: 'change-case-all#constantCase' }, - enumValues: { - UserRole: './files#default as UserRole', + await plugin( + schema, + [{ document }], + { + typesPrefix: 'I', + namingConvention: { enumValues: 'change-case-all#constantCase' }, + enumValues: { + UserRole: './files#default as UserRole', + }, }, - }), + { outputFile: '' } + ), ]); expect(result).toMatchInlineSnapshot(` @@ -1277,7 +1349,7 @@ describe('TypeScript Operations Plugin - Enum', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' })]); + const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' }, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; @@ -1327,7 +1399,7 @@ describe('TypeScript Operations Plugin - Enum `%future added value`', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { futureProofEnums: true })]); + const result = mergeOutputs([await plugin(schema, [{ document }], { futureProofEnums: true }, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts new file mode 100644 index 00000000000..af820bf713a --- /dev/null +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts @@ -0,0 +1,371 @@ +import { buildSchema, parse } from 'graphql'; +import { validateTs } from '@graphql-codegen/testing'; +import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; +import { plugin } from '../src/index.js'; + +describe('TypeScript Operations Plugin - Import Types', () => { + it('imports user-defined types externally with relative importSchemaTypesFrom correctly', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + users(input: UsersInput!): UsersResponse! + } + + type ResponseError { + error: ResponseErrorType! + } + + enum ResponseErrorType { + NOT_FOUND + INPUT_VALIDATION_ERROR + FORBIDDEN_ERROR + UNEXPECTED_ERROR + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + "UserRole Description" + enum UserRole { + "UserRole ADMIN" + ADMIN + "UserRole CUSTOMER" + CUSTOMER + } + + "UsersInput Description" + input UsersInput { + "UsersInput from" + from: DateTime + "UsersInput to" + to: DateTime + role: UserRole + } + + type UsersResponseOk { + result: [User!]! + } + union UsersResponse = UsersResponseOk | ResponseError + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User($id: ID!) { + user(id: $id) { + id + name + role + createdAt + } + } + + query Users($input: UsersInput!) { + users(input: $input) { + ... on UsersResponseOk { + result { + id + } + } + ... on ResponseError { + error + } + } + } + + query UsersWithScalarInput($from: DateTime!, $to: DateTime, $role: UserRole) { + users(input: { from: $from, to: $to, role: $role }) { + ... on UsersResponseOk { + result { + __typename + } + } + ... on ResponseError { + __typename + } + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + importSchemaTypesFrom: './base-dir/path-to-other-file.generated.ts', + namespacedImportName: 'TypeImport', + }, + { outputFile: './base-dir/this-file.ts' } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "import type * as TypeImport from './path-to-other-file.generated'; + + type Exact = { [K in keyof T]: T[K] }; + export type UserQueryVariables = Exact<{ + id: string; + }>; + + + export type UserQuery = { __typename?: 'Query', user?: { __typename?: 'User', id: string, name: string, role: TypeImport.UserRole, createdAt: any } | null }; + + export type UsersQueryVariables = Exact<{ + input: TypeImport.UsersInput; + }>; + + + export type UsersQuery = { __typename?: 'Query', users: + | { __typename?: 'UsersResponseOk', result: Array<{ __typename?: 'User', id: string }> } + | { __typename?: 'ResponseError', error: TypeImport.ResponseErrorType } + }; + + export type UsersWithScalarInputQueryVariables = Exact<{ + from: any; + to?: any | null; + role?: TypeImport.UserRole | null; + }>; + + + export type UsersWithScalarInputQuery = { __typename?: 'Query', users: + | { __typename?: 'UsersResponseOk', result: Array<{ __typename: 'User' }> } + | { __typename: 'ResponseError' } + }; + " + `); + }); + + it('imports user-defined types externally with absolute importSchemaTypesFrom correctly', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + users(input: UsersInput!): UsersResponse! + } + + type ResponseError { + error: ResponseErrorType! + } + + enum ResponseErrorType { + NOT_FOUND + INPUT_VALIDATION_ERROR + FORBIDDEN_ERROR + UNEXPECTED_ERROR + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + "UserRole Description" + enum UserRole { + "UserRole ADMIN" + ADMIN + "UserRole CUSTOMER" + CUSTOMER + } + + "UsersInput Description" + input UsersInput { + "UsersInput from" + from: DateTime + "UsersInput to" + to: DateTime + role: UserRole + } + + type UsersResponseOk { + result: [User!]! + } + union UsersResponse = UsersResponseOk | ResponseError + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User($id: ID!) { + user(id: $id) { + id + name + role + createdAt + } + } + + query Users($input: UsersInput!) { + users(input: $input) { + ... on UsersResponseOk { + result { + id + } + } + ... on ResponseError { + error + } + } + } + + query UsersWithScalarInput($from: DateTime!, $to: DateTime, $role: UserRole) { + users(input: { from: $from, to: $to, role: $role }) { + ... on UsersResponseOk { + result { + __typename + } + } + ... on ResponseError { + __typename + } + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + importSchemaTypesFrom: '~@my-company/package/types', + namespacedImportName: 'TypeImport', + }, + { outputFile: './base-dir/this-file.ts' } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "import type * as TypeImport from '@my-company/package/types'; + + type Exact = { [K in keyof T]: T[K] }; + export type UserQueryVariables = Exact<{ + id: string; + }>; + + + export type UserQuery = { __typename?: 'Query', user?: { __typename?: 'User', id: string, name: string, role: TypeImport.UserRole, createdAt: any } | null }; + + export type UsersQueryVariables = Exact<{ + input: TypeImport.UsersInput; + }>; + + + export type UsersQuery = { __typename?: 'Query', users: + | { __typename?: 'UsersResponseOk', result: Array<{ __typename?: 'User', id: string }> } + | { __typename?: 'ResponseError', error: TypeImport.ResponseErrorType } + }; + + export type UsersWithScalarInputQueryVariables = Exact<{ + from: any; + to?: any | null; + role?: TypeImport.UserRole | null; + }>; + + + export type UsersWithScalarInputQuery = { __typename?: 'Query', users: + | { __typename?: 'UsersResponseOk', result: Array<{ __typename: 'User' }> } + | { __typename: 'ResponseError' } + }; + " + `); + }); + + it('does not import external types if only native GraphQL types are used in Variables and Result', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + users(input: UsersInput!): UsersResponse! + } + + type ResponseError { + error: ResponseErrorType! + } + + enum ResponseErrorType { + NOT_FOUND + INPUT_VALIDATION_ERROR + FORBIDDEN_ERROR + UNEXPECTED_ERROR + } + + type User { + # Native GraphQL types + id: ID! + name: String! + isOld: Boolean! + ageInt: Int! + ageFloat: Float! + + # User-defined types + role: UserRole! + createdAt: DateTime! + } + + "UserRole Description" + enum UserRole { + "UserRole ADMIN" + ADMIN + "UserRole CUSTOMER" + CUSTOMER + } + + "UsersInput Description" + input UsersInput { + "UsersInput from" + from: DateTime + "UsersInput to" + to: DateTime + role: UserRole + } + + type UsersResponseOk { + result: [User!]! + } + union UsersResponse = UsersResponseOk | ResponseError + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User($id: ID, $name: String, $bool: Boolean, $int: Int, $float: Float) { + user(id: $id) { + id + name + isOld + ageInt + ageFloat + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + importSchemaTypesFrom: './path-to-other-file', + namespacedImportName: 'TypeImport', + }, + { outputFile: '' } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type UserQueryVariables = Exact<{ + id?: string | null; + name?: string | null; + bool?: boolean | null; + int?: number | null; + float?: number | null; + }>; + + + export type UserQuery = { __typename?: 'Query', user?: { __typename?: 'User', id: string, name: string, isOld: boolean, ageInt: number, ageFloat: number } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); +}); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts index 2f1cb9a5485..00ea9a5ca42 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -90,7 +90,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], {})]); + const result = mergeOutputs([await plugin(schema, [{ document }], {}, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; @@ -157,7 +157,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { scalars: { ID: 'string | number | boolean' } }), + await plugin(schema, [{ document }], { scalars: { ID: 'string | number | boolean' } }, { outputFile: '' }), ]); expect(result).toMatchInlineSnapshot(` @@ -283,7 +283,9 @@ describe('TypeScript Operations Plugin - Standalone', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { generatesOperationTypes: false })]); + const result = mergeOutputs([ + await plugin(schema, [{ document }], { generatesOperationTypes: false }, { outputFile: '' }), + ]); expect(result).toMatchInlineSnapshot(` " @@ -299,4 +301,81 @@ describe('TypeScript Operations Plugin - Standalone', () => { validateTs(result, undefined, undefined, undefined, undefined, true); }); + + it('does not generate unused schema enum and input types', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + users(input: UsersInput!): UsersResponse! + } + + type Mutation { + makeUserAdmin(id: ID!): User! + } + + type Subscription { + userChanges(id: ID!): User! + } + + type ResponseError { + error: ResponseErrorType! + } + + enum ResponseErrorType { + NOT_FOUND + INPUT_VALIDATION_ERROR + FORBIDDEN_ERROR + UNEXPECTED_ERROR + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + "UserRole Description" + enum UserRole { + "UserRole ADMIN" + ADMIN + "UserRole CUSTOMER" + CUSTOMER + } + + "UsersInput Description" + input UsersInput { + "UsersInput from" + from: DateTime + "UsersInput to" + to: DateTime + role: UserRole + } + + type UsersResponseOk { + result: [User!]! + } + union UsersResponse = UsersResponseOk | ResponseError + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User { + user(id: "100") { + id + } + } + `); + + const result = mergeOutputs([ + await plugin(schema, [{ document }], { generatesOperationTypes: false }, { outputFile: '' }), + ]); + + expect(result).toMatchInlineSnapshot(` + " + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); }); From 843b06282b3c1cd50ced49c02300b25719500a90 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Sun, 14 Dec 2025 00:59:47 +1100 Subject: [PATCH 11/69] [typescript-operations][client-preset] Integrate new typescript-operations with client preset (#10540) * Do not use typescript and its config in Client Preset * Fix issue where enumValues are imported even if not used * Split enum tests for client preset * Update unit tests * Update examples * Generate Incremental utilty type * Add changeset * Rebase tests (with errors) --- .changeset/salty-guests-retire.md | 6 + dev-test/codegen.ts | 63 +- .../external-documents/app/types.generated.ts | 5 +- dev-test/githunt/typed-document-nodes.ts | 172 +-- dev-test/githunt/types.avoidOptionals.ts | 172 +-- dev-test/githunt/types.d.ts | 167 +-- dev-test/githunt/types.enumsAsTypes.ts | 167 +-- .../githunt/types.flatten.preResolveTypes.ts | 172 +-- dev-test/githunt/types.immutableTypes.ts | 172 +-- ...ypes.preResolveTypes.onlyOperationTypes.ts | 35 +- dev-test/githunt/types.preResolveTypes.ts | 172 +-- dev-test/githunt/types.ts | 172 +-- .../gql-tag-operations-masking/gql/graphql.ts | 109 +- .../gql-tag-operations-urql/gql/graphql.ts | 109 +- dev-test/gql-tag-operations/gql/graphql.ts | 109 +- .../gql-tag-operations/graphql/graphql.ts | 109 +- .../import-schema-types/_types.generated.ts | 5 +- dev-test/star-wars/types.avoidOptionals.ts | 244 +--- dev-test/star-wars/types.d.ts | 241 +--- dev-test/star-wars/types.excludeQueryAlpha.ts | 244 +--- dev-test/star-wars/types.excludeQueryBeta.ts | 244 +--- .../star-wars/types.globallyAvailable.d.ts | 242 +--- dev-test/star-wars/types.immutableTypes.ts | 244 +--- ...ypes.preResolveTypes.onlyOperationTypes.ts | 53 +- dev-test/star-wars/types.preResolveTypes.ts | 244 +--- dev-test/star-wars/types.skipSchema.ts | 244 +--- dev-test/star-wars/types.ts | 244 +--- dev-test/test-null-value/result.d.ts | 47 +- ...ypes.preResolveTypes.onlyOperationTypes.ts | 18 +- dev-test/test-schema/types.preResolveTypes.ts | 43 +- dev-test/test-schema/typings.wrapped.ts | 1 - .../src/gql/graphql.ts | 32 +- .../persisted-documents/src/gql/graphql.ts | 32 +- .../apollo-client-defer/src/gql/graphql.ts | 34 +- .../react/apollo-client/src/gql/graphql.ts | 1277 +---------------- .../react/http-executor/src/gql/graphql.ts | 1277 +---------------- .../tanstack-react-query/src/gql/graphql.ts | 1277 +---------------- examples/react/urql/src/gql/graphql.ts | 1277 +---------------- examples/typescript-esm/src/gql/graphql.ts | 1277 +---------------- .../src/gql/graphql.ts | 1277 +---------------- .../vite/vite-react-cts/src/gql/graphql.ts | 1277 +---------------- .../vite/vite-react-mts/src/gql/graphql.ts | 1277 +---------------- .../vite/vite-react-ts/src/gql/graphql.ts | 1277 +---------------- .../vue/apollo-composable/src/gql/graphql.ts | 1277 +---------------- examples/vue/urql/src/gql/graphql.ts | 1277 +---------------- examples/vue/villus/src/gql/graphql.ts | 1277 +---------------- examples/yoga-tests/src/gql/graphql.ts | 32 +- .../typescript/operations/src/index.ts | 5 +- .../typescript/operations/src/visitor.ts | 28 +- .../ts-documents.standalone.enum.spec.ts | 80 ++ ...-documents.standalone.import-types.spec.ts | 3 + .../tests/ts-documents.standalone.spec.ts | 4 + packages/presets/client/src/index.ts | 12 +- .../client/tests/client-preset.enum.spec.ts | 208 +++ .../client/tests/client-preset.spec.ts | 667 +-------- 55 files changed, 435 insertions(+), 20295 deletions(-) create mode 100644 .changeset/salty-guests-retire.md create mode 100644 packages/presets/client/tests/client-preset.enum.spec.ts diff --git a/.changeset/salty-guests-retire.md b/.changeset/salty-guests-retire.md new file mode 100644 index 00000000000..78587b447ad --- /dev/null +++ b/.changeset/salty-guests-retire.md @@ -0,0 +1,6 @@ +--- +'@graphql-codegen/typescript-operations': major +'@graphql-codegen/client-preset': major +--- + +Integrate new typescript-operations into client-preset diff --git a/dev-test/codegen.ts b/dev-test/codegen.ts index aa9ab6104dc..604deca956e 100644 --- a/dev-test/codegen.ts +++ b/dev-test/codegen.ts @@ -40,7 +40,6 @@ const config: CodegenConfig = { { add: { content: 'declare namespace GraphQL {' } }, { add: { placement: 'append', content: '}' } }, 'typescript', - 'typescript-operations', ], }, './dev-test/test-schema/env.types.ts': { @@ -68,65 +67,65 @@ const config: CodegenConfig = { './dev-test/githunt/typed-document-nodes.ts': { schema: './dev-test/githunt/schema.json', documents: './dev-test/githunt/**/*.graphql', - plugins: ['typescript', 'typescript-operations', 'typed-document-node'], + plugins: ['typescript-operations', 'typed-document-node'], }, './dev-test/githunt/types.ts': { schema: './dev-test/githunt/schema.json', documents: './dev-test/githunt/**/*.graphql', - plugins: ['typescript', 'typescript-operations'], + plugins: ['typescript-operations'], }, './dev-test/githunt/types.preResolveTypes.ts': { schema: './dev-test/githunt/schema.json', documents: './dev-test/githunt/**/*.graphql', config: { preResolveTypes: true }, - plugins: ['typescript', 'typescript-operations'], + plugins: ['typescript-operations'], }, './dev-test/githunt/types.onlyEnums.ts': { schema: './dev-test/githunt/schema.json', documents: './dev-test/githunt/**/*.graphql', - config: { onlyEnums: true }, - plugins: ['typescript'], + config: { generatesOperationTypes: false }, + plugins: ['typescript-operations'], }, './dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts': { schema: './dev-test/githunt/schema.json', documents: './dev-test/githunt/**/*.graphql', - config: { preResolveTypes: true, onlyOperationTypes: true }, - plugins: ['typescript', 'typescript-operations'], + config: { preResolveTypes: true }, + plugins: ['typescript-operations'], }, './dev-test/githunt/types.flatten.preResolveTypes.ts': { schema: './dev-test/githunt/schema.json', documents: './dev-test/githunt/**/*.graphql', config: { preResolveTypes: true, flattenGeneratedTypes: true }, - plugins: ['typescript', 'typescript-operations'], + plugins: ['typescript-operations'], }, './dev-test/githunt/types.enumsAsTypes.ts': { schema: './dev-test/githunt/schema.json', documents: './dev-test/githunt/**/*.graphql', - config: { enumsAsTypes: true }, - plugins: ['typescript', 'typescript-operations'], + config: { enumType: 'string-literal' }, + plugins: ['typescript-operations'], }, './dev-test/githunt/types.d.ts': { schema: './dev-test/githunt/schema.json', documents: './dev-test/githunt/**/*.graphql', - config: { enumsAsTypes: true }, - plugins: ['typescript', 'typescript-operations'], + config: {}, + plugins: ['typescript-operations'], }, './dev-test/githunt/types.avoidOptionals.ts': { schema: './dev-test/githunt/schema.json', documents: './dev-test/githunt/**/*.graphql', config: { avoidOptionals: true }, - plugins: ['typescript', 'typescript-operations'], + plugins: ['typescript-operations'], }, './dev-test/githunt/types.immutableTypes.ts': { schema: './dev-test/githunt/schema.json', documents: './dev-test/githunt/**/*.graphql', config: { immutableTypes: true }, - plugins: ['typescript', 'typescript-operations'], + plugins: ['typescript-operations'], }, './dev-test/star-wars/types.ts': { schema: './dev-test/star-wars/schema.json', documents: './dev-test/star-wars/**/*.graphql', - plugins: ['typescript', 'typescript-operations'], + plugins: ['typescript-operations'], }, './dev-test/star-wars/types.excludeQueryAlpha.ts': { schema: './dev-test/star-wars/schema.json', @@ -134,7 +133,7 @@ const config: CodegenConfig = { './dev-test/star-wars/**/*.graphql', '!./dev-test/star-wars/**/ExcludeQueryAlpha.graphql', ], - plugins: ['typescript', 'typescript-operations'], + plugins: ['typescript-operations'], }, './dev-test/star-wars/types.excludeQueryBeta.ts': { schema: './dev-test/star-wars/schema.json', @@ -142,13 +141,13 @@ const config: CodegenConfig = { './dev-test/star-wars/**/*.graphql', '!./dev-test/star-wars/**/ExcludeQueryBeta.graphql', ], - plugins: ['typescript', 'typescript-operations'], + plugins: ['typescript-operations'], }, './dev-test/star-wars/types.preResolveTypes.ts': { schema: './dev-test/star-wars/schema.json', documents: './dev-test/star-wars/**/*.graphql', config: { preResolveTypes: true }, - plugins: ['typescript', 'typescript-operations'], + plugins: ['typescript-operations'], }, './dev-test/star-wars/types.OnlyEnums.ts': { schema: './dev-test/star-wars/schema.json', @@ -159,25 +158,25 @@ const config: CodegenConfig = { './dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts': { schema: './dev-test/star-wars/schema.json', documents: './dev-test/star-wars/**/*.graphql', - config: { preResolveTypes: true, onlyOperationTypes: true }, - plugins: ['typescript', 'typescript-operations'], + config: { preResolveTypes: true }, + plugins: ['typescript-operations'], }, './dev-test/test-schema/types.preResolveTypes.ts': { schema: './dev-test/test-schema/schema.graphql', documents: ['query test { testArr1 testArr2 testArr3 }'], config: { preResolveTypes: true }, - plugins: ['typescript', 'typescript-operations'], + plugins: ['typescript-operations'], }, './dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts': { schema: './dev-test/test-schema/schema.graphql', documents: ['query test { testArr1 testArr2 testArr3 }'], - config: { preResolveTypes: true, onlyOperationTypes: true }, - plugins: ['typescript', 'typescript-operations'], + config: { preResolveTypes: true }, + plugins: ['typescript-operations'], }, './dev-test/star-wars/types.d.ts': { schema: './dev-test/star-wars/schema.json', - config: { enumsAsTypes: true }, - plugins: ['typescript', 'typescript-operations'], + config: { enumType: 'string-literal' }, + plugins: ['typescript-operations'], }, './dev-test/modules/': { schema: './dev-test/modules/*/types/*.graphql', @@ -188,25 +187,25 @@ const config: CodegenConfig = { './dev-test/star-wars/types.globallyAvailable.d.ts': { schema: './dev-test/star-wars/schema.json', documents: './dev-test/star-wars/**/*.graphql', - config: { enumsAsTypes: true, noExport: true }, - plugins: ['typescript', 'typescript-operations'], + config: { noExport: true }, + plugins: ['typescript-operations'], }, './dev-test/star-wars/types.avoidOptionals.ts': { schema: './dev-test/star-wars/schema.json', documents: './dev-test/star-wars/**/*.graphql', config: { avoidOptionals: true }, - plugins: ['typescript', 'typescript-operations'], + plugins: ['typescript-operations'], }, './dev-test/star-wars/types.immutableTypes.ts': { schema: './dev-test/star-wars/schema.json', documents: './dev-test/star-wars/**/*.graphql', config: { immutableTypes: true }, - plugins: ['typescript', 'typescript-operations'], + plugins: ['typescript-operations'], }, './dev-test/star-wars/types.skipSchema.ts': { schema: './dev-test/star-wars/schema.json', documents: './dev-test/star-wars/**/*.graphql', - plugins: ['typescript', 'typescript-operations'], + plugins: ['typescript-operations'], }, './dev-test/gql-tag-operations/gql/': { schema: './dev-test/gql-tag-operations/schema.graphql', @@ -233,7 +232,7 @@ const config: CodegenConfig = { './dev-test/test-null-value/result.d.ts': { schema: './dev-test/test-null-value/schema.graphql', documents: ['./dev-test/test-null-value/query.ts'], - plugins: ['typescript', 'typescript-operations'], + plugins: ['typescript-operations'], config: { // The combination of these two flags caused the following issue: // https://github.com/dotansimha/graphql-code-generator/pull/9709 diff --git a/dev-test/external-documents/app/types.generated.ts b/dev-test/external-documents/app/types.generated.ts index 4fb00945d52..40b98b77936 100644 --- a/dev-test/external-documents/app/types.generated.ts +++ b/dev-test/external-documents/app/types.generated.ts @@ -1,6 +1,9 @@ type Exact = { [K in keyof T]: T[K] }; +export type Incremental = + | T + | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ - id: Scalars['ID']['input']; + id: string; }>; export type UserQuery = { diff --git a/dev-test/githunt/typed-document-nodes.ts b/dev-test/githunt/typed-document-nodes.ts index 9ca29efb843..e2d4fa0cf7e 100644 --- a/dev-test/githunt/typed-document-nodes.ts +++ b/dev-test/githunt/typed-document-nodes.ts @@ -1,179 +1,9 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A comment about an entry, submitted by a user */ -export type Comment = { - __typename?: 'Comment'; - /** The text of the comment */ - content: Scalars['String']['output']; - /** A timestamp of when the comment was posted */ - createdAt: Scalars['Float']['output']; - /** The SQL ID of this entry */ - id: Scalars['Int']['output']; - /** The GitHub user who posted the comment */ - postedBy: User; - /** The repository which this comment is about */ - repoName: Scalars['String']['output']; -}; - -/** Information about a GitHub repository submitted to GitHunt */ -export type Entry = { - __typename?: 'Entry'; - /** The number of comments posted about this repository */ - commentCount: Scalars['Int']['output']; - /** Comments posted about this repository */ - comments: Array>; - /** A timestamp of when the entry was submitted */ - createdAt: Scalars['Float']['output']; - /** The hot score of this repository */ - hotScore: Scalars['Float']['output']; - /** The SQL ID of this entry */ - id: Scalars['Int']['output']; - /** The GitHub user who submitted this entry */ - postedBy: User; - /** Information about the repository from GitHub */ - repository: Repository; - /** The score of this repository, upvotes - downvotes */ - score: Scalars['Int']['output']; - /** XXX to be changed */ - vote: Vote; -}; - -/** Information about a GitHub repository submitted to GitHunt */ -export type EntryCommentsArgs = { - limit?: InputMaybe; - offset?: InputMaybe; -}; - -/** A list of options for the sort order of the feed */ -export enum FeedType { - /** Sort by a combination of freshness and score, using Reddit's algorithm */ - Hot = 'HOT', - /** Newest entries first */ - New = 'NEW', - /** Highest score entries first */ - Top = 'TOP', -} - -export type Mutation = { - __typename?: 'Mutation'; - /** Comment on a repository, returns the new comment */ - submitComment?: Maybe; - /** Submit a new repository, returns the new submission */ - submitRepository?: Maybe; - /** Vote on a repository submission, returns the submission that was voted on */ - vote?: Maybe; -}; - -export type MutationSubmitCommentArgs = { - commentContent: Scalars['String']['input']; - repoFullName: Scalars['String']['input']; -}; - -export type MutationSubmitRepositoryArgs = { - repoFullName: Scalars['String']['input']; -}; - -export type MutationVoteArgs = { - repoFullName: Scalars['String']['input']; - type: VoteType; -}; - -export type Query = { - __typename?: 'Query'; - /** Return the currently logged in user, or null if nobody is logged in */ - currentUser?: Maybe; - /** A single entry */ - entry?: Maybe; - /** A feed of repository submissions */ - feed?: Maybe>>; -}; - -export type QueryEntryArgs = { - repoFullName: Scalars['String']['input']; -}; - -export type QueryFeedArgs = { - limit?: InputMaybe; - offset?: InputMaybe; - type: FeedType; -}; - -/** - * A repository object from the GitHub API. This uses the exact field names returned by the - * GitHub API for simplicity, even though the convention for GraphQL is usually to camel case. - */ -export type Repository = { - __typename?: 'Repository'; - /** The description of the repository */ - description?: Maybe; - /** The full name of the repository with the username, e.g. apollostack/GitHunt-API */ - full_name: Scalars['String']['output']; - /** The link to the repository on GitHub */ - html_url: Scalars['String']['output']; - /** Just the name of the repository, e.g. GitHunt-API */ - name: Scalars['String']['output']; - /** The number of open issues on this repository on GitHub */ - open_issues_count?: Maybe; - /** The owner of this repository on GitHub, e.g. apollostack */ - owner?: Maybe; - /** The number of people who have starred this repository on GitHub */ - stargazers_count: Scalars['Int']['output']; -}; - -export type Subscription = { - __typename?: 'Subscription'; - /** Subscription fires on every comment added */ - commentAdded?: Maybe; -}; - -export type SubscriptionCommentAddedArgs = { - repoFullName: Scalars['String']['input']; -}; - -/** A user object from the GitHub API. This uses the exact field names returned from the GitHub API. */ -export type User = { - __typename?: 'User'; - /** The URL to a directly embeddable image for this user's avatar */ - avatar_url: Scalars['String']['output']; - /** The URL of this user's GitHub page */ - html_url: Scalars['String']['output']; - /** The name of the user, e.g. apollostack */ - login: Scalars['String']['output']; -}; - -/** XXX to be removed */ -export type Vote = { - __typename?: 'Vote'; - vote_value: Scalars['Int']['output']; -}; - -/** The type of vote to record, when submitting a vote */ -export enum VoteType { - Cancel = 'CANCEL', - Down = 'DOWN', - Up = 'UP', -} - export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.avoidOptionals.ts b/dev-test/githunt/types.avoidOptionals.ts index 0612dfd6890..0a1908ad3af 100644 --- a/dev-test/githunt/types.avoidOptionals.ts +++ b/dev-test/githunt/types.avoidOptionals.ts @@ -1,177 +1,7 @@ -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A comment about an entry, submitted by a user */ -export type Comment = { - __typename?: 'Comment'; - /** The text of the comment */ - content: Scalars['String']['output']; - /** A timestamp of when the comment was posted */ - createdAt: Scalars['Float']['output']; - /** The SQL ID of this entry */ - id: Scalars['Int']['output']; - /** The GitHub user who posted the comment */ - postedBy: User; - /** The repository which this comment is about */ - repoName: Scalars['String']['output']; -}; - -/** Information about a GitHub repository submitted to GitHunt */ -export type Entry = { - __typename?: 'Entry'; - /** The number of comments posted about this repository */ - commentCount: Scalars['Int']['output']; - /** Comments posted about this repository */ - comments: Array>; - /** A timestamp of when the entry was submitted */ - createdAt: Scalars['Float']['output']; - /** The hot score of this repository */ - hotScore: Scalars['Float']['output']; - /** The SQL ID of this entry */ - id: Scalars['Int']['output']; - /** The GitHub user who submitted this entry */ - postedBy: User; - /** Information about the repository from GitHub */ - repository: Repository; - /** The score of this repository, upvotes - downvotes */ - score: Scalars['Int']['output']; - /** XXX to be changed */ - vote: Vote; -}; - -/** Information about a GitHub repository submitted to GitHunt */ -export type EntryCommentsArgs = { - limit: InputMaybe; - offset: InputMaybe; -}; - -/** A list of options for the sort order of the feed */ -export enum FeedType { - /** Sort by a combination of freshness and score, using Reddit's algorithm */ - Hot = 'HOT', - /** Newest entries first */ - New = 'NEW', - /** Highest score entries first */ - Top = 'TOP', -} - -export type Mutation = { - __typename?: 'Mutation'; - /** Comment on a repository, returns the new comment */ - submitComment: Maybe; - /** Submit a new repository, returns the new submission */ - submitRepository: Maybe; - /** Vote on a repository submission, returns the submission that was voted on */ - vote: Maybe; -}; - -export type MutationSubmitCommentArgs = { - commentContent: Scalars['String']['input']; - repoFullName: Scalars['String']['input']; -}; - -export type MutationSubmitRepositoryArgs = { - repoFullName: Scalars['String']['input']; -}; - -export type MutationVoteArgs = { - repoFullName: Scalars['String']['input']; - type: VoteType; -}; - -export type Query = { - __typename?: 'Query'; - /** Return the currently logged in user, or null if nobody is logged in */ - currentUser: Maybe; - /** A single entry */ - entry: Maybe; - /** A feed of repository submissions */ - feed: Maybe>>; -}; - -export type QueryEntryArgs = { - repoFullName: Scalars['String']['input']; -}; - -export type QueryFeedArgs = { - limit: InputMaybe; - offset: InputMaybe; - type: FeedType; -}; - -/** - * A repository object from the GitHub API. This uses the exact field names returned by the - * GitHub API for simplicity, even though the convention for GraphQL is usually to camel case. - */ -export type Repository = { - __typename?: 'Repository'; - /** The description of the repository */ - description: Maybe; - /** The full name of the repository with the username, e.g. apollostack/GitHunt-API */ - full_name: Scalars['String']['output']; - /** The link to the repository on GitHub */ - html_url: Scalars['String']['output']; - /** Just the name of the repository, e.g. GitHunt-API */ - name: Scalars['String']['output']; - /** The number of open issues on this repository on GitHub */ - open_issues_count: Maybe; - /** The owner of this repository on GitHub, e.g. apollostack */ - owner: Maybe; - /** The number of people who have starred this repository on GitHub */ - stargazers_count: Scalars['Int']['output']; -}; - -export type Subscription = { - __typename?: 'Subscription'; - /** Subscription fires on every comment added */ - commentAdded: Maybe; -}; - -export type SubscriptionCommentAddedArgs = { - repoFullName: Scalars['String']['input']; -}; - -/** A user object from the GitHub API. This uses the exact field names returned from the GitHub API. */ -export type User = { - __typename?: 'User'; - /** The URL to a directly embeddable image for this user's avatar */ - avatar_url: Scalars['String']['output']; - /** The URL of this user's GitHub page */ - html_url: Scalars['String']['output']; - /** The name of the user, e.g. apollostack */ - login: Scalars['String']['output']; -}; - -/** XXX to be removed */ -export type Vote = { - __typename?: 'Vote'; - vote_value: Scalars['Int']['output']; -}; - -/** The type of vote to record, when submitting a vote */ -export enum VoteType { - Cancel = 'CANCEL', - Down = 'DOWN', - Up = 'UP', -} - export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.d.ts b/dev-test/githunt/types.d.ts index 3e669417bac..ec2ba3f599b 100644 --- a/dev-test/githunt/types.d.ts +++ b/dev-test/githunt/types.d.ts @@ -1,172 +1,7 @@ -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A comment about an entry, submitted by a user */ -export type Comment = { - __typename?: 'Comment'; - /** The text of the comment */ - content: Scalars['String']['output']; - /** A timestamp of when the comment was posted */ - createdAt: Scalars['Float']['output']; - /** The SQL ID of this entry */ - id: Scalars['Int']['output']; - /** The GitHub user who posted the comment */ - postedBy: User; - /** The repository which this comment is about */ - repoName: Scalars['String']['output']; -}; - -/** Information about a GitHub repository submitted to GitHunt */ -export type Entry = { - __typename?: 'Entry'; - /** The number of comments posted about this repository */ - commentCount: Scalars['Int']['output']; - /** Comments posted about this repository */ - comments: Array>; - /** A timestamp of when the entry was submitted */ - createdAt: Scalars['Float']['output']; - /** The hot score of this repository */ - hotScore: Scalars['Float']['output']; - /** The SQL ID of this entry */ - id: Scalars['Int']['output']; - /** The GitHub user who submitted this entry */ - postedBy: User; - /** Information about the repository from GitHub */ - repository: Repository; - /** The score of this repository, upvotes - downvotes */ - score: Scalars['Int']['output']; - /** XXX to be changed */ - vote: Vote; -}; - -/** Information about a GitHub repository submitted to GitHunt */ -export type EntryCommentsArgs = { - limit?: InputMaybe; - offset?: InputMaybe; -}; - -/** A list of options for the sort order of the feed */ -export type FeedType = - /** Sort by a combination of freshness and score, using Reddit's algorithm */ - | 'HOT' - /** Newest entries first */ - | 'NEW' - /** Highest score entries first */ - | 'TOP'; - -export type Mutation = { - __typename?: 'Mutation'; - /** Comment on a repository, returns the new comment */ - submitComment?: Maybe; - /** Submit a new repository, returns the new submission */ - submitRepository?: Maybe; - /** Vote on a repository submission, returns the submission that was voted on */ - vote?: Maybe; -}; - -export type MutationSubmitCommentArgs = { - commentContent: Scalars['String']['input']; - repoFullName: Scalars['String']['input']; -}; - -export type MutationSubmitRepositoryArgs = { - repoFullName: Scalars['String']['input']; -}; - -export type MutationVoteArgs = { - repoFullName: Scalars['String']['input']; - type: VoteType; -}; - -export type Query = { - __typename?: 'Query'; - /** Return the currently logged in user, or null if nobody is logged in */ - currentUser?: Maybe; - /** A single entry */ - entry?: Maybe; - /** A feed of repository submissions */ - feed?: Maybe>>; -}; - -export type QueryEntryArgs = { - repoFullName: Scalars['String']['input']; -}; - -export type QueryFeedArgs = { - limit?: InputMaybe; - offset?: InputMaybe; - type: FeedType; -}; - -/** - * A repository object from the GitHub API. This uses the exact field names returned by the - * GitHub API for simplicity, even though the convention for GraphQL is usually to camel case. - */ -export type Repository = { - __typename?: 'Repository'; - /** The description of the repository */ - description?: Maybe; - /** The full name of the repository with the username, e.g. apollostack/GitHunt-API */ - full_name: Scalars['String']['output']; - /** The link to the repository on GitHub */ - html_url: Scalars['String']['output']; - /** Just the name of the repository, e.g. GitHunt-API */ - name: Scalars['String']['output']; - /** The number of open issues on this repository on GitHub */ - open_issues_count?: Maybe; - /** The owner of this repository on GitHub, e.g. apollostack */ - owner?: Maybe; - /** The number of people who have starred this repository on GitHub */ - stargazers_count: Scalars['Int']['output']; -}; - -export type Subscription = { - __typename?: 'Subscription'; - /** Subscription fires on every comment added */ - commentAdded?: Maybe; -}; - -export type SubscriptionCommentAddedArgs = { - repoFullName: Scalars['String']['input']; -}; - -/** A user object from the GitHub API. This uses the exact field names returned from the GitHub API. */ -export type User = { - __typename?: 'User'; - /** The URL to a directly embeddable image for this user's avatar */ - avatar_url: Scalars['String']['output']; - /** The URL of this user's GitHub page */ - html_url: Scalars['String']['output']; - /** The name of the user, e.g. apollostack */ - login: Scalars['String']['output']; -}; - -/** XXX to be removed */ -export type Vote = { - __typename?: 'Vote'; - vote_value: Scalars['Int']['output']; -}; - -/** The type of vote to record, when submitting a vote */ -export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; - export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.enumsAsTypes.ts b/dev-test/githunt/types.enumsAsTypes.ts index 3e669417bac..ec2ba3f599b 100644 --- a/dev-test/githunt/types.enumsAsTypes.ts +++ b/dev-test/githunt/types.enumsAsTypes.ts @@ -1,172 +1,7 @@ -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A comment about an entry, submitted by a user */ -export type Comment = { - __typename?: 'Comment'; - /** The text of the comment */ - content: Scalars['String']['output']; - /** A timestamp of when the comment was posted */ - createdAt: Scalars['Float']['output']; - /** The SQL ID of this entry */ - id: Scalars['Int']['output']; - /** The GitHub user who posted the comment */ - postedBy: User; - /** The repository which this comment is about */ - repoName: Scalars['String']['output']; -}; - -/** Information about a GitHub repository submitted to GitHunt */ -export type Entry = { - __typename?: 'Entry'; - /** The number of comments posted about this repository */ - commentCount: Scalars['Int']['output']; - /** Comments posted about this repository */ - comments: Array>; - /** A timestamp of when the entry was submitted */ - createdAt: Scalars['Float']['output']; - /** The hot score of this repository */ - hotScore: Scalars['Float']['output']; - /** The SQL ID of this entry */ - id: Scalars['Int']['output']; - /** The GitHub user who submitted this entry */ - postedBy: User; - /** Information about the repository from GitHub */ - repository: Repository; - /** The score of this repository, upvotes - downvotes */ - score: Scalars['Int']['output']; - /** XXX to be changed */ - vote: Vote; -}; - -/** Information about a GitHub repository submitted to GitHunt */ -export type EntryCommentsArgs = { - limit?: InputMaybe; - offset?: InputMaybe; -}; - -/** A list of options for the sort order of the feed */ -export type FeedType = - /** Sort by a combination of freshness and score, using Reddit's algorithm */ - | 'HOT' - /** Newest entries first */ - | 'NEW' - /** Highest score entries first */ - | 'TOP'; - -export type Mutation = { - __typename?: 'Mutation'; - /** Comment on a repository, returns the new comment */ - submitComment?: Maybe; - /** Submit a new repository, returns the new submission */ - submitRepository?: Maybe; - /** Vote on a repository submission, returns the submission that was voted on */ - vote?: Maybe; -}; - -export type MutationSubmitCommentArgs = { - commentContent: Scalars['String']['input']; - repoFullName: Scalars['String']['input']; -}; - -export type MutationSubmitRepositoryArgs = { - repoFullName: Scalars['String']['input']; -}; - -export type MutationVoteArgs = { - repoFullName: Scalars['String']['input']; - type: VoteType; -}; - -export type Query = { - __typename?: 'Query'; - /** Return the currently logged in user, or null if nobody is logged in */ - currentUser?: Maybe; - /** A single entry */ - entry?: Maybe; - /** A feed of repository submissions */ - feed?: Maybe>>; -}; - -export type QueryEntryArgs = { - repoFullName: Scalars['String']['input']; -}; - -export type QueryFeedArgs = { - limit?: InputMaybe; - offset?: InputMaybe; - type: FeedType; -}; - -/** - * A repository object from the GitHub API. This uses the exact field names returned by the - * GitHub API for simplicity, even though the convention for GraphQL is usually to camel case. - */ -export type Repository = { - __typename?: 'Repository'; - /** The description of the repository */ - description?: Maybe; - /** The full name of the repository with the username, e.g. apollostack/GitHunt-API */ - full_name: Scalars['String']['output']; - /** The link to the repository on GitHub */ - html_url: Scalars['String']['output']; - /** Just the name of the repository, e.g. GitHunt-API */ - name: Scalars['String']['output']; - /** The number of open issues on this repository on GitHub */ - open_issues_count?: Maybe; - /** The owner of this repository on GitHub, e.g. apollostack */ - owner?: Maybe; - /** The number of people who have starred this repository on GitHub */ - stargazers_count: Scalars['Int']['output']; -}; - -export type Subscription = { - __typename?: 'Subscription'; - /** Subscription fires on every comment added */ - commentAdded?: Maybe; -}; - -export type SubscriptionCommentAddedArgs = { - repoFullName: Scalars['String']['input']; -}; - -/** A user object from the GitHub API. This uses the exact field names returned from the GitHub API. */ -export type User = { - __typename?: 'User'; - /** The URL to a directly embeddable image for this user's avatar */ - avatar_url: Scalars['String']['output']; - /** The URL of this user's GitHub page */ - html_url: Scalars['String']['output']; - /** The name of the user, e.g. apollostack */ - login: Scalars['String']['output']; -}; - -/** XXX to be removed */ -export type Vote = { - __typename?: 'Vote'; - vote_value: Scalars['Int']['output']; -}; - -/** The type of vote to record, when submitting a vote */ -export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; - export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.flatten.preResolveTypes.ts b/dev-test/githunt/types.flatten.preResolveTypes.ts index 48e7f922615..feed22b3cf5 100644 --- a/dev-test/githunt/types.flatten.preResolveTypes.ts +++ b/dev-test/githunt/types.flatten.preResolveTypes.ts @@ -1,177 +1,7 @@ -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A comment about an entry, submitted by a user */ -export type Comment = { - __typename?: 'Comment'; - /** The text of the comment */ - content: Scalars['String']['output']; - /** A timestamp of when the comment was posted */ - createdAt: Scalars['Float']['output']; - /** The SQL ID of this entry */ - id: Scalars['Int']['output']; - /** The GitHub user who posted the comment */ - postedBy: User; - /** The repository which this comment is about */ - repoName: Scalars['String']['output']; -}; - -/** Information about a GitHub repository submitted to GitHunt */ -export type Entry = { - __typename?: 'Entry'; - /** The number of comments posted about this repository */ - commentCount: Scalars['Int']['output']; - /** Comments posted about this repository */ - comments: Array>; - /** A timestamp of when the entry was submitted */ - createdAt: Scalars['Float']['output']; - /** The hot score of this repository */ - hotScore: Scalars['Float']['output']; - /** The SQL ID of this entry */ - id: Scalars['Int']['output']; - /** The GitHub user who submitted this entry */ - postedBy: User; - /** Information about the repository from GitHub */ - repository: Repository; - /** The score of this repository, upvotes - downvotes */ - score: Scalars['Int']['output']; - /** XXX to be changed */ - vote: Vote; -}; - -/** Information about a GitHub repository submitted to GitHunt */ -export type EntryCommentsArgs = { - limit?: InputMaybe; - offset?: InputMaybe; -}; - -/** A list of options for the sort order of the feed */ -export enum FeedType { - /** Sort by a combination of freshness and score, using Reddit's algorithm */ - Hot = 'HOT', - /** Newest entries first */ - New = 'NEW', - /** Highest score entries first */ - Top = 'TOP', -} - -export type Mutation = { - __typename?: 'Mutation'; - /** Comment on a repository, returns the new comment */ - submitComment?: Maybe; - /** Submit a new repository, returns the new submission */ - submitRepository?: Maybe; - /** Vote on a repository submission, returns the submission that was voted on */ - vote?: Maybe; -}; - -export type MutationSubmitCommentArgs = { - commentContent: Scalars['String']['input']; - repoFullName: Scalars['String']['input']; -}; - -export type MutationSubmitRepositoryArgs = { - repoFullName: Scalars['String']['input']; -}; - -export type MutationVoteArgs = { - repoFullName: Scalars['String']['input']; - type: VoteType; -}; - -export type Query = { - __typename?: 'Query'; - /** Return the currently logged in user, or null if nobody is logged in */ - currentUser?: Maybe; - /** A single entry */ - entry?: Maybe; - /** A feed of repository submissions */ - feed?: Maybe>>; -}; - -export type QueryEntryArgs = { - repoFullName: Scalars['String']['input']; -}; - -export type QueryFeedArgs = { - limit?: InputMaybe; - offset?: InputMaybe; - type: FeedType; -}; - -/** - * A repository object from the GitHub API. This uses the exact field names returned by the - * GitHub API for simplicity, even though the convention for GraphQL is usually to camel case. - */ -export type Repository = { - __typename?: 'Repository'; - /** The description of the repository */ - description?: Maybe; - /** The full name of the repository with the username, e.g. apollostack/GitHunt-API */ - full_name: Scalars['String']['output']; - /** The link to the repository on GitHub */ - html_url: Scalars['String']['output']; - /** Just the name of the repository, e.g. GitHunt-API */ - name: Scalars['String']['output']; - /** The number of open issues on this repository on GitHub */ - open_issues_count?: Maybe; - /** The owner of this repository on GitHub, e.g. apollostack */ - owner?: Maybe; - /** The number of people who have starred this repository on GitHub */ - stargazers_count: Scalars['Int']['output']; -}; - -export type Subscription = { - __typename?: 'Subscription'; - /** Subscription fires on every comment added */ - commentAdded?: Maybe; -}; - -export type SubscriptionCommentAddedArgs = { - repoFullName: Scalars['String']['input']; -}; - -/** A user object from the GitHub API. This uses the exact field names returned from the GitHub API. */ -export type User = { - __typename?: 'User'; - /** The URL to a directly embeddable image for this user's avatar */ - avatar_url: Scalars['String']['output']; - /** The URL of this user's GitHub page */ - html_url: Scalars['String']['output']; - /** The name of the user, e.g. apollostack */ - login: Scalars['String']['output']; -}; - -/** XXX to be removed */ -export type Vote = { - __typename?: 'Vote'; - vote_value: Scalars['Int']['output']; -}; - -/** The type of vote to record, when submitting a vote */ -export enum VoteType { - Cancel = 'CANCEL', - Down = 'DOWN', - Up = 'UP', -} - export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.immutableTypes.ts b/dev-test/githunt/types.immutableTypes.ts index 15205c69630..78425b31023 100644 --- a/dev-test/githunt/types.immutableTypes.ts +++ b/dev-test/githunt/types.immutableTypes.ts @@ -1,177 +1,7 @@ -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A comment about an entry, submitted by a user */ -export type Comment = { - readonly __typename?: 'Comment'; - /** The text of the comment */ - readonly content: Scalars['String']['output']; - /** A timestamp of when the comment was posted */ - readonly createdAt: Scalars['Float']['output']; - /** The SQL ID of this entry */ - readonly id: Scalars['Int']['output']; - /** The GitHub user who posted the comment */ - readonly postedBy: User; - /** The repository which this comment is about */ - readonly repoName: Scalars['String']['output']; -}; - -/** Information about a GitHub repository submitted to GitHunt */ -export type Entry = { - readonly __typename?: 'Entry'; - /** The number of comments posted about this repository */ - readonly commentCount: Scalars['Int']['output']; - /** Comments posted about this repository */ - readonly comments: ReadonlyArray>; - /** A timestamp of when the entry was submitted */ - readonly createdAt: Scalars['Float']['output']; - /** The hot score of this repository */ - readonly hotScore: Scalars['Float']['output']; - /** The SQL ID of this entry */ - readonly id: Scalars['Int']['output']; - /** The GitHub user who submitted this entry */ - readonly postedBy: User; - /** Information about the repository from GitHub */ - readonly repository: Repository; - /** The score of this repository, upvotes - downvotes */ - readonly score: Scalars['Int']['output']; - /** XXX to be changed */ - readonly vote: Vote; -}; - -/** Information about a GitHub repository submitted to GitHunt */ -export type EntryCommentsArgs = { - limit?: InputMaybe; - offset?: InputMaybe; -}; - -/** A list of options for the sort order of the feed */ -export enum FeedType { - /** Sort by a combination of freshness and score, using Reddit's algorithm */ - Hot = 'HOT', - /** Newest entries first */ - New = 'NEW', - /** Highest score entries first */ - Top = 'TOP', -} - -export type Mutation = { - readonly __typename?: 'Mutation'; - /** Comment on a repository, returns the new comment */ - readonly submitComment?: Maybe; - /** Submit a new repository, returns the new submission */ - readonly submitRepository?: Maybe; - /** Vote on a repository submission, returns the submission that was voted on */ - readonly vote?: Maybe; -}; - -export type MutationSubmitCommentArgs = { - commentContent: Scalars['String']['input']; - repoFullName: Scalars['String']['input']; -}; - -export type MutationSubmitRepositoryArgs = { - repoFullName: Scalars['String']['input']; -}; - -export type MutationVoteArgs = { - repoFullName: Scalars['String']['input']; - type: VoteType; -}; - -export type Query = { - readonly __typename?: 'Query'; - /** Return the currently logged in user, or null if nobody is logged in */ - readonly currentUser?: Maybe; - /** A single entry */ - readonly entry?: Maybe; - /** A feed of repository submissions */ - readonly feed?: Maybe>>; -}; - -export type QueryEntryArgs = { - repoFullName: Scalars['String']['input']; -}; - -export type QueryFeedArgs = { - limit?: InputMaybe; - offset?: InputMaybe; - type: FeedType; -}; - -/** - * A repository object from the GitHub API. This uses the exact field names returned by the - * GitHub API for simplicity, even though the convention for GraphQL is usually to camel case. - */ -export type Repository = { - readonly __typename?: 'Repository'; - /** The description of the repository */ - readonly description?: Maybe; - /** The full name of the repository with the username, e.g. apollostack/GitHunt-API */ - readonly full_name: Scalars['String']['output']; - /** The link to the repository on GitHub */ - readonly html_url: Scalars['String']['output']; - /** Just the name of the repository, e.g. GitHunt-API */ - readonly name: Scalars['String']['output']; - /** The number of open issues on this repository on GitHub */ - readonly open_issues_count?: Maybe; - /** The owner of this repository on GitHub, e.g. apollostack */ - readonly owner?: Maybe; - /** The number of people who have starred this repository on GitHub */ - readonly stargazers_count: Scalars['Int']['output']; -}; - -export type Subscription = { - readonly __typename?: 'Subscription'; - /** Subscription fires on every comment added */ - readonly commentAdded?: Maybe; -}; - -export type SubscriptionCommentAddedArgs = { - repoFullName: Scalars['String']['input']; -}; - -/** A user object from the GitHub API. This uses the exact field names returned from the GitHub API. */ -export type User = { - readonly __typename?: 'User'; - /** The URL to a directly embeddable image for this user's avatar */ - readonly avatar_url: Scalars['String']['output']; - /** The URL of this user's GitHub page */ - readonly html_url: Scalars['String']['output']; - /** The name of the user, e.g. apollostack */ - readonly login: Scalars['String']['output']; -}; - -/** XXX to be removed */ -export type Vote = { - readonly __typename?: 'Vote'; - readonly vote_value: Scalars['Int']['output']; -}; - -/** The type of vote to record, when submitting a vote */ -export enum VoteType { - Cancel = 'CANCEL', - Down = 'DOWN', - Up = 'UP', -} - export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts index f83e95365e0..ec2ba3f599b 100644 --- a/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts @@ -1,40 +1,7 @@ -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A list of options for the sort order of the feed */ -export enum FeedType { - /** Sort by a combination of freshness and score, using Reddit's algorithm */ - Hot = 'HOT', - /** Newest entries first */ - New = 'NEW', - /** Highest score entries first */ - Top = 'TOP', -} - -/** The type of vote to record, when submitting a vote */ -export enum VoteType { - Cancel = 'CANCEL', - Down = 'DOWN', - Up = 'UP', -} - export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.preResolveTypes.ts b/dev-test/githunt/types.preResolveTypes.ts index 7c7f591cd75..ec2ba3f599b 100644 --- a/dev-test/githunt/types.preResolveTypes.ts +++ b/dev-test/githunt/types.preResolveTypes.ts @@ -1,177 +1,7 @@ -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A comment about an entry, submitted by a user */ -export type Comment = { - __typename?: 'Comment'; - /** The text of the comment */ - content: Scalars['String']['output']; - /** A timestamp of when the comment was posted */ - createdAt: Scalars['Float']['output']; - /** The SQL ID of this entry */ - id: Scalars['Int']['output']; - /** The GitHub user who posted the comment */ - postedBy: User; - /** The repository which this comment is about */ - repoName: Scalars['String']['output']; -}; - -/** Information about a GitHub repository submitted to GitHunt */ -export type Entry = { - __typename?: 'Entry'; - /** The number of comments posted about this repository */ - commentCount: Scalars['Int']['output']; - /** Comments posted about this repository */ - comments: Array>; - /** A timestamp of when the entry was submitted */ - createdAt: Scalars['Float']['output']; - /** The hot score of this repository */ - hotScore: Scalars['Float']['output']; - /** The SQL ID of this entry */ - id: Scalars['Int']['output']; - /** The GitHub user who submitted this entry */ - postedBy: User; - /** Information about the repository from GitHub */ - repository: Repository; - /** The score of this repository, upvotes - downvotes */ - score: Scalars['Int']['output']; - /** XXX to be changed */ - vote: Vote; -}; - -/** Information about a GitHub repository submitted to GitHunt */ -export type EntryCommentsArgs = { - limit?: InputMaybe; - offset?: InputMaybe; -}; - -/** A list of options for the sort order of the feed */ -export enum FeedType { - /** Sort by a combination of freshness and score, using Reddit's algorithm */ - Hot = 'HOT', - /** Newest entries first */ - New = 'NEW', - /** Highest score entries first */ - Top = 'TOP', -} - -export type Mutation = { - __typename?: 'Mutation'; - /** Comment on a repository, returns the new comment */ - submitComment?: Maybe; - /** Submit a new repository, returns the new submission */ - submitRepository?: Maybe; - /** Vote on a repository submission, returns the submission that was voted on */ - vote?: Maybe; -}; - -export type MutationSubmitCommentArgs = { - commentContent: Scalars['String']['input']; - repoFullName: Scalars['String']['input']; -}; - -export type MutationSubmitRepositoryArgs = { - repoFullName: Scalars['String']['input']; -}; - -export type MutationVoteArgs = { - repoFullName: Scalars['String']['input']; - type: VoteType; -}; - -export type Query = { - __typename?: 'Query'; - /** Return the currently logged in user, or null if nobody is logged in */ - currentUser?: Maybe; - /** A single entry */ - entry?: Maybe; - /** A feed of repository submissions */ - feed?: Maybe>>; -}; - -export type QueryEntryArgs = { - repoFullName: Scalars['String']['input']; -}; - -export type QueryFeedArgs = { - limit?: InputMaybe; - offset?: InputMaybe; - type: FeedType; -}; - -/** - * A repository object from the GitHub API. This uses the exact field names returned by the - * GitHub API for simplicity, even though the convention for GraphQL is usually to camel case. - */ -export type Repository = { - __typename?: 'Repository'; - /** The description of the repository */ - description?: Maybe; - /** The full name of the repository with the username, e.g. apollostack/GitHunt-API */ - full_name: Scalars['String']['output']; - /** The link to the repository on GitHub */ - html_url: Scalars['String']['output']; - /** Just the name of the repository, e.g. GitHunt-API */ - name: Scalars['String']['output']; - /** The number of open issues on this repository on GitHub */ - open_issues_count?: Maybe; - /** The owner of this repository on GitHub, e.g. apollostack */ - owner?: Maybe; - /** The number of people who have starred this repository on GitHub */ - stargazers_count: Scalars['Int']['output']; -}; - -export type Subscription = { - __typename?: 'Subscription'; - /** Subscription fires on every comment added */ - commentAdded?: Maybe; -}; - -export type SubscriptionCommentAddedArgs = { - repoFullName: Scalars['String']['input']; -}; - -/** A user object from the GitHub API. This uses the exact field names returned from the GitHub API. */ -export type User = { - __typename?: 'User'; - /** The URL to a directly embeddable image for this user's avatar */ - avatar_url: Scalars['String']['output']; - /** The URL of this user's GitHub page */ - html_url: Scalars['String']['output']; - /** The name of the user, e.g. apollostack */ - login: Scalars['String']['output']; -}; - -/** XXX to be removed */ -export type Vote = { - __typename?: 'Vote'; - vote_value: Scalars['Int']['output']; -}; - -/** The type of vote to record, when submitting a vote */ -export enum VoteType { - Cancel = 'CANCEL', - Down = 'DOWN', - Up = 'UP', -} - export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.ts b/dev-test/githunt/types.ts index 7c7f591cd75..ec2ba3f599b 100644 --- a/dev-test/githunt/types.ts +++ b/dev-test/githunt/types.ts @@ -1,177 +1,7 @@ -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A comment about an entry, submitted by a user */ -export type Comment = { - __typename?: 'Comment'; - /** The text of the comment */ - content: Scalars['String']['output']; - /** A timestamp of when the comment was posted */ - createdAt: Scalars['Float']['output']; - /** The SQL ID of this entry */ - id: Scalars['Int']['output']; - /** The GitHub user who posted the comment */ - postedBy: User; - /** The repository which this comment is about */ - repoName: Scalars['String']['output']; -}; - -/** Information about a GitHub repository submitted to GitHunt */ -export type Entry = { - __typename?: 'Entry'; - /** The number of comments posted about this repository */ - commentCount: Scalars['Int']['output']; - /** Comments posted about this repository */ - comments: Array>; - /** A timestamp of when the entry was submitted */ - createdAt: Scalars['Float']['output']; - /** The hot score of this repository */ - hotScore: Scalars['Float']['output']; - /** The SQL ID of this entry */ - id: Scalars['Int']['output']; - /** The GitHub user who submitted this entry */ - postedBy: User; - /** Information about the repository from GitHub */ - repository: Repository; - /** The score of this repository, upvotes - downvotes */ - score: Scalars['Int']['output']; - /** XXX to be changed */ - vote: Vote; -}; - -/** Information about a GitHub repository submitted to GitHunt */ -export type EntryCommentsArgs = { - limit?: InputMaybe; - offset?: InputMaybe; -}; - -/** A list of options for the sort order of the feed */ -export enum FeedType { - /** Sort by a combination of freshness and score, using Reddit's algorithm */ - Hot = 'HOT', - /** Newest entries first */ - New = 'NEW', - /** Highest score entries first */ - Top = 'TOP', -} - -export type Mutation = { - __typename?: 'Mutation'; - /** Comment on a repository, returns the new comment */ - submitComment?: Maybe; - /** Submit a new repository, returns the new submission */ - submitRepository?: Maybe; - /** Vote on a repository submission, returns the submission that was voted on */ - vote?: Maybe; -}; - -export type MutationSubmitCommentArgs = { - commentContent: Scalars['String']['input']; - repoFullName: Scalars['String']['input']; -}; - -export type MutationSubmitRepositoryArgs = { - repoFullName: Scalars['String']['input']; -}; - -export type MutationVoteArgs = { - repoFullName: Scalars['String']['input']; - type: VoteType; -}; - -export type Query = { - __typename?: 'Query'; - /** Return the currently logged in user, or null if nobody is logged in */ - currentUser?: Maybe; - /** A single entry */ - entry?: Maybe; - /** A feed of repository submissions */ - feed?: Maybe>>; -}; - -export type QueryEntryArgs = { - repoFullName: Scalars['String']['input']; -}; - -export type QueryFeedArgs = { - limit?: InputMaybe; - offset?: InputMaybe; - type: FeedType; -}; - -/** - * A repository object from the GitHub API. This uses the exact field names returned by the - * GitHub API for simplicity, even though the convention for GraphQL is usually to camel case. - */ -export type Repository = { - __typename?: 'Repository'; - /** The description of the repository */ - description?: Maybe; - /** The full name of the repository with the username, e.g. apollostack/GitHunt-API */ - full_name: Scalars['String']['output']; - /** The link to the repository on GitHub */ - html_url: Scalars['String']['output']; - /** Just the name of the repository, e.g. GitHunt-API */ - name: Scalars['String']['output']; - /** The number of open issues on this repository on GitHub */ - open_issues_count?: Maybe; - /** The owner of this repository on GitHub, e.g. apollostack */ - owner?: Maybe; - /** The number of people who have starred this repository on GitHub */ - stargazers_count: Scalars['Int']['output']; -}; - -export type Subscription = { - __typename?: 'Subscription'; - /** Subscription fires on every comment added */ - commentAdded?: Maybe; -}; - -export type SubscriptionCommentAddedArgs = { - repoFullName: Scalars['String']['input']; -}; - -/** A user object from the GitHub API. This uses the exact field names returned from the GitHub API. */ -export type User = { - __typename?: 'User'; - /** The URL to a directly embeddable image for this user's avatar */ - avatar_url: Scalars['String']['output']; - /** The URL of this user's GitHub page */ - html_url: Scalars['String']['output']; - /** The name of the user, e.g. apollostack */ - login: Scalars['String']['output']; -}; - -/** XXX to be removed */ -export type Vote = { - __typename?: 'Vote'; - vote_value: Scalars['Int']['output']; -}; - -/** The type of vote to record, when submitting a vote */ -export enum VoteType { - Cancel = 'CANCEL', - Down = 'DOWN', - Up = 'UP', -} - export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/gql-tag-operations-masking/gql/graphql.ts b/dev-test/gql-tag-operations-masking/gql/graphql.ts index 4e6a15678c2..8f6d59a3d7c 100644 --- a/dev-test/gql-tag-operations-masking/gql/graphql.ts +++ b/dev-test/gql-tag-operations-masking/gql/graphql.ts @@ -1,117 +1,10 @@ /* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; - Date: { input: any; output: any }; - Url: { input: any; output: any }; -}; - -export type Meta = { - __typename?: 'Meta'; - count?: Maybe; -}; - -export type Mutation = { - __typename?: 'Mutation'; - createTweet?: Maybe; - deleteTweet?: Maybe; - markTweetRead?: Maybe; -}; - -export type MutationCreateTweetArgs = { - body?: InputMaybe; -}; - -export type MutationDeleteTweetArgs = { - id: Scalars['ID']['input']; -}; - -export type MutationMarkTweetReadArgs = { - id: Scalars['ID']['input']; -}; - -export type Notification = { - __typename?: 'Notification'; - date?: Maybe; - id?: Maybe; - type?: Maybe; -}; - -export type Query = { - __typename?: 'Query'; - Notifications?: Maybe>>; - NotificationsMeta?: Maybe; - Tweet?: Maybe; - Tweets?: Maybe>; - TweetsMeta?: Maybe; - User?: Maybe; -}; - -export type QueryNotificationsArgs = { - limit?: InputMaybe; -}; - -export type QueryTweetArgs = { - id: Scalars['ID']['input']; -}; - -export type QueryTweetsArgs = { - limit?: InputMaybe; - skip?: InputMaybe; - sort_field?: InputMaybe; - sort_order?: InputMaybe; -}; - -export type QueryUserArgs = { - id: Scalars['ID']['input']; -}; - -export type Stat = { - __typename?: 'Stat'; - likes?: Maybe; - responses?: Maybe; - retweets?: Maybe; - views?: Maybe; -}; - -export type Tweet = { - __typename?: 'Tweet'; - Stats?: Maybe; - author: User; - body: Scalars['String']['output']; - date?: Maybe; - id: Scalars['ID']['output']; -}; - -export type User = { - __typename?: 'User'; - avatar_url?: Maybe; - first_name?: Maybe; - full_name?: Maybe; - id: Scalars['ID']['output']; - last_name?: Maybe; - /** @deprecated Field no longer supported */ - name?: Maybe; - username?: Maybe; -}; - export type TweetFragmentFragment = ({ __typename?: 'Tweet'; id: string; body: string } & { ' $fragmentRefs'?: { TweetAuthorFragmentFragment: TweetAuthorFragmentFragment }; }) & { ' $fragmentName'?: 'TweetFragmentFragment' }; diff --git a/dev-test/gql-tag-operations-urql/gql/graphql.ts b/dev-test/gql-tag-operations-urql/gql/graphql.ts index a2080173c54..13ffc0cd740 100644 --- a/dev-test/gql-tag-operations-urql/gql/graphql.ts +++ b/dev-test/gql-tag-operations-urql/gql/graphql.ts @@ -1,117 +1,10 @@ /* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; - Date: { input: any; output: any }; - Url: { input: any; output: any }; -}; - -export type Meta = { - __typename?: 'Meta'; - count?: Maybe; -}; - -export type Mutation = { - __typename?: 'Mutation'; - createTweet?: Maybe; - deleteTweet?: Maybe; - markTweetRead?: Maybe; -}; - -export type MutationCreateTweetArgs = { - body?: InputMaybe; -}; - -export type MutationDeleteTweetArgs = { - id: Scalars['ID']['input']; -}; - -export type MutationMarkTweetReadArgs = { - id: Scalars['ID']['input']; -}; - -export type Notification = { - __typename?: 'Notification'; - date?: Maybe; - id?: Maybe; - type?: Maybe; -}; - -export type Query = { - __typename?: 'Query'; - Notifications?: Maybe>>; - NotificationsMeta?: Maybe; - Tweet?: Maybe; - Tweets?: Maybe>>; - TweetsMeta?: Maybe; - User?: Maybe; -}; - -export type QueryNotificationsArgs = { - limit?: InputMaybe; -}; - -export type QueryTweetArgs = { - id: Scalars['ID']['input']; -}; - -export type QueryTweetsArgs = { - limit?: InputMaybe; - skip?: InputMaybe; - sort_field?: InputMaybe; - sort_order?: InputMaybe; -}; - -export type QueryUserArgs = { - id: Scalars['ID']['input']; -}; - -export type Stat = { - __typename?: 'Stat'; - likes?: Maybe; - responses?: Maybe; - retweets?: Maybe; - views?: Maybe; -}; - -export type Tweet = { - __typename?: 'Tweet'; - Author?: Maybe; - Stats?: Maybe; - body?: Maybe; - date?: Maybe; - id: Scalars['ID']['output']; -}; - -export type User = { - __typename?: 'User'; - avatar_url?: Maybe; - first_name?: Maybe; - full_name?: Maybe; - id: Scalars['ID']['output']; - last_name?: Maybe; - /** @deprecated Field no longer supported */ - name?: Maybe; - username?: Maybe; -}; - export type FooQueryVariables = Exact<{ [key: string]: never }>; export type FooQuery = { diff --git a/dev-test/gql-tag-operations/gql/graphql.ts b/dev-test/gql-tag-operations/gql/graphql.ts index a2080173c54..13ffc0cd740 100644 --- a/dev-test/gql-tag-operations/gql/graphql.ts +++ b/dev-test/gql-tag-operations/gql/graphql.ts @@ -1,117 +1,10 @@ /* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; - Date: { input: any; output: any }; - Url: { input: any; output: any }; -}; - -export type Meta = { - __typename?: 'Meta'; - count?: Maybe; -}; - -export type Mutation = { - __typename?: 'Mutation'; - createTweet?: Maybe; - deleteTweet?: Maybe; - markTweetRead?: Maybe; -}; - -export type MutationCreateTweetArgs = { - body?: InputMaybe; -}; - -export type MutationDeleteTweetArgs = { - id: Scalars['ID']['input']; -}; - -export type MutationMarkTweetReadArgs = { - id: Scalars['ID']['input']; -}; - -export type Notification = { - __typename?: 'Notification'; - date?: Maybe; - id?: Maybe; - type?: Maybe; -}; - -export type Query = { - __typename?: 'Query'; - Notifications?: Maybe>>; - NotificationsMeta?: Maybe; - Tweet?: Maybe; - Tweets?: Maybe>>; - TweetsMeta?: Maybe; - User?: Maybe; -}; - -export type QueryNotificationsArgs = { - limit?: InputMaybe; -}; - -export type QueryTweetArgs = { - id: Scalars['ID']['input']; -}; - -export type QueryTweetsArgs = { - limit?: InputMaybe; - skip?: InputMaybe; - sort_field?: InputMaybe; - sort_order?: InputMaybe; -}; - -export type QueryUserArgs = { - id: Scalars['ID']['input']; -}; - -export type Stat = { - __typename?: 'Stat'; - likes?: Maybe; - responses?: Maybe; - retweets?: Maybe; - views?: Maybe; -}; - -export type Tweet = { - __typename?: 'Tweet'; - Author?: Maybe; - Stats?: Maybe; - body?: Maybe; - date?: Maybe; - id: Scalars['ID']['output']; -}; - -export type User = { - __typename?: 'User'; - avatar_url?: Maybe; - first_name?: Maybe; - full_name?: Maybe; - id: Scalars['ID']['output']; - last_name?: Maybe; - /** @deprecated Field no longer supported */ - name?: Maybe; - username?: Maybe; -}; - export type FooQueryVariables = Exact<{ [key: string]: never }>; export type FooQuery = { diff --git a/dev-test/gql-tag-operations/graphql/graphql.ts b/dev-test/gql-tag-operations/graphql/graphql.ts index a2080173c54..13ffc0cd740 100644 --- a/dev-test/gql-tag-operations/graphql/graphql.ts +++ b/dev-test/gql-tag-operations/graphql/graphql.ts @@ -1,117 +1,10 @@ /* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; - Date: { input: any; output: any }; - Url: { input: any; output: any }; -}; - -export type Meta = { - __typename?: 'Meta'; - count?: Maybe; -}; - -export type Mutation = { - __typename?: 'Mutation'; - createTweet?: Maybe; - deleteTweet?: Maybe; - markTweetRead?: Maybe; -}; - -export type MutationCreateTweetArgs = { - body?: InputMaybe; -}; - -export type MutationDeleteTweetArgs = { - id: Scalars['ID']['input']; -}; - -export type MutationMarkTweetReadArgs = { - id: Scalars['ID']['input']; -}; - -export type Notification = { - __typename?: 'Notification'; - date?: Maybe; - id?: Maybe; - type?: Maybe; -}; - -export type Query = { - __typename?: 'Query'; - Notifications?: Maybe>>; - NotificationsMeta?: Maybe; - Tweet?: Maybe; - Tweets?: Maybe>>; - TweetsMeta?: Maybe; - User?: Maybe; -}; - -export type QueryNotificationsArgs = { - limit?: InputMaybe; -}; - -export type QueryTweetArgs = { - id: Scalars['ID']['input']; -}; - -export type QueryTweetsArgs = { - limit?: InputMaybe; - skip?: InputMaybe; - sort_field?: InputMaybe; - sort_order?: InputMaybe; -}; - -export type QueryUserArgs = { - id: Scalars['ID']['input']; -}; - -export type Stat = { - __typename?: 'Stat'; - likes?: Maybe; - responses?: Maybe; - retweets?: Maybe; - views?: Maybe; -}; - -export type Tweet = { - __typename?: 'Tweet'; - Author?: Maybe; - Stats?: Maybe; - body?: Maybe; - date?: Maybe; - id: Scalars['ID']['output']; -}; - -export type User = { - __typename?: 'User'; - avatar_url?: Maybe; - first_name?: Maybe; - full_name?: Maybe; - id: Scalars['ID']['output']; - last_name?: Maybe; - /** @deprecated Field no longer supported */ - name?: Maybe; - username?: Maybe; -}; - export type FooQueryVariables = Exact<{ [key: string]: never }>; export type FooQuery = { diff --git a/dev-test/standalone-operations/import-schema-types/_types.generated.ts b/dev-test/standalone-operations/import-schema-types/_types.generated.ts index f51c326a287..9c369786a25 100644 --- a/dev-test/standalone-operations/import-schema-types/_types.generated.ts +++ b/dev-test/standalone-operations/import-schema-types/_types.generated.ts @@ -1,6 +1,9 @@ -import type * as Types from './_base.generated'; +import type * as Types from './_base.generated.js'; type Exact = { [K in keyof T]: T[K] }; +export type Incremental = + | T + | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type WithVariablesQueryVariables = Exact<{ role?: Types.UserRole | null; }>; diff --git a/dev-test/star-wars/types.avoidOptionals.ts b/dev-test/star-wars/types.avoidOptionals.ts index 8a218f79265..1d68e007027 100644 --- a/dev-test/star-wars/types.avoidOptionals.ts +++ b/dev-test/star-wars/types.avoidOptionals.ts @@ -1,249 +1,7 @@ -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A character from the Star Wars universe */ -export type Character = { - /** The movies this character appears in */ - appearsIn: Array>; - /** The friends of the character, or an empty list if they have none */ - friends: Maybe>>; - /** The friends of the character exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** The ID of the character */ - id: Scalars['ID']['output']; - /** The name of the character */ - name: Scalars['String']['output']; -}; - -/** A character from the Star Wars universe */ -export type CharacterFriendsConnectionArgs = { - after: InputMaybe; - first: InputMaybe; -}; - -/** The input object sent when passing a color */ -export type ColorInput = { - blue: Scalars['Int']['input']; - green: Scalars['Int']['input']; - red: Scalars['Int']['input']; -}; - -/** An autonomous mechanical character in the Star Wars universe */ -export type Droid = Character & { - __typename?: 'Droid'; - /** The movies this droid appears in */ - appearsIn: Array>; - /** This droid's friends, or an empty list if they have none */ - friends: Maybe>>; - /** The friends of the droid exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** The ID of the droid */ - id: Scalars['ID']['output']; - /** What others call this droid */ - name: Scalars['String']['output']; - /** This droid's primary function */ - primaryFunction: Maybe; -}; - -/** An autonomous mechanical character in the Star Wars universe */ -export type DroidFriendsConnectionArgs = { - after: InputMaybe; - first: InputMaybe; -}; - -/** The episodes in the Star Wars trilogy */ -export enum Episode { - /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ - Empire = 'EMPIRE', - /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ - Jedi = 'JEDI', - /** Star Wars Episode IV: A New Hope, released in 1977. */ - Newhope = 'NEWHOPE', -} - -/** A connection object for a character's friends */ -export type FriendsConnection = { - __typename?: 'FriendsConnection'; - /** The edges for each of the character's friends. */ - edges: Maybe>>; - /** A list of the friends, as a convenience when edges are not needed. */ - friends: Maybe>>; - /** Information for paginating this connection */ - pageInfo: PageInfo; - /** The total number of friends */ - totalCount: Maybe; -}; - -/** An edge object for a character's friends */ -export type FriendsEdge = { - __typename?: 'FriendsEdge'; - /** A cursor used for pagination */ - cursor: Scalars['ID']['output']; - /** The character represented by this friendship edge */ - node: Maybe; -}; - -/** A humanoid creature from the Star Wars universe */ -export type Human = Character & { - __typename?: 'Human'; - /** The movies this human appears in */ - appearsIn: Array>; - /** This human's friends, or an empty list if they have none */ - friends: Maybe>>; - /** The friends of the human exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** Height in the preferred unit, default is meters */ - height: Maybe; - /** The home planet of the human, or null if unknown */ - homePlanet: Maybe; - /** The ID of the human */ - id: Scalars['ID']['output']; - /** Mass in kilograms, or null if unknown */ - mass: Maybe; - /** What this human calls themselves */ - name: Scalars['String']['output']; - /** A list of starships this person has piloted, or an empty list if none */ - starships: Maybe>>; -}; - -/** A humanoid creature from the Star Wars universe */ -export type HumanFriendsConnectionArgs = { - after: InputMaybe; - first: InputMaybe; -}; - -/** A humanoid creature from the Star Wars universe */ -export type HumanHeightArgs = { - unit?: InputMaybe; -}; - -/** Units of height */ -export enum LengthUnit { - /** Primarily used in the United States */ - Foot = 'FOOT', - /** The standard unit around the world */ - Meter = 'METER', -} - -/** The mutation type, represents all updates we can make to our data */ -export type Mutation = { - __typename?: 'Mutation'; - createReview: Maybe; -}; - -/** The mutation type, represents all updates we can make to our data */ -export type MutationCreateReviewArgs = { - episode: InputMaybe; - review: ReviewInput; -}; - -/** Information for paginating this connection */ -export type PageInfo = { - __typename?: 'PageInfo'; - endCursor: Maybe; - hasNextPage: Scalars['Boolean']['output']; - startCursor: Maybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type Query = { - __typename?: 'Query'; - character: Maybe; - droid: Maybe; - hero: Maybe; - human: Maybe; - reviews: Maybe>>; - search: Maybe>>; - starship: Maybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryCharacterArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryDroidArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryHeroArgs = { - episode: InputMaybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryHumanArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryReviewsArgs = { - episode: Episode; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QuerySearchArgs = { - text: InputMaybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryStarshipArgs = { - id: Scalars['ID']['input']; -}; - -/** Represents a review for a movie */ -export type Review = { - __typename?: 'Review'; - /** Comment about the movie */ - commentary: Maybe; - /** The number of stars this review gave, 1-5 */ - stars: Scalars['Int']['output']; -}; - -/** The input object sent when someone is creating a new review */ -export type ReviewInput = { - /** Comment about the movie, optional */ - commentary: InputMaybe; - /** Favorite color, optional */ - favoriteColor: InputMaybe; - /** 0-5 stars */ - stars: Scalars['Int']['input']; -}; - -export type SearchResult = Droid | Human | Starship; - -export type Starship = { - __typename?: 'Starship'; - /** The ID of the starship */ - id: Scalars['ID']['output']; - /** Length of the starship, along the longest axis */ - length: Maybe; - /** The name of the starship */ - name: Scalars['String']['output']; -}; - -export type StarshipLengthArgs = { - unit?: InputMaybe; -}; - export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.d.ts b/dev-test/star-wars/types.d.ts index 32aaf9b03e6..ac440322507 100644 --- a/dev-test/star-wars/types.d.ts +++ b/dev-test/star-wars/types.d.ts @@ -1,243 +1,4 @@ -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A character from the Star Wars universe */ -export type Character = { - /** The movies this character appears in */ - appearsIn: Array>; - /** The friends of the character, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the character exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** The ID of the character */ - id: Scalars['ID']['output']; - /** The name of the character */ - name: Scalars['String']['output']; -}; - -/** A character from the Star Wars universe */ -export type CharacterFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** The input object sent when passing a color */ -export type ColorInput = { - blue: Scalars['Int']['input']; - green: Scalars['Int']['input']; - red: Scalars['Int']['input']; -}; - -/** An autonomous mechanical character in the Star Wars universe */ -export type Droid = Character & { - __typename?: 'Droid'; - /** The movies this droid appears in */ - appearsIn: Array>; - /** This droid's friends, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the droid exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** The ID of the droid */ - id: Scalars['ID']['output']; - /** What others call this droid */ - name: Scalars['String']['output']; - /** This droid's primary function */ - primaryFunction?: Maybe; -}; - -/** An autonomous mechanical character in the Star Wars universe */ -export type DroidFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** The episodes in the Star Wars trilogy */ -export type Episode = - /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ - | 'EMPIRE' - /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ - | 'JEDI' - /** Star Wars Episode IV: A New Hope, released in 1977. */ - | 'NEWHOPE'; - -/** A connection object for a character's friends */ -export type FriendsConnection = { - __typename?: 'FriendsConnection'; - /** The edges for each of the character's friends. */ - edges?: Maybe>>; - /** A list of the friends, as a convenience when edges are not needed. */ - friends?: Maybe>>; - /** Information for paginating this connection */ - pageInfo: PageInfo; - /** The total number of friends */ - totalCount?: Maybe; -}; - -/** An edge object for a character's friends */ -export type FriendsEdge = { - __typename?: 'FriendsEdge'; - /** A cursor used for pagination */ - cursor: Scalars['ID']['output']; - /** The character represented by this friendship edge */ - node?: Maybe; -}; - -/** A humanoid creature from the Star Wars universe */ -export type Human = Character & { - __typename?: 'Human'; - /** The movies this human appears in */ - appearsIn: Array>; - /** This human's friends, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the human exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** Height in the preferred unit, default is meters */ - height?: Maybe; - /** The home planet of the human, or null if unknown */ - homePlanet?: Maybe; - /** The ID of the human */ - id: Scalars['ID']['output']; - /** Mass in kilograms, or null if unknown */ - mass?: Maybe; - /** What this human calls themselves */ - name: Scalars['String']['output']; - /** A list of starships this person has piloted, or an empty list if none */ - starships?: Maybe>>; -}; - -/** A humanoid creature from the Star Wars universe */ -export type HumanFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** A humanoid creature from the Star Wars universe */ -export type HumanHeightArgs = { - unit?: InputMaybe; -}; - -/** Units of height */ -export type LengthUnit = - /** Primarily used in the United States */ - | 'FOOT' - /** The standard unit around the world */ - | 'METER'; - -/** The mutation type, represents all updates we can make to our data */ -export type Mutation = { - __typename?: 'Mutation'; - createReview?: Maybe; -}; - -/** The mutation type, represents all updates we can make to our data */ -export type MutationCreateReviewArgs = { - episode?: InputMaybe; - review: ReviewInput; -}; - -/** Information for paginating this connection */ -export type PageInfo = { - __typename?: 'PageInfo'; - endCursor?: Maybe; - hasNextPage: Scalars['Boolean']['output']; - startCursor?: Maybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type Query = { - __typename?: 'Query'; - character?: Maybe; - droid?: Maybe; - hero?: Maybe; - human?: Maybe; - reviews?: Maybe>>; - search?: Maybe>>; - starship?: Maybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryCharacterArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryDroidArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryHeroArgs = { - episode?: InputMaybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryHumanArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryReviewsArgs = { - episode: Episode; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QuerySearchArgs = { - text?: InputMaybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryStarshipArgs = { - id: Scalars['ID']['input']; -}; - -/** Represents a review for a movie */ -export type Review = { - __typename?: 'Review'; - /** Comment about the movie */ - commentary?: Maybe; - /** The number of stars this review gave, 1-5 */ - stars: Scalars['Int']['output']; -}; - -/** The input object sent when someone is creating a new review */ -export type ReviewInput = { - /** Comment about the movie, optional */ - commentary?: InputMaybe; - /** Favorite color, optional */ - favoriteColor?: InputMaybe; - /** 0-5 stars */ - stars: Scalars['Int']['input']; -}; - -export type SearchResult = Droid | Human | Starship; - -export type Starship = { - __typename?: 'Starship'; - /** The ID of the starship */ - id: Scalars['ID']['output']; - /** Length of the starship, along the longest axis */ - length?: Maybe; - /** The name of the starship */ - name: Scalars['String']['output']; -}; - -export type StarshipLengthArgs = { - unit?: InputMaybe; -}; diff --git a/dev-test/star-wars/types.excludeQueryAlpha.ts b/dev-test/star-wars/types.excludeQueryAlpha.ts index 063e31c3a00..3ebf4d2a82e 100644 --- a/dev-test/star-wars/types.excludeQueryAlpha.ts +++ b/dev-test/star-wars/types.excludeQueryAlpha.ts @@ -1,249 +1,7 @@ -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A character from the Star Wars universe */ -export type Character = { - /** The movies this character appears in */ - appearsIn: Array>; - /** The friends of the character, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the character exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** The ID of the character */ - id: Scalars['ID']['output']; - /** The name of the character */ - name: Scalars['String']['output']; -}; - -/** A character from the Star Wars universe */ -export type CharacterFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** The input object sent when passing a color */ -export type ColorInput = { - blue: Scalars['Int']['input']; - green: Scalars['Int']['input']; - red: Scalars['Int']['input']; -}; - -/** An autonomous mechanical character in the Star Wars universe */ -export type Droid = Character & { - __typename?: 'Droid'; - /** The movies this droid appears in */ - appearsIn: Array>; - /** This droid's friends, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the droid exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** The ID of the droid */ - id: Scalars['ID']['output']; - /** What others call this droid */ - name: Scalars['String']['output']; - /** This droid's primary function */ - primaryFunction?: Maybe; -}; - -/** An autonomous mechanical character in the Star Wars universe */ -export type DroidFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** The episodes in the Star Wars trilogy */ -export enum Episode { - /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ - Empire = 'EMPIRE', - /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ - Jedi = 'JEDI', - /** Star Wars Episode IV: A New Hope, released in 1977. */ - Newhope = 'NEWHOPE', -} - -/** A connection object for a character's friends */ -export type FriendsConnection = { - __typename?: 'FriendsConnection'; - /** The edges for each of the character's friends. */ - edges?: Maybe>>; - /** A list of the friends, as a convenience when edges are not needed. */ - friends?: Maybe>>; - /** Information for paginating this connection */ - pageInfo: PageInfo; - /** The total number of friends */ - totalCount?: Maybe; -}; - -/** An edge object for a character's friends */ -export type FriendsEdge = { - __typename?: 'FriendsEdge'; - /** A cursor used for pagination */ - cursor: Scalars['ID']['output']; - /** The character represented by this friendship edge */ - node?: Maybe; -}; - -/** A humanoid creature from the Star Wars universe */ -export type Human = Character & { - __typename?: 'Human'; - /** The movies this human appears in */ - appearsIn: Array>; - /** This human's friends, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the human exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** Height in the preferred unit, default is meters */ - height?: Maybe; - /** The home planet of the human, or null if unknown */ - homePlanet?: Maybe; - /** The ID of the human */ - id: Scalars['ID']['output']; - /** Mass in kilograms, or null if unknown */ - mass?: Maybe; - /** What this human calls themselves */ - name: Scalars['String']['output']; - /** A list of starships this person has piloted, or an empty list if none */ - starships?: Maybe>>; -}; - -/** A humanoid creature from the Star Wars universe */ -export type HumanFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** A humanoid creature from the Star Wars universe */ -export type HumanHeightArgs = { - unit?: InputMaybe; -}; - -/** Units of height */ -export enum LengthUnit { - /** Primarily used in the United States */ - Foot = 'FOOT', - /** The standard unit around the world */ - Meter = 'METER', -} - -/** The mutation type, represents all updates we can make to our data */ -export type Mutation = { - __typename?: 'Mutation'; - createReview?: Maybe; -}; - -/** The mutation type, represents all updates we can make to our data */ -export type MutationCreateReviewArgs = { - episode?: InputMaybe; - review: ReviewInput; -}; - -/** Information for paginating this connection */ -export type PageInfo = { - __typename?: 'PageInfo'; - endCursor?: Maybe; - hasNextPage: Scalars['Boolean']['output']; - startCursor?: Maybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type Query = { - __typename?: 'Query'; - character?: Maybe; - droid?: Maybe; - hero?: Maybe; - human?: Maybe; - reviews?: Maybe>>; - search?: Maybe>>; - starship?: Maybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryCharacterArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryDroidArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryHeroArgs = { - episode?: InputMaybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryHumanArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryReviewsArgs = { - episode: Episode; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QuerySearchArgs = { - text?: InputMaybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryStarshipArgs = { - id: Scalars['ID']['input']; -}; - -/** Represents a review for a movie */ -export type Review = { - __typename?: 'Review'; - /** Comment about the movie */ - commentary?: Maybe; - /** The number of stars this review gave, 1-5 */ - stars: Scalars['Int']['output']; -}; - -/** The input object sent when someone is creating a new review */ -export type ReviewInput = { - /** Comment about the movie, optional */ - commentary?: InputMaybe; - /** Favorite color, optional */ - favoriteColor?: InputMaybe; - /** 0-5 stars */ - stars: Scalars['Int']['input']; -}; - -export type SearchResult = Droid | Human | Starship; - -export type Starship = { - __typename?: 'Starship'; - /** The ID of the starship */ - id: Scalars['ID']['output']; - /** Length of the starship, along the longest axis */ - length?: Maybe; - /** The name of the starship */ - name: Scalars['String']['output']; -}; - -export type StarshipLengthArgs = { - unit?: InputMaybe; -}; - export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.excludeQueryBeta.ts b/dev-test/star-wars/types.excludeQueryBeta.ts index 3ea8a6c5617..6b0a5109dc2 100644 --- a/dev-test/star-wars/types.excludeQueryBeta.ts +++ b/dev-test/star-wars/types.excludeQueryBeta.ts @@ -1,249 +1,7 @@ -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A character from the Star Wars universe */ -export type Character = { - /** The movies this character appears in */ - appearsIn: Array>; - /** The friends of the character, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the character exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** The ID of the character */ - id: Scalars['ID']['output']; - /** The name of the character */ - name: Scalars['String']['output']; -}; - -/** A character from the Star Wars universe */ -export type CharacterFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** The input object sent when passing a color */ -export type ColorInput = { - blue: Scalars['Int']['input']; - green: Scalars['Int']['input']; - red: Scalars['Int']['input']; -}; - -/** An autonomous mechanical character in the Star Wars universe */ -export type Droid = Character & { - __typename?: 'Droid'; - /** The movies this droid appears in */ - appearsIn: Array>; - /** This droid's friends, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the droid exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** The ID of the droid */ - id: Scalars['ID']['output']; - /** What others call this droid */ - name: Scalars['String']['output']; - /** This droid's primary function */ - primaryFunction?: Maybe; -}; - -/** An autonomous mechanical character in the Star Wars universe */ -export type DroidFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** The episodes in the Star Wars trilogy */ -export enum Episode { - /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ - Empire = 'EMPIRE', - /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ - Jedi = 'JEDI', - /** Star Wars Episode IV: A New Hope, released in 1977. */ - Newhope = 'NEWHOPE', -} - -/** A connection object for a character's friends */ -export type FriendsConnection = { - __typename?: 'FriendsConnection'; - /** The edges for each of the character's friends. */ - edges?: Maybe>>; - /** A list of the friends, as a convenience when edges are not needed. */ - friends?: Maybe>>; - /** Information for paginating this connection */ - pageInfo: PageInfo; - /** The total number of friends */ - totalCount?: Maybe; -}; - -/** An edge object for a character's friends */ -export type FriendsEdge = { - __typename?: 'FriendsEdge'; - /** A cursor used for pagination */ - cursor: Scalars['ID']['output']; - /** The character represented by this friendship edge */ - node?: Maybe; -}; - -/** A humanoid creature from the Star Wars universe */ -export type Human = Character & { - __typename?: 'Human'; - /** The movies this human appears in */ - appearsIn: Array>; - /** This human's friends, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the human exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** Height in the preferred unit, default is meters */ - height?: Maybe; - /** The home planet of the human, or null if unknown */ - homePlanet?: Maybe; - /** The ID of the human */ - id: Scalars['ID']['output']; - /** Mass in kilograms, or null if unknown */ - mass?: Maybe; - /** What this human calls themselves */ - name: Scalars['String']['output']; - /** A list of starships this person has piloted, or an empty list if none */ - starships?: Maybe>>; -}; - -/** A humanoid creature from the Star Wars universe */ -export type HumanFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** A humanoid creature from the Star Wars universe */ -export type HumanHeightArgs = { - unit?: InputMaybe; -}; - -/** Units of height */ -export enum LengthUnit { - /** Primarily used in the United States */ - Foot = 'FOOT', - /** The standard unit around the world */ - Meter = 'METER', -} - -/** The mutation type, represents all updates we can make to our data */ -export type Mutation = { - __typename?: 'Mutation'; - createReview?: Maybe; -}; - -/** The mutation type, represents all updates we can make to our data */ -export type MutationCreateReviewArgs = { - episode?: InputMaybe; - review: ReviewInput; -}; - -/** Information for paginating this connection */ -export type PageInfo = { - __typename?: 'PageInfo'; - endCursor?: Maybe; - hasNextPage: Scalars['Boolean']['output']; - startCursor?: Maybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type Query = { - __typename?: 'Query'; - character?: Maybe; - droid?: Maybe; - hero?: Maybe; - human?: Maybe; - reviews?: Maybe>>; - search?: Maybe>>; - starship?: Maybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryCharacterArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryDroidArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryHeroArgs = { - episode?: InputMaybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryHumanArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryReviewsArgs = { - episode: Episode; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QuerySearchArgs = { - text?: InputMaybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryStarshipArgs = { - id: Scalars['ID']['input']; -}; - -/** Represents a review for a movie */ -export type Review = { - __typename?: 'Review'; - /** Comment about the movie */ - commentary?: Maybe; - /** The number of stars this review gave, 1-5 */ - stars: Scalars['Int']['output']; -}; - -/** The input object sent when someone is creating a new review */ -export type ReviewInput = { - /** Comment about the movie, optional */ - commentary?: InputMaybe; - /** Favorite color, optional */ - favoriteColor?: InputMaybe; - /** 0-5 stars */ - stars: Scalars['Int']['input']; -}; - -export type SearchResult = Droid | Human | Starship; - -export type Starship = { - __typename?: 'Starship'; - /** The ID of the starship */ - id: Scalars['ID']['output']; - /** Length of the starship, along the longest axis */ - length?: Maybe; - /** The name of the starship */ - name: Scalars['String']['output']; -}; - -export type StarshipLengthArgs = { - unit?: InputMaybe; -}; - export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.globallyAvailable.d.ts b/dev-test/star-wars/types.globallyAvailable.d.ts index 7cdcb977a14..4d60ead1878 100644 --- a/dev-test/star-wars/types.globallyAvailable.d.ts +++ b/dev-test/star-wars/types.globallyAvailable.d.ts @@ -1,245 +1,7 @@ -type Maybe = T | null; -type InputMaybe = Maybe; -type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -type MakeEmpty = { [_ in K]?: never }; -type Incremental = +type Exact = { [K in keyof T]: T[K] }; +export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A character from the Star Wars universe */ -type Character = { - /** The movies this character appears in */ - appearsIn: Array>; - /** The friends of the character, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the character exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** The ID of the character */ - id: Scalars['ID']['output']; - /** The name of the character */ - name: Scalars['String']['output']; -}; - -/** A character from the Star Wars universe */ -type CharacterFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** The input object sent when passing a color */ -type ColorInput = { - blue: Scalars['Int']['input']; - green: Scalars['Int']['input']; - red: Scalars['Int']['input']; -}; - -/** An autonomous mechanical character in the Star Wars universe */ -type Droid = Character & { - __typename?: 'Droid'; - /** The movies this droid appears in */ - appearsIn: Array>; - /** This droid's friends, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the droid exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** The ID of the droid */ - id: Scalars['ID']['output']; - /** What others call this droid */ - name: Scalars['String']['output']; - /** This droid's primary function */ - primaryFunction?: Maybe; -}; - -/** An autonomous mechanical character in the Star Wars universe */ -type DroidFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** The episodes in the Star Wars trilogy */ -type Episode = - /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ - | 'EMPIRE' - /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ - | 'JEDI' - /** Star Wars Episode IV: A New Hope, released in 1977. */ - | 'NEWHOPE'; - -/** A connection object for a character's friends */ -type FriendsConnection = { - __typename?: 'FriendsConnection'; - /** The edges for each of the character's friends. */ - edges?: Maybe>>; - /** A list of the friends, as a convenience when edges are not needed. */ - friends?: Maybe>>; - /** Information for paginating this connection */ - pageInfo: PageInfo; - /** The total number of friends */ - totalCount?: Maybe; -}; - -/** An edge object for a character's friends */ -type FriendsEdge = { - __typename?: 'FriendsEdge'; - /** A cursor used for pagination */ - cursor: Scalars['ID']['output']; - /** The character represented by this friendship edge */ - node?: Maybe; -}; - -/** A humanoid creature from the Star Wars universe */ -type Human = Character & { - __typename?: 'Human'; - /** The movies this human appears in */ - appearsIn: Array>; - /** This human's friends, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the human exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** Height in the preferred unit, default is meters */ - height?: Maybe; - /** The home planet of the human, or null if unknown */ - homePlanet?: Maybe; - /** The ID of the human */ - id: Scalars['ID']['output']; - /** Mass in kilograms, or null if unknown */ - mass?: Maybe; - /** What this human calls themselves */ - name: Scalars['String']['output']; - /** A list of starships this person has piloted, or an empty list if none */ - starships?: Maybe>>; -}; - -/** A humanoid creature from the Star Wars universe */ -type HumanFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** A humanoid creature from the Star Wars universe */ -type HumanHeightArgs = { - unit?: InputMaybe; -}; - -/** Units of height */ -type LengthUnit = - /** Primarily used in the United States */ - | 'FOOT' - /** The standard unit around the world */ - | 'METER'; - -/** The mutation type, represents all updates we can make to our data */ -type Mutation = { - __typename?: 'Mutation'; - createReview?: Maybe; -}; - -/** The mutation type, represents all updates we can make to our data */ -type MutationCreateReviewArgs = { - episode?: InputMaybe; - review: ReviewInput; -}; - -/** Information for paginating this connection */ -type PageInfo = { - __typename?: 'PageInfo'; - endCursor?: Maybe; - hasNextPage: Scalars['Boolean']['output']; - startCursor?: Maybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -type Query = { - __typename?: 'Query'; - character?: Maybe; - droid?: Maybe; - hero?: Maybe; - human?: Maybe; - reviews?: Maybe>>; - search?: Maybe>>; - starship?: Maybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -type QueryCharacterArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -type QueryDroidArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -type QueryHeroArgs = { - episode?: InputMaybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -type QueryHumanArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -type QueryReviewsArgs = { - episode: Episode; -}; - -/** The query type, represents all of the entry points into our object graph */ -type QuerySearchArgs = { - text?: InputMaybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -type QueryStarshipArgs = { - id: Scalars['ID']['input']; -}; - -/** Represents a review for a movie */ -type Review = { - __typename?: 'Review'; - /** Comment about the movie */ - commentary?: Maybe; - /** The number of stars this review gave, 1-5 */ - stars: Scalars['Int']['output']; -}; - -/** The input object sent when someone is creating a new review */ -type ReviewInput = { - /** Comment about the movie, optional */ - commentary?: InputMaybe; - /** Favorite color, optional */ - favoriteColor?: InputMaybe; - /** 0-5 stars */ - stars: Scalars['Int']['input']; -}; - -type SearchResult = Droid | Human | Starship; - -type Starship = { - __typename?: 'Starship'; - /** The ID of the starship */ - id: Scalars['ID']['output']; - /** Length of the starship, along the longest axis */ - length?: Maybe; - /** The name of the starship */ - name: Scalars['String']['output']; -}; - -type StarshipLengthArgs = { - unit?: InputMaybe; -}; - type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.immutableTypes.ts b/dev-test/star-wars/types.immutableTypes.ts index a5d194d5c0b..c3b9dd10e2f 100644 --- a/dev-test/star-wars/types.immutableTypes.ts +++ b/dev-test/star-wars/types.immutableTypes.ts @@ -1,249 +1,7 @@ -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A character from the Star Wars universe */ -export type Character = { - /** The movies this character appears in */ - readonly appearsIn: ReadonlyArray>; - /** The friends of the character, or an empty list if they have none */ - readonly friends?: Maybe>>; - /** The friends of the character exposed as a connection with edges */ - readonly friendsConnection: FriendsConnection; - /** The ID of the character */ - readonly id: Scalars['ID']['output']; - /** The name of the character */ - readonly name: Scalars['String']['output']; -}; - -/** A character from the Star Wars universe */ -export type CharacterFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** The input object sent when passing a color */ -export type ColorInput = { - readonly blue: Scalars['Int']['input']; - readonly green: Scalars['Int']['input']; - readonly red: Scalars['Int']['input']; -}; - -/** An autonomous mechanical character in the Star Wars universe */ -export type Droid = Character & { - readonly __typename?: 'Droid'; - /** The movies this droid appears in */ - readonly appearsIn: ReadonlyArray>; - /** This droid's friends, or an empty list if they have none */ - readonly friends?: Maybe>>; - /** The friends of the droid exposed as a connection with edges */ - readonly friendsConnection: FriendsConnection; - /** The ID of the droid */ - readonly id: Scalars['ID']['output']; - /** What others call this droid */ - readonly name: Scalars['String']['output']; - /** This droid's primary function */ - readonly primaryFunction?: Maybe; -}; - -/** An autonomous mechanical character in the Star Wars universe */ -export type DroidFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** The episodes in the Star Wars trilogy */ -export enum Episode { - /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ - Empire = 'EMPIRE', - /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ - Jedi = 'JEDI', - /** Star Wars Episode IV: A New Hope, released in 1977. */ - Newhope = 'NEWHOPE', -} - -/** A connection object for a character's friends */ -export type FriendsConnection = { - readonly __typename?: 'FriendsConnection'; - /** The edges for each of the character's friends. */ - readonly edges?: Maybe>>; - /** A list of the friends, as a convenience when edges are not needed. */ - readonly friends?: Maybe>>; - /** Information for paginating this connection */ - readonly pageInfo: PageInfo; - /** The total number of friends */ - readonly totalCount?: Maybe; -}; - -/** An edge object for a character's friends */ -export type FriendsEdge = { - readonly __typename?: 'FriendsEdge'; - /** A cursor used for pagination */ - readonly cursor: Scalars['ID']['output']; - /** The character represented by this friendship edge */ - readonly node?: Maybe; -}; - -/** A humanoid creature from the Star Wars universe */ -export type Human = Character & { - readonly __typename?: 'Human'; - /** The movies this human appears in */ - readonly appearsIn: ReadonlyArray>; - /** This human's friends, or an empty list if they have none */ - readonly friends?: Maybe>>; - /** The friends of the human exposed as a connection with edges */ - readonly friendsConnection: FriendsConnection; - /** Height in the preferred unit, default is meters */ - readonly height?: Maybe; - /** The home planet of the human, or null if unknown */ - readonly homePlanet?: Maybe; - /** The ID of the human */ - readonly id: Scalars['ID']['output']; - /** Mass in kilograms, or null if unknown */ - readonly mass?: Maybe; - /** What this human calls themselves */ - readonly name: Scalars['String']['output']; - /** A list of starships this person has piloted, or an empty list if none */ - readonly starships?: Maybe>>; -}; - -/** A humanoid creature from the Star Wars universe */ -export type HumanFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** A humanoid creature from the Star Wars universe */ -export type HumanHeightArgs = { - unit?: InputMaybe; -}; - -/** Units of height */ -export enum LengthUnit { - /** Primarily used in the United States */ - Foot = 'FOOT', - /** The standard unit around the world */ - Meter = 'METER', -} - -/** The mutation type, represents all updates we can make to our data */ -export type Mutation = { - readonly __typename?: 'Mutation'; - readonly createReview?: Maybe; -}; - -/** The mutation type, represents all updates we can make to our data */ -export type MutationCreateReviewArgs = { - episode?: InputMaybe; - review: ReviewInput; -}; - -/** Information for paginating this connection */ -export type PageInfo = { - readonly __typename?: 'PageInfo'; - readonly endCursor?: Maybe; - readonly hasNextPage: Scalars['Boolean']['output']; - readonly startCursor?: Maybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type Query = { - readonly __typename?: 'Query'; - readonly character?: Maybe; - readonly droid?: Maybe; - readonly hero?: Maybe; - readonly human?: Maybe; - readonly reviews?: Maybe>>; - readonly search?: Maybe>>; - readonly starship?: Maybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryCharacterArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryDroidArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryHeroArgs = { - episode?: InputMaybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryHumanArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryReviewsArgs = { - episode: Episode; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QuerySearchArgs = { - text?: InputMaybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryStarshipArgs = { - id: Scalars['ID']['input']; -}; - -/** Represents a review for a movie */ -export type Review = { - readonly __typename?: 'Review'; - /** Comment about the movie */ - readonly commentary?: Maybe; - /** The number of stars this review gave, 1-5 */ - readonly stars: Scalars['Int']['output']; -}; - -/** The input object sent when someone is creating a new review */ -export type ReviewInput = { - /** Comment about the movie, optional */ - readonly commentary?: InputMaybe; - /** Favorite color, optional */ - readonly favoriteColor?: InputMaybe; - /** 0-5 stars */ - readonly stars: Scalars['Int']['input']; -}; - -export type SearchResult = Droid | Human | Starship; - -export type Starship = { - readonly __typename?: 'Starship'; - /** The ID of the starship */ - readonly id: Scalars['ID']['output']; - /** Length of the starship, along the longest axis */ - readonly length?: Maybe; - /** The name of the starship */ - readonly name: Scalars['String']['output']; -}; - -export type StarshipLengthArgs = { - unit?: InputMaybe; -}; - export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts index 6f844783949..4e34d8a65e6 100644 --- a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts @@ -1,58 +1,7 @@ -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** The input object sent when passing a color */ -export type ColorInput = { - blue: Scalars['Int']['input']; - green: Scalars['Int']['input']; - red: Scalars['Int']['input']; -}; - -/** The episodes in the Star Wars trilogy */ -export enum Episode { - /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ - Empire = 'EMPIRE', - /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ - Jedi = 'JEDI', - /** Star Wars Episode IV: A New Hope, released in 1977. */ - Newhope = 'NEWHOPE', -} - -/** Units of height */ -export enum LengthUnit { - /** Primarily used in the United States */ - Foot = 'FOOT', - /** The standard unit around the world */ - Meter = 'METER', -} - -/** The input object sent when someone is creating a new review */ -export type ReviewInput = { - /** Comment about the movie, optional */ - commentary?: InputMaybe; - /** Favorite color, optional */ - favoriteColor?: InputMaybe; - /** 0-5 stars */ - stars: Scalars['Int']['input']; -}; - export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.preResolveTypes.ts b/dev-test/star-wars/types.preResolveTypes.ts index e3d32fb9e2e..4e34d8a65e6 100644 --- a/dev-test/star-wars/types.preResolveTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.ts @@ -1,249 +1,7 @@ -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A character from the Star Wars universe */ -export type Character = { - /** The movies this character appears in */ - appearsIn: Array>; - /** The friends of the character, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the character exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** The ID of the character */ - id: Scalars['ID']['output']; - /** The name of the character */ - name: Scalars['String']['output']; -}; - -/** A character from the Star Wars universe */ -export type CharacterFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** The input object sent when passing a color */ -export type ColorInput = { - blue: Scalars['Int']['input']; - green: Scalars['Int']['input']; - red: Scalars['Int']['input']; -}; - -/** An autonomous mechanical character in the Star Wars universe */ -export type Droid = Character & { - __typename?: 'Droid'; - /** The movies this droid appears in */ - appearsIn: Array>; - /** This droid's friends, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the droid exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** The ID of the droid */ - id: Scalars['ID']['output']; - /** What others call this droid */ - name: Scalars['String']['output']; - /** This droid's primary function */ - primaryFunction?: Maybe; -}; - -/** An autonomous mechanical character in the Star Wars universe */ -export type DroidFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** The episodes in the Star Wars trilogy */ -export enum Episode { - /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ - Empire = 'EMPIRE', - /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ - Jedi = 'JEDI', - /** Star Wars Episode IV: A New Hope, released in 1977. */ - Newhope = 'NEWHOPE', -} - -/** A connection object for a character's friends */ -export type FriendsConnection = { - __typename?: 'FriendsConnection'; - /** The edges for each of the character's friends. */ - edges?: Maybe>>; - /** A list of the friends, as a convenience when edges are not needed. */ - friends?: Maybe>>; - /** Information for paginating this connection */ - pageInfo: PageInfo; - /** The total number of friends */ - totalCount?: Maybe; -}; - -/** An edge object for a character's friends */ -export type FriendsEdge = { - __typename?: 'FriendsEdge'; - /** A cursor used for pagination */ - cursor: Scalars['ID']['output']; - /** The character represented by this friendship edge */ - node?: Maybe; -}; - -/** A humanoid creature from the Star Wars universe */ -export type Human = Character & { - __typename?: 'Human'; - /** The movies this human appears in */ - appearsIn: Array>; - /** This human's friends, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the human exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** Height in the preferred unit, default is meters */ - height?: Maybe; - /** The home planet of the human, or null if unknown */ - homePlanet?: Maybe; - /** The ID of the human */ - id: Scalars['ID']['output']; - /** Mass in kilograms, or null if unknown */ - mass?: Maybe; - /** What this human calls themselves */ - name: Scalars['String']['output']; - /** A list of starships this person has piloted, or an empty list if none */ - starships?: Maybe>>; -}; - -/** A humanoid creature from the Star Wars universe */ -export type HumanFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** A humanoid creature from the Star Wars universe */ -export type HumanHeightArgs = { - unit?: InputMaybe; -}; - -/** Units of height */ -export enum LengthUnit { - /** Primarily used in the United States */ - Foot = 'FOOT', - /** The standard unit around the world */ - Meter = 'METER', -} - -/** The mutation type, represents all updates we can make to our data */ -export type Mutation = { - __typename?: 'Mutation'; - createReview?: Maybe; -}; - -/** The mutation type, represents all updates we can make to our data */ -export type MutationCreateReviewArgs = { - episode?: InputMaybe; - review: ReviewInput; -}; - -/** Information for paginating this connection */ -export type PageInfo = { - __typename?: 'PageInfo'; - endCursor?: Maybe; - hasNextPage: Scalars['Boolean']['output']; - startCursor?: Maybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type Query = { - __typename?: 'Query'; - character?: Maybe; - droid?: Maybe; - hero?: Maybe; - human?: Maybe; - reviews?: Maybe>>; - search?: Maybe>>; - starship?: Maybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryCharacterArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryDroidArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryHeroArgs = { - episode?: InputMaybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryHumanArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryReviewsArgs = { - episode: Episode; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QuerySearchArgs = { - text?: InputMaybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryStarshipArgs = { - id: Scalars['ID']['input']; -}; - -/** Represents a review for a movie */ -export type Review = { - __typename?: 'Review'; - /** Comment about the movie */ - commentary?: Maybe; - /** The number of stars this review gave, 1-5 */ - stars: Scalars['Int']['output']; -}; - -/** The input object sent when someone is creating a new review */ -export type ReviewInput = { - /** Comment about the movie, optional */ - commentary?: InputMaybe; - /** Favorite color, optional */ - favoriteColor?: InputMaybe; - /** 0-5 stars */ - stars: Scalars['Int']['input']; -}; - -export type SearchResult = Droid | Human | Starship; - -export type Starship = { - __typename?: 'Starship'; - /** The ID of the starship */ - id: Scalars['ID']['output']; - /** Length of the starship, along the longest axis */ - length?: Maybe; - /** The name of the starship */ - name: Scalars['String']['output']; -}; - -export type StarshipLengthArgs = { - unit?: InputMaybe; -}; - export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.skipSchema.ts b/dev-test/star-wars/types.skipSchema.ts index e3d32fb9e2e..4e34d8a65e6 100644 --- a/dev-test/star-wars/types.skipSchema.ts +++ b/dev-test/star-wars/types.skipSchema.ts @@ -1,249 +1,7 @@ -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A character from the Star Wars universe */ -export type Character = { - /** The movies this character appears in */ - appearsIn: Array>; - /** The friends of the character, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the character exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** The ID of the character */ - id: Scalars['ID']['output']; - /** The name of the character */ - name: Scalars['String']['output']; -}; - -/** A character from the Star Wars universe */ -export type CharacterFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** The input object sent when passing a color */ -export type ColorInput = { - blue: Scalars['Int']['input']; - green: Scalars['Int']['input']; - red: Scalars['Int']['input']; -}; - -/** An autonomous mechanical character in the Star Wars universe */ -export type Droid = Character & { - __typename?: 'Droid'; - /** The movies this droid appears in */ - appearsIn: Array>; - /** This droid's friends, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the droid exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** The ID of the droid */ - id: Scalars['ID']['output']; - /** What others call this droid */ - name: Scalars['String']['output']; - /** This droid's primary function */ - primaryFunction?: Maybe; -}; - -/** An autonomous mechanical character in the Star Wars universe */ -export type DroidFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** The episodes in the Star Wars trilogy */ -export enum Episode { - /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ - Empire = 'EMPIRE', - /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ - Jedi = 'JEDI', - /** Star Wars Episode IV: A New Hope, released in 1977. */ - Newhope = 'NEWHOPE', -} - -/** A connection object for a character's friends */ -export type FriendsConnection = { - __typename?: 'FriendsConnection'; - /** The edges for each of the character's friends. */ - edges?: Maybe>>; - /** A list of the friends, as a convenience when edges are not needed. */ - friends?: Maybe>>; - /** Information for paginating this connection */ - pageInfo: PageInfo; - /** The total number of friends */ - totalCount?: Maybe; -}; - -/** An edge object for a character's friends */ -export type FriendsEdge = { - __typename?: 'FriendsEdge'; - /** A cursor used for pagination */ - cursor: Scalars['ID']['output']; - /** The character represented by this friendship edge */ - node?: Maybe; -}; - -/** A humanoid creature from the Star Wars universe */ -export type Human = Character & { - __typename?: 'Human'; - /** The movies this human appears in */ - appearsIn: Array>; - /** This human's friends, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the human exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** Height in the preferred unit, default is meters */ - height?: Maybe; - /** The home planet of the human, or null if unknown */ - homePlanet?: Maybe; - /** The ID of the human */ - id: Scalars['ID']['output']; - /** Mass in kilograms, or null if unknown */ - mass?: Maybe; - /** What this human calls themselves */ - name: Scalars['String']['output']; - /** A list of starships this person has piloted, or an empty list if none */ - starships?: Maybe>>; -}; - -/** A humanoid creature from the Star Wars universe */ -export type HumanFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** A humanoid creature from the Star Wars universe */ -export type HumanHeightArgs = { - unit?: InputMaybe; -}; - -/** Units of height */ -export enum LengthUnit { - /** Primarily used in the United States */ - Foot = 'FOOT', - /** The standard unit around the world */ - Meter = 'METER', -} - -/** The mutation type, represents all updates we can make to our data */ -export type Mutation = { - __typename?: 'Mutation'; - createReview?: Maybe; -}; - -/** The mutation type, represents all updates we can make to our data */ -export type MutationCreateReviewArgs = { - episode?: InputMaybe; - review: ReviewInput; -}; - -/** Information for paginating this connection */ -export type PageInfo = { - __typename?: 'PageInfo'; - endCursor?: Maybe; - hasNextPage: Scalars['Boolean']['output']; - startCursor?: Maybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type Query = { - __typename?: 'Query'; - character?: Maybe; - droid?: Maybe; - hero?: Maybe; - human?: Maybe; - reviews?: Maybe>>; - search?: Maybe>>; - starship?: Maybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryCharacterArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryDroidArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryHeroArgs = { - episode?: InputMaybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryHumanArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryReviewsArgs = { - episode: Episode; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QuerySearchArgs = { - text?: InputMaybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryStarshipArgs = { - id: Scalars['ID']['input']; -}; - -/** Represents a review for a movie */ -export type Review = { - __typename?: 'Review'; - /** Comment about the movie */ - commentary?: Maybe; - /** The number of stars this review gave, 1-5 */ - stars: Scalars['Int']['output']; -}; - -/** The input object sent when someone is creating a new review */ -export type ReviewInput = { - /** Comment about the movie, optional */ - commentary?: InputMaybe; - /** Favorite color, optional */ - favoriteColor?: InputMaybe; - /** 0-5 stars */ - stars: Scalars['Int']['input']; -}; - -export type SearchResult = Droid | Human | Starship; - -export type Starship = { - __typename?: 'Starship'; - /** The ID of the starship */ - id: Scalars['ID']['output']; - /** Length of the starship, along the longest axis */ - length?: Maybe; - /** The name of the starship */ - name: Scalars['String']['output']; -}; - -export type StarshipLengthArgs = { - unit?: InputMaybe; -}; - export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.ts b/dev-test/star-wars/types.ts index e3d32fb9e2e..4e34d8a65e6 100644 --- a/dev-test/star-wars/types.ts +++ b/dev-test/star-wars/types.ts @@ -1,249 +1,7 @@ -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A character from the Star Wars universe */ -export type Character = { - /** The movies this character appears in */ - appearsIn: Array>; - /** The friends of the character, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the character exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** The ID of the character */ - id: Scalars['ID']['output']; - /** The name of the character */ - name: Scalars['String']['output']; -}; - -/** A character from the Star Wars universe */ -export type CharacterFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** The input object sent when passing a color */ -export type ColorInput = { - blue: Scalars['Int']['input']; - green: Scalars['Int']['input']; - red: Scalars['Int']['input']; -}; - -/** An autonomous mechanical character in the Star Wars universe */ -export type Droid = Character & { - __typename?: 'Droid'; - /** The movies this droid appears in */ - appearsIn: Array>; - /** This droid's friends, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the droid exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** The ID of the droid */ - id: Scalars['ID']['output']; - /** What others call this droid */ - name: Scalars['String']['output']; - /** This droid's primary function */ - primaryFunction?: Maybe; -}; - -/** An autonomous mechanical character in the Star Wars universe */ -export type DroidFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** The episodes in the Star Wars trilogy */ -export enum Episode { - /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ - Empire = 'EMPIRE', - /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ - Jedi = 'JEDI', - /** Star Wars Episode IV: A New Hope, released in 1977. */ - Newhope = 'NEWHOPE', -} - -/** A connection object for a character's friends */ -export type FriendsConnection = { - __typename?: 'FriendsConnection'; - /** The edges for each of the character's friends. */ - edges?: Maybe>>; - /** A list of the friends, as a convenience when edges are not needed. */ - friends?: Maybe>>; - /** Information for paginating this connection */ - pageInfo: PageInfo; - /** The total number of friends */ - totalCount?: Maybe; -}; - -/** An edge object for a character's friends */ -export type FriendsEdge = { - __typename?: 'FriendsEdge'; - /** A cursor used for pagination */ - cursor: Scalars['ID']['output']; - /** The character represented by this friendship edge */ - node?: Maybe; -}; - -/** A humanoid creature from the Star Wars universe */ -export type Human = Character & { - __typename?: 'Human'; - /** The movies this human appears in */ - appearsIn: Array>; - /** This human's friends, or an empty list if they have none */ - friends?: Maybe>>; - /** The friends of the human exposed as a connection with edges */ - friendsConnection: FriendsConnection; - /** Height in the preferred unit, default is meters */ - height?: Maybe; - /** The home planet of the human, or null if unknown */ - homePlanet?: Maybe; - /** The ID of the human */ - id: Scalars['ID']['output']; - /** Mass in kilograms, or null if unknown */ - mass?: Maybe; - /** What this human calls themselves */ - name: Scalars['String']['output']; - /** A list of starships this person has piloted, or an empty list if none */ - starships?: Maybe>>; -}; - -/** A humanoid creature from the Star Wars universe */ -export type HumanFriendsConnectionArgs = { - after?: InputMaybe; - first?: InputMaybe; -}; - -/** A humanoid creature from the Star Wars universe */ -export type HumanHeightArgs = { - unit?: InputMaybe; -}; - -/** Units of height */ -export enum LengthUnit { - /** Primarily used in the United States */ - Foot = 'FOOT', - /** The standard unit around the world */ - Meter = 'METER', -} - -/** The mutation type, represents all updates we can make to our data */ -export type Mutation = { - __typename?: 'Mutation'; - createReview?: Maybe; -}; - -/** The mutation type, represents all updates we can make to our data */ -export type MutationCreateReviewArgs = { - episode?: InputMaybe; - review: ReviewInput; -}; - -/** Information for paginating this connection */ -export type PageInfo = { - __typename?: 'PageInfo'; - endCursor?: Maybe; - hasNextPage: Scalars['Boolean']['output']; - startCursor?: Maybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type Query = { - __typename?: 'Query'; - character?: Maybe; - droid?: Maybe; - hero?: Maybe; - human?: Maybe; - reviews?: Maybe>>; - search?: Maybe>>; - starship?: Maybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryCharacterArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryDroidArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryHeroArgs = { - episode?: InputMaybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryHumanArgs = { - id: Scalars['ID']['input']; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryReviewsArgs = { - episode: Episode; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QuerySearchArgs = { - text?: InputMaybe; -}; - -/** The query type, represents all of the entry points into our object graph */ -export type QueryStarshipArgs = { - id: Scalars['ID']['input']; -}; - -/** Represents a review for a movie */ -export type Review = { - __typename?: 'Review'; - /** Comment about the movie */ - commentary?: Maybe; - /** The number of stars this review gave, 1-5 */ - stars: Scalars['Int']['output']; -}; - -/** The input object sent when someone is creating a new review */ -export type ReviewInput = { - /** Comment about the movie, optional */ - commentary?: InputMaybe; - /** Favorite color, optional */ - favoriteColor?: InputMaybe; - /** 0-5 stars */ - stars: Scalars['Int']['input']; -}; - -export type SearchResult = Droid | Human | Starship; - -export type Starship = { - __typename?: 'Starship'; - /** The ID of the starship */ - id: Scalars['ID']['output']; - /** Length of the starship, along the longest axis */ - length?: Maybe; - /** The name of the starship */ - name: Scalars['String']['output']; -}; - -export type StarshipLengthArgs = { - unit?: InputMaybe; -}; - export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/test-null-value/result.d.ts b/dev-test/test-null-value/result.d.ts index 4b37cd5a870..d5e09b41781 100644 --- a/dev-test/test-null-value/result.d.ts +++ b/dev-test/test-null-value/result.d.ts @@ -1,52 +1,7 @@ -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -export type BaseCartLine = { - id: Scalars['String']['output']; - quantity: Scalars['Int']['output']; -}; - -export type BaseCartLineConnection = { - id: Scalars['String']['output']; - nodes: Array; -}; - -export type Cart = { - id: Scalars['String']['output']; - lines: BaseCartLineConnection; -}; - -export type CartLine = BaseCartLine & { - id: Scalars['String']['output']; - quantity: Scalars['Int']['output']; -}; - -export type ComponentizableCartLine = BaseCartLine & { - id: Scalars['String']['output']; - quantity: Scalars['Int']['output']; -}; - -export type QueryRoot = { - cart?: Maybe; -}; - export type CartLineFragment = { id: string; quantity: number }; export type TestQueryVariables = Exact<{ [key: string]: never }>; diff --git a/dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts index 541df10d958..9784511b3c6 100644 --- a/dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts @@ -1,23 +1,7 @@ -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - export type TestQueryVariables = Exact<{ [key: string]: never }>; export type TestQuery = { diff --git a/dev-test/test-schema/types.preResolveTypes.ts b/dev-test/test-schema/types.preResolveTypes.ts index e114e0af309..9784511b3c6 100644 --- a/dev-test/test-schema/types.preResolveTypes.ts +++ b/dev-test/test-schema/types.preResolveTypes.ts @@ -1,48 +1,7 @@ -export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -export type Query = { - __typename?: 'Query'; - allUsers: Array>; - /** - * Generates a new answer for th - * guessing game - */ - answer: Array; - testArr1?: Maybe>>; - testArr2: Array>; - testArr3: Array; - userById?: Maybe; -}; - -export type QueryUserByIdArgs = { - id: Scalars['Int']['input']; -}; - -export type User = { - __typename?: 'User'; - email: Scalars['String']['output']; - id: Scalars['Int']['output']; - name: Scalars['String']['output']; -}; - export type TestQueryVariables = Exact<{ [key: string]: never }>; export type TestQuery = { diff --git a/dev-test/test-schema/typings.wrapped.ts b/dev-test/test-schema/typings.wrapped.ts index c607ba519fb..029f15125d9 100644 --- a/dev-test/test-schema/typings.wrapped.ts +++ b/dev-test/test-schema/typings.wrapped.ts @@ -11,7 +11,6 @@ declare namespace GraphQL { export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - type Exact = { [K in keyof T]: T[K] }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/examples/persisted-documents-string-mode/src/gql/graphql.ts b/examples/persisted-documents-string-mode/src/gql/graphql.ts index bb1d048aba9..a5fd33f5185 100644 --- a/examples/persisted-documents-string-mode/src/gql/graphql.ts +++ b/examples/persisted-documents-string-mode/src/gql/graphql.ts @@ -1,40 +1,10 @@ /* eslint-disable */ import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -export type Mutation = { - __typename?: 'Mutation'; - echo: Scalars['String']['output']; -}; - -export type MutationEchoArgs = { - message: Scalars['String']['input']; -}; - -export type Query = { - __typename?: 'Query'; - hello: Scalars['String']['output']; -}; - export type HelloQueryQueryVariables = Exact<{ [key: string]: never }>; export type HelloQueryQuery = { __typename?: 'Query'; hello: string }; diff --git a/examples/persisted-documents/src/gql/graphql.ts b/examples/persisted-documents/src/gql/graphql.ts index 53cf201b793..7fd26f94347 100644 --- a/examples/persisted-documents/src/gql/graphql.ts +++ b/examples/persisted-documents/src/gql/graphql.ts @@ -1,40 +1,10 @@ /* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -export type Mutation = { - __typename?: 'Mutation'; - echo: Scalars['String']['output']; -}; - -export type MutationEchoArgs = { - message: Scalars['String']['input']; -}; - -export type Query = { - __typename?: 'Query'; - hello: Scalars['String']['output']; -}; - export type HelloQueryQueryVariables = Exact<{ [key: string]: never }>; export type HelloQueryQuery = { __typename?: 'Query'; hello: string }; diff --git a/examples/react/apollo-client-defer/src/gql/graphql.ts b/examples/react/apollo-client-defer/src/gql/graphql.ts index b8f8cc8cb01..a94db489602 100644 --- a/examples/react/apollo-client-defer/src/gql/graphql.ts +++ b/examples/react/apollo-client-defer/src/gql/graphql.ts @@ -1,42 +1,10 @@ /* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -export type Query = { - __typename?: 'Query'; - alphabet: Array; - /** A field that resolves fast. */ - fastField: Scalars['String']['output']; - /** - * A field that resolves slowly. - * Maybe you want to @defer this field ;) - */ - slowField: Scalars['String']['output']; -}; - -export type QuerySlowFieldArgs = { - waitFor?: Scalars['Int']['input']; -}; - export type SlowFieldFragmentFragment = { __typename?: 'Query'; slowField: string } & { ' $fragmentName'?: 'SlowFieldFragmentFragment'; }; diff --git a/examples/react/apollo-client/src/gql/graphql.ts b/examples/react/apollo-client/src/gql/graphql.ts index e6603fce09d..0341892a345 100644 --- a/examples/react/apollo-client/src/gql/graphql.ts +++ b/examples/react/apollo-client/src/gql/graphql.ts @@ -1,1285 +1,10 @@ /* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A single film. */ -export type Film = Node & { - __typename?: 'Film'; - characterConnection?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The name of the director of this film. */ - director?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** The episode number of this film. */ - episodeID?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The opening paragraphs at the beginning of this film. */ - openingCrawl?: Maybe; - planetConnection?: Maybe; - /** The name(s) of the producer(s) of this film. */ - producers?: Maybe>>; - /** The ISO 8601 date format of film release at original creator country. */ - releaseDate?: Maybe; - speciesConnection?: Maybe; - starshipConnection?: Maybe; - /** The title of this film. */ - title?: Maybe; - vehicleConnection?: Maybe; -}; - -/** A single film. */ -export type FilmCharacterConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmPlanetConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmSpeciesConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type FilmCharactersConnection = { - __typename?: 'FilmCharactersConnection'; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - characters?: Maybe>>; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmCharactersEdge = { - __typename?: 'FilmCharactersEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmPlanetsConnection = { - __typename?: 'FilmPlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmPlanetsEdge = { - __typename?: 'FilmPlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmSpeciesConnection = { - __typename?: 'FilmSpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmSpeciesEdge = { - __typename?: 'FilmSpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmStarshipsConnection = { - __typename?: 'FilmStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmStarshipsEdge = { - __typename?: 'FilmStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmVehiclesConnection = { - __typename?: 'FilmVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type FilmVehiclesEdge = { - __typename?: 'FilmVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmsConnection = { - __typename?: 'FilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmsEdge = { - __typename?: 'FilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An object with an ID */ -export type Node = { - /** The id of the object. */ - id: Scalars['ID']['output']; -}; - -/** Information about pagination in a connection. */ -export type PageInfo = { - __typename?: 'PageInfo'; - /** When paginating forwards, the cursor to continue. */ - endCursor?: Maybe; - /** When paginating forwards, are there more items? */ - hasNextPage: Scalars['Boolean']['output']; - /** When paginating backwards, are there more items? */ - hasPreviousPage: Scalars['Boolean']['output']; - /** When paginating backwards, the cursor to continue. */ - startCursor?: Maybe; -}; - -/** A connection to a list of items. */ -export type PeopleConnection = { - __typename?: 'PeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PeopleEdge = { - __typename?: 'PeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type Person = Node & { - __typename?: 'Person'; - /** - * The birth year of the person, using the in-universe standard of BBY or ABY - - * Before the Battle of Yavin or After the Battle of Yavin. The Battle of Yavin is - * a battle that occurs at the end of Star Wars episode IV: A New Hope. - */ - birthYear?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * The eye color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have an eye. - */ - eyeColor?: Maybe; - filmConnection?: Maybe; - /** - * The gender of this person. Either "Male", "Female" or "unknown", - * "n/a" if the person does not have a gender. - */ - gender?: Maybe; - /** - * The hair color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have hair. - */ - hairColor?: Maybe; - /** The height of the person in centimeters. */ - height?: Maybe; - /** A planet that this person was born on or inhabits. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The mass of the person in kilograms. */ - mass?: Maybe; - /** The name of this person. */ - name?: Maybe; - /** The skin color of this person. */ - skinColor?: Maybe; - /** The species that this person belongs to, or null if unknown. */ - species?: Maybe; - starshipConnection?: Maybe; - vehicleConnection?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PersonFilmsConnection = { - __typename?: 'PersonFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonFilmsEdge = { - __typename?: 'PersonFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonStarshipsConnection = { - __typename?: 'PersonStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonStarshipsEdge = { - __typename?: 'PersonStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonVehiclesConnection = { - __typename?: 'PersonVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type PersonVehiclesEdge = { - __typename?: 'PersonVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type Planet = Node & { - __typename?: 'Planet'; - /** The climates of this planet. */ - climates?: Maybe>>; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The diameter of this planet in kilometers. */ - diameter?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** - * A number denoting the gravity of this planet, where "1" is normal or 1 standard - * G. "2" is twice or 2 standard Gs. "0.5" is half or 0.5 standard Gs. - */ - gravity?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The name of this planet. */ - name?: Maybe; - /** - * The number of standard days it takes for this planet to complete a single orbit - * of its local star. - */ - orbitalPeriod?: Maybe; - /** The average population of sentient beings inhabiting this planet. */ - population?: Maybe; - residentConnection?: Maybe; - /** - * The number of standard hours it takes for this planet to complete a single - * rotation on its axis. - */ - rotationPeriod?: Maybe; - /** - * The percentage of the planet surface that is naturally occurring water or bodies - * of water. - */ - surfaceWater?: Maybe; - /** The terrains of this planet. */ - terrains?: Maybe>>; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetResidentConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PlanetFilmsConnection = { - __typename?: 'PlanetFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetFilmsEdge = { - __typename?: 'PlanetFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetResidentsConnection = { - __typename?: 'PlanetResidentsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - residents?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetResidentsEdge = { - __typename?: 'PlanetResidentsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetsConnection = { - __typename?: 'PlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetsEdge = { - __typename?: 'PlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -export type Root = { - __typename?: 'Root'; - allFilms?: Maybe; - allPeople?: Maybe; - allPlanets?: Maybe; - allSpecies?: Maybe; - allStarships?: Maybe; - allVehicles?: Maybe; - film?: Maybe; - /** Fetches an object given its ID */ - node?: Maybe; - person?: Maybe; - planet?: Maybe; - species?: Maybe; - starship?: Maybe; - vehicle?: Maybe; -}; - -export type RootAllFilmsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPeopleArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPlanetsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllSpeciesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllStarshipsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllVehiclesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootFilmArgs = { - filmID?: InputMaybe; - id?: InputMaybe; -}; - -export type RootNodeArgs = { - id: Scalars['ID']['input']; -}; - -export type RootPersonArgs = { - id?: InputMaybe; - personID?: InputMaybe; -}; - -export type RootPlanetArgs = { - id?: InputMaybe; - planetID?: InputMaybe; -}; - -export type RootSpeciesArgs = { - id?: InputMaybe; - speciesID?: InputMaybe; -}; - -export type RootStarshipArgs = { - id?: InputMaybe; - starshipID?: InputMaybe; -}; - -export type RootVehicleArgs = { - id?: InputMaybe; - vehicleID?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type Species = Node & { - __typename?: 'Species'; - /** The average height of this species in centimeters. */ - averageHeight?: Maybe; - /** The average lifespan of this species in years, null if unknown. */ - averageLifespan?: Maybe; - /** The classification of this species, such as "mammal" or "reptile". */ - classification?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The designation of this species, such as "sentient". */ - designation?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * Common eye colors for this species, null if this species does not typically - * have eyes. - */ - eyeColors?: Maybe>>; - filmConnection?: Maybe; - /** - * Common hair colors for this species, null if this species does not typically - * have hair. - */ - hairColors?: Maybe>>; - /** A planet that this species originates from. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The language commonly spoken by this species. */ - language?: Maybe; - /** The name of this species. */ - name?: Maybe; - personConnection?: Maybe; - /** - * Common skin colors for this species, null if this species does not typically - * have skin. - */ - skinColors?: Maybe>>; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesPersonConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type SpeciesConnection = { - __typename?: 'SpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesEdge = { - __typename?: 'SpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesFilmsConnection = { - __typename?: 'SpeciesFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesFilmsEdge = { - __typename?: 'SpeciesFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesPeopleConnection = { - __typename?: 'SpeciesPeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesPeopleEdge = { - __typename?: 'SpeciesPeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type Starship = Node & { - __typename?: 'Starship'; - /** - * The Maximum number of Megalights this starship can travel in a standard hour. - * A "Megalight" is a standard unit of distance and has never been defined before - * within the Star Wars universe. This figure is only really useful for measuring - * the difference in speed of starships. We can assume it is similar to AU, the - * distance between our Sun (Sol) and Earth. - */ - MGLT?: Maybe; - /** The maximum number of kilograms that this starship can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this starship can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this starship new, in galactic credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this starship. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The class of this starships hyperdrive. */ - hyperdriveRating?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this starship in meters. */ - length?: Maybe; - /** The manufacturers of this starship. */ - manufacturers?: Maybe>>; - /** - * The maximum speed of this starship in atmosphere. null if this starship is - * incapable of atmosphering flight. - */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this starship. Such as "T-65 X-wing" or "DS-1 - * Orbital Battle Station". - */ - model?: Maybe; - /** The name of this starship. The common name, such as "Death Star". */ - name?: Maybe; - /** The number of non-essential people this starship can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** - * The class of this starship, such as "Starfighter" or "Deep Space Mobile - * Battlestation" - */ - starshipClass?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipPilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type StarshipFilmsConnection = { - __typename?: 'StarshipFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipFilmsEdge = { - __typename?: 'StarshipFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipPilotsConnection = { - __typename?: 'StarshipPilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipPilotsEdge = { - __typename?: 'StarshipPilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipsConnection = { - __typename?: 'StarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipsEdge = { - __typename?: 'StarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type Vehicle = Node & { - __typename?: 'Vehicle'; - /** The maximum number of kilograms that this vehicle can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this vehicle can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this vehicle new, in Galactic Credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this vehicle. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this vehicle in meters. */ - length?: Maybe; - /** The manufacturers of this vehicle. */ - manufacturers?: Maybe>>; - /** The maximum speed of this vehicle in atmosphere. */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this vehicle. Such as "All-Terrain Attack - * Transport". - */ - model?: Maybe; - /** - * The name of this vehicle. The common name, such as "Sand Crawler" or "Speeder - * bike". - */ - name?: Maybe; - /** The number of non-essential people this vehicle can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** The class of this vehicle, such as "Wheeled" or "Repulsorcraft". */ - vehicleClass?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehicleFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehiclePilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type VehicleFilmsConnection = { - __typename?: 'VehicleFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehicleFilmsEdge = { - __typename?: 'VehicleFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclePilotsConnection = { - __typename?: 'VehiclePilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehiclePilotsEdge = { - __typename?: 'VehiclePilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclesConnection = { - __typename?: 'VehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type VehiclesEdge = { - __typename?: 'VehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ first: number; }>; diff --git a/examples/react/http-executor/src/gql/graphql.ts b/examples/react/http-executor/src/gql/graphql.ts index e6603fce09d..0341892a345 100644 --- a/examples/react/http-executor/src/gql/graphql.ts +++ b/examples/react/http-executor/src/gql/graphql.ts @@ -1,1285 +1,10 @@ /* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A single film. */ -export type Film = Node & { - __typename?: 'Film'; - characterConnection?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The name of the director of this film. */ - director?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** The episode number of this film. */ - episodeID?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The opening paragraphs at the beginning of this film. */ - openingCrawl?: Maybe; - planetConnection?: Maybe; - /** The name(s) of the producer(s) of this film. */ - producers?: Maybe>>; - /** The ISO 8601 date format of film release at original creator country. */ - releaseDate?: Maybe; - speciesConnection?: Maybe; - starshipConnection?: Maybe; - /** The title of this film. */ - title?: Maybe; - vehicleConnection?: Maybe; -}; - -/** A single film. */ -export type FilmCharacterConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmPlanetConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmSpeciesConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type FilmCharactersConnection = { - __typename?: 'FilmCharactersConnection'; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - characters?: Maybe>>; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmCharactersEdge = { - __typename?: 'FilmCharactersEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmPlanetsConnection = { - __typename?: 'FilmPlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmPlanetsEdge = { - __typename?: 'FilmPlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmSpeciesConnection = { - __typename?: 'FilmSpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmSpeciesEdge = { - __typename?: 'FilmSpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmStarshipsConnection = { - __typename?: 'FilmStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmStarshipsEdge = { - __typename?: 'FilmStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmVehiclesConnection = { - __typename?: 'FilmVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type FilmVehiclesEdge = { - __typename?: 'FilmVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmsConnection = { - __typename?: 'FilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmsEdge = { - __typename?: 'FilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An object with an ID */ -export type Node = { - /** The id of the object. */ - id: Scalars['ID']['output']; -}; - -/** Information about pagination in a connection. */ -export type PageInfo = { - __typename?: 'PageInfo'; - /** When paginating forwards, the cursor to continue. */ - endCursor?: Maybe; - /** When paginating forwards, are there more items? */ - hasNextPage: Scalars['Boolean']['output']; - /** When paginating backwards, are there more items? */ - hasPreviousPage: Scalars['Boolean']['output']; - /** When paginating backwards, the cursor to continue. */ - startCursor?: Maybe; -}; - -/** A connection to a list of items. */ -export type PeopleConnection = { - __typename?: 'PeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PeopleEdge = { - __typename?: 'PeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type Person = Node & { - __typename?: 'Person'; - /** - * The birth year of the person, using the in-universe standard of BBY or ABY - - * Before the Battle of Yavin or After the Battle of Yavin. The Battle of Yavin is - * a battle that occurs at the end of Star Wars episode IV: A New Hope. - */ - birthYear?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * The eye color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have an eye. - */ - eyeColor?: Maybe; - filmConnection?: Maybe; - /** - * The gender of this person. Either "Male", "Female" or "unknown", - * "n/a" if the person does not have a gender. - */ - gender?: Maybe; - /** - * The hair color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have hair. - */ - hairColor?: Maybe; - /** The height of the person in centimeters. */ - height?: Maybe; - /** A planet that this person was born on or inhabits. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The mass of the person in kilograms. */ - mass?: Maybe; - /** The name of this person. */ - name?: Maybe; - /** The skin color of this person. */ - skinColor?: Maybe; - /** The species that this person belongs to, or null if unknown. */ - species?: Maybe; - starshipConnection?: Maybe; - vehicleConnection?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PersonFilmsConnection = { - __typename?: 'PersonFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonFilmsEdge = { - __typename?: 'PersonFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonStarshipsConnection = { - __typename?: 'PersonStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonStarshipsEdge = { - __typename?: 'PersonStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonVehiclesConnection = { - __typename?: 'PersonVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type PersonVehiclesEdge = { - __typename?: 'PersonVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type Planet = Node & { - __typename?: 'Planet'; - /** The climates of this planet. */ - climates?: Maybe>>; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The diameter of this planet in kilometers. */ - diameter?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** - * A number denoting the gravity of this planet, where "1" is normal or 1 standard - * G. "2" is twice or 2 standard Gs. "0.5" is half or 0.5 standard Gs. - */ - gravity?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The name of this planet. */ - name?: Maybe; - /** - * The number of standard days it takes for this planet to complete a single orbit - * of its local star. - */ - orbitalPeriod?: Maybe; - /** The average population of sentient beings inhabiting this planet. */ - population?: Maybe; - residentConnection?: Maybe; - /** - * The number of standard hours it takes for this planet to complete a single - * rotation on its axis. - */ - rotationPeriod?: Maybe; - /** - * The percentage of the planet surface that is naturally occurring water or bodies - * of water. - */ - surfaceWater?: Maybe; - /** The terrains of this planet. */ - terrains?: Maybe>>; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetResidentConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PlanetFilmsConnection = { - __typename?: 'PlanetFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetFilmsEdge = { - __typename?: 'PlanetFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetResidentsConnection = { - __typename?: 'PlanetResidentsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - residents?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetResidentsEdge = { - __typename?: 'PlanetResidentsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetsConnection = { - __typename?: 'PlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetsEdge = { - __typename?: 'PlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -export type Root = { - __typename?: 'Root'; - allFilms?: Maybe; - allPeople?: Maybe; - allPlanets?: Maybe; - allSpecies?: Maybe; - allStarships?: Maybe; - allVehicles?: Maybe; - film?: Maybe; - /** Fetches an object given its ID */ - node?: Maybe; - person?: Maybe; - planet?: Maybe; - species?: Maybe; - starship?: Maybe; - vehicle?: Maybe; -}; - -export type RootAllFilmsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPeopleArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPlanetsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllSpeciesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllStarshipsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllVehiclesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootFilmArgs = { - filmID?: InputMaybe; - id?: InputMaybe; -}; - -export type RootNodeArgs = { - id: Scalars['ID']['input']; -}; - -export type RootPersonArgs = { - id?: InputMaybe; - personID?: InputMaybe; -}; - -export type RootPlanetArgs = { - id?: InputMaybe; - planetID?: InputMaybe; -}; - -export type RootSpeciesArgs = { - id?: InputMaybe; - speciesID?: InputMaybe; -}; - -export type RootStarshipArgs = { - id?: InputMaybe; - starshipID?: InputMaybe; -}; - -export type RootVehicleArgs = { - id?: InputMaybe; - vehicleID?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type Species = Node & { - __typename?: 'Species'; - /** The average height of this species in centimeters. */ - averageHeight?: Maybe; - /** The average lifespan of this species in years, null if unknown. */ - averageLifespan?: Maybe; - /** The classification of this species, such as "mammal" or "reptile". */ - classification?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The designation of this species, such as "sentient". */ - designation?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * Common eye colors for this species, null if this species does not typically - * have eyes. - */ - eyeColors?: Maybe>>; - filmConnection?: Maybe; - /** - * Common hair colors for this species, null if this species does not typically - * have hair. - */ - hairColors?: Maybe>>; - /** A planet that this species originates from. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The language commonly spoken by this species. */ - language?: Maybe; - /** The name of this species. */ - name?: Maybe; - personConnection?: Maybe; - /** - * Common skin colors for this species, null if this species does not typically - * have skin. - */ - skinColors?: Maybe>>; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesPersonConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type SpeciesConnection = { - __typename?: 'SpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesEdge = { - __typename?: 'SpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesFilmsConnection = { - __typename?: 'SpeciesFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesFilmsEdge = { - __typename?: 'SpeciesFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesPeopleConnection = { - __typename?: 'SpeciesPeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesPeopleEdge = { - __typename?: 'SpeciesPeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type Starship = Node & { - __typename?: 'Starship'; - /** - * The Maximum number of Megalights this starship can travel in a standard hour. - * A "Megalight" is a standard unit of distance and has never been defined before - * within the Star Wars universe. This figure is only really useful for measuring - * the difference in speed of starships. We can assume it is similar to AU, the - * distance between our Sun (Sol) and Earth. - */ - MGLT?: Maybe; - /** The maximum number of kilograms that this starship can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this starship can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this starship new, in galactic credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this starship. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The class of this starships hyperdrive. */ - hyperdriveRating?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this starship in meters. */ - length?: Maybe; - /** The manufacturers of this starship. */ - manufacturers?: Maybe>>; - /** - * The maximum speed of this starship in atmosphere. null if this starship is - * incapable of atmosphering flight. - */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this starship. Such as "T-65 X-wing" or "DS-1 - * Orbital Battle Station". - */ - model?: Maybe; - /** The name of this starship. The common name, such as "Death Star". */ - name?: Maybe; - /** The number of non-essential people this starship can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** - * The class of this starship, such as "Starfighter" or "Deep Space Mobile - * Battlestation" - */ - starshipClass?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipPilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type StarshipFilmsConnection = { - __typename?: 'StarshipFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipFilmsEdge = { - __typename?: 'StarshipFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipPilotsConnection = { - __typename?: 'StarshipPilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipPilotsEdge = { - __typename?: 'StarshipPilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipsConnection = { - __typename?: 'StarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipsEdge = { - __typename?: 'StarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type Vehicle = Node & { - __typename?: 'Vehicle'; - /** The maximum number of kilograms that this vehicle can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this vehicle can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this vehicle new, in Galactic Credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this vehicle. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this vehicle in meters. */ - length?: Maybe; - /** The manufacturers of this vehicle. */ - manufacturers?: Maybe>>; - /** The maximum speed of this vehicle in atmosphere. */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this vehicle. Such as "All-Terrain Attack - * Transport". - */ - model?: Maybe; - /** - * The name of this vehicle. The common name, such as "Sand Crawler" or "Speeder - * bike". - */ - name?: Maybe; - /** The number of non-essential people this vehicle can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** The class of this vehicle, such as "Wheeled" or "Repulsorcraft". */ - vehicleClass?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehicleFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehiclePilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type VehicleFilmsConnection = { - __typename?: 'VehicleFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehicleFilmsEdge = { - __typename?: 'VehicleFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclePilotsConnection = { - __typename?: 'VehiclePilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehiclePilotsEdge = { - __typename?: 'VehiclePilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclesConnection = { - __typename?: 'VehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type VehiclesEdge = { - __typename?: 'VehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ first: number; }>; diff --git a/examples/react/tanstack-react-query/src/gql/graphql.ts b/examples/react/tanstack-react-query/src/gql/graphql.ts index afc9b7af363..c42ceb185cf 100644 --- a/examples/react/tanstack-react-query/src/gql/graphql.ts +++ b/examples/react/tanstack-react-query/src/gql/graphql.ts @@ -1,1285 +1,10 @@ /* eslint-disable */ import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A single film. */ -export type Film = Node & { - __typename?: 'Film'; - characterConnection?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The name of the director of this film. */ - director?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** The episode number of this film. */ - episodeID?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The opening paragraphs at the beginning of this film. */ - openingCrawl?: Maybe; - planetConnection?: Maybe; - /** The name(s) of the producer(s) of this film. */ - producers?: Maybe>>; - /** The ISO 8601 date format of film release at original creator country. */ - releaseDate?: Maybe; - speciesConnection?: Maybe; - starshipConnection?: Maybe; - /** The title of this film. */ - title?: Maybe; - vehicleConnection?: Maybe; -}; - -/** A single film. */ -export type FilmCharacterConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmPlanetConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmSpeciesConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type FilmCharactersConnection = { - __typename?: 'FilmCharactersConnection'; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - characters?: Maybe>>; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmCharactersEdge = { - __typename?: 'FilmCharactersEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmPlanetsConnection = { - __typename?: 'FilmPlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmPlanetsEdge = { - __typename?: 'FilmPlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmSpeciesConnection = { - __typename?: 'FilmSpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmSpeciesEdge = { - __typename?: 'FilmSpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmStarshipsConnection = { - __typename?: 'FilmStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmStarshipsEdge = { - __typename?: 'FilmStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmVehiclesConnection = { - __typename?: 'FilmVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type FilmVehiclesEdge = { - __typename?: 'FilmVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmsConnection = { - __typename?: 'FilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmsEdge = { - __typename?: 'FilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An object with an ID */ -export type Node = { - /** The id of the object. */ - id: Scalars['ID']['output']; -}; - -/** Information about pagination in a connection. */ -export type PageInfo = { - __typename?: 'PageInfo'; - /** When paginating forwards, the cursor to continue. */ - endCursor?: Maybe; - /** When paginating forwards, are there more items? */ - hasNextPage: Scalars['Boolean']['output']; - /** When paginating backwards, are there more items? */ - hasPreviousPage: Scalars['Boolean']['output']; - /** When paginating backwards, the cursor to continue. */ - startCursor?: Maybe; -}; - -/** A connection to a list of items. */ -export type PeopleConnection = { - __typename?: 'PeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PeopleEdge = { - __typename?: 'PeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type Person = Node & { - __typename?: 'Person'; - /** - * The birth year of the person, using the in-universe standard of BBY or ABY - - * Before the Battle of Yavin or After the Battle of Yavin. The Battle of Yavin is - * a battle that occurs at the end of Star Wars episode IV: A New Hope. - */ - birthYear?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * The eye color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have an eye. - */ - eyeColor?: Maybe; - filmConnection?: Maybe; - /** - * The gender of this person. Either "Male", "Female" or "unknown", - * "n/a" if the person does not have a gender. - */ - gender?: Maybe; - /** - * The hair color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have hair. - */ - hairColor?: Maybe; - /** The height of the person in centimeters. */ - height?: Maybe; - /** A planet that this person was born on or inhabits. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The mass of the person in kilograms. */ - mass?: Maybe; - /** The name of this person. */ - name?: Maybe; - /** The skin color of this person. */ - skinColor?: Maybe; - /** The species that this person belongs to, or null if unknown. */ - species?: Maybe; - starshipConnection?: Maybe; - vehicleConnection?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PersonFilmsConnection = { - __typename?: 'PersonFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonFilmsEdge = { - __typename?: 'PersonFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonStarshipsConnection = { - __typename?: 'PersonStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonStarshipsEdge = { - __typename?: 'PersonStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonVehiclesConnection = { - __typename?: 'PersonVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type PersonVehiclesEdge = { - __typename?: 'PersonVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type Planet = Node & { - __typename?: 'Planet'; - /** The climates of this planet. */ - climates?: Maybe>>; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The diameter of this planet in kilometers. */ - diameter?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** - * A number denoting the gravity of this planet, where "1" is normal or 1 standard - * G. "2" is twice or 2 standard Gs. "0.5" is half or 0.5 standard Gs. - */ - gravity?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The name of this planet. */ - name?: Maybe; - /** - * The number of standard days it takes for this planet to complete a single orbit - * of its local star. - */ - orbitalPeriod?: Maybe; - /** The average population of sentient beings inhabiting this planet. */ - population?: Maybe; - residentConnection?: Maybe; - /** - * The number of standard hours it takes for this planet to complete a single - * rotation on its axis. - */ - rotationPeriod?: Maybe; - /** - * The percentage of the planet surface that is naturally occurring water or bodies - * of water. - */ - surfaceWater?: Maybe; - /** The terrains of this planet. */ - terrains?: Maybe>>; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetResidentConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PlanetFilmsConnection = { - __typename?: 'PlanetFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetFilmsEdge = { - __typename?: 'PlanetFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetResidentsConnection = { - __typename?: 'PlanetResidentsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - residents?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetResidentsEdge = { - __typename?: 'PlanetResidentsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetsConnection = { - __typename?: 'PlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetsEdge = { - __typename?: 'PlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -export type Root = { - __typename?: 'Root'; - allFilms?: Maybe; - allPeople?: Maybe; - allPlanets?: Maybe; - allSpecies?: Maybe; - allStarships?: Maybe; - allVehicles?: Maybe; - film?: Maybe; - /** Fetches an object given its ID */ - node?: Maybe; - person?: Maybe; - planet?: Maybe; - species?: Maybe; - starship?: Maybe; - vehicle?: Maybe; -}; - -export type RootAllFilmsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPeopleArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPlanetsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllSpeciesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllStarshipsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllVehiclesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootFilmArgs = { - filmID?: InputMaybe; - id?: InputMaybe; -}; - -export type RootNodeArgs = { - id: Scalars['ID']['input']; -}; - -export type RootPersonArgs = { - id?: InputMaybe; - personID?: InputMaybe; -}; - -export type RootPlanetArgs = { - id?: InputMaybe; - planetID?: InputMaybe; -}; - -export type RootSpeciesArgs = { - id?: InputMaybe; - speciesID?: InputMaybe; -}; - -export type RootStarshipArgs = { - id?: InputMaybe; - starshipID?: InputMaybe; -}; - -export type RootVehicleArgs = { - id?: InputMaybe; - vehicleID?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type Species = Node & { - __typename?: 'Species'; - /** The average height of this species in centimeters. */ - averageHeight?: Maybe; - /** The average lifespan of this species in years, null if unknown. */ - averageLifespan?: Maybe; - /** The classification of this species, such as "mammal" or "reptile". */ - classification?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The designation of this species, such as "sentient". */ - designation?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * Common eye colors for this species, null if this species does not typically - * have eyes. - */ - eyeColors?: Maybe>>; - filmConnection?: Maybe; - /** - * Common hair colors for this species, null if this species does not typically - * have hair. - */ - hairColors?: Maybe>>; - /** A planet that this species originates from. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The language commonly spoken by this species. */ - language?: Maybe; - /** The name of this species. */ - name?: Maybe; - personConnection?: Maybe; - /** - * Common skin colors for this species, null if this species does not typically - * have skin. - */ - skinColors?: Maybe>>; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesPersonConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type SpeciesConnection = { - __typename?: 'SpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesEdge = { - __typename?: 'SpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesFilmsConnection = { - __typename?: 'SpeciesFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesFilmsEdge = { - __typename?: 'SpeciesFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesPeopleConnection = { - __typename?: 'SpeciesPeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesPeopleEdge = { - __typename?: 'SpeciesPeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type Starship = Node & { - __typename?: 'Starship'; - /** - * The Maximum number of Megalights this starship can travel in a standard hour. - * A "Megalight" is a standard unit of distance and has never been defined before - * within the Star Wars universe. This figure is only really useful for measuring - * the difference in speed of starships. We can assume it is similar to AU, the - * distance between our Sun (Sol) and Earth. - */ - MGLT?: Maybe; - /** The maximum number of kilograms that this starship can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this starship can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this starship new, in galactic credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this starship. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The class of this starships hyperdrive. */ - hyperdriveRating?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this starship in meters. */ - length?: Maybe; - /** The manufacturers of this starship. */ - manufacturers?: Maybe>>; - /** - * The maximum speed of this starship in atmosphere. null if this starship is - * incapable of atmosphering flight. - */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this starship. Such as "T-65 X-wing" or "DS-1 - * Orbital Battle Station". - */ - model?: Maybe; - /** The name of this starship. The common name, such as "Death Star". */ - name?: Maybe; - /** The number of non-essential people this starship can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** - * The class of this starship, such as "Starfighter" or "Deep Space Mobile - * Battlestation" - */ - starshipClass?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipPilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type StarshipFilmsConnection = { - __typename?: 'StarshipFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipFilmsEdge = { - __typename?: 'StarshipFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipPilotsConnection = { - __typename?: 'StarshipPilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipPilotsEdge = { - __typename?: 'StarshipPilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipsConnection = { - __typename?: 'StarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipsEdge = { - __typename?: 'StarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type Vehicle = Node & { - __typename?: 'Vehicle'; - /** The maximum number of kilograms that this vehicle can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this vehicle can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this vehicle new, in Galactic Credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this vehicle. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this vehicle in meters. */ - length?: Maybe; - /** The manufacturers of this vehicle. */ - manufacturers?: Maybe>>; - /** The maximum speed of this vehicle in atmosphere. */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this vehicle. Such as "All-Terrain Attack - * Transport". - */ - model?: Maybe; - /** - * The name of this vehicle. The common name, such as "Sand Crawler" or "Speeder - * bike". - */ - name?: Maybe; - /** The number of non-essential people this vehicle can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** The class of this vehicle, such as "Wheeled" or "Repulsorcraft". */ - vehicleClass?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehicleFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehiclePilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type VehicleFilmsConnection = { - __typename?: 'VehicleFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehicleFilmsEdge = { - __typename?: 'VehicleFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclePilotsConnection = { - __typename?: 'VehiclePilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehiclePilotsEdge = { - __typename?: 'VehiclePilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclesConnection = { - __typename?: 'VehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type VehiclesEdge = { - __typename?: 'VehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ first: number; }>; diff --git a/examples/react/urql/src/gql/graphql.ts b/examples/react/urql/src/gql/graphql.ts index baf11154cf0..da41e38e420 100644 --- a/examples/react/urql/src/gql/graphql.ts +++ b/examples/react/urql/src/gql/graphql.ts @@ -1,1285 +1,10 @@ /* eslint-disable */ import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A single film. */ -export type Film = Node & { - __typename?: 'Film'; - characterConnection?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The name of the director of this film. */ - director?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** The episode number of this film. */ - episodeID?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The opening paragraphs at the beginning of this film. */ - openingCrawl?: Maybe; - planetConnection?: Maybe; - /** The name(s) of the producer(s) of this film. */ - producers?: Maybe>>; - /** The ISO 8601 date format of film release at original creator country. */ - releaseDate?: Maybe; - speciesConnection?: Maybe; - starshipConnection?: Maybe; - /** The title of this film. */ - title?: Maybe; - vehicleConnection?: Maybe; -}; - -/** A single film. */ -export type FilmCharacterConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmPlanetConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmSpeciesConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type FilmCharactersConnection = { - __typename?: 'FilmCharactersConnection'; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - characters?: Maybe>>; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmCharactersEdge = { - __typename?: 'FilmCharactersEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmPlanetsConnection = { - __typename?: 'FilmPlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmPlanetsEdge = { - __typename?: 'FilmPlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmSpeciesConnection = { - __typename?: 'FilmSpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmSpeciesEdge = { - __typename?: 'FilmSpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmStarshipsConnection = { - __typename?: 'FilmStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmStarshipsEdge = { - __typename?: 'FilmStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmVehiclesConnection = { - __typename?: 'FilmVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type FilmVehiclesEdge = { - __typename?: 'FilmVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmsConnection = { - __typename?: 'FilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmsEdge = { - __typename?: 'FilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An object with an ID */ -export type Node = { - /** The id of the object. */ - id: Scalars['ID']['output']; -}; - -/** Information about pagination in a connection. */ -export type PageInfo = { - __typename?: 'PageInfo'; - /** When paginating forwards, the cursor to continue. */ - endCursor?: Maybe; - /** When paginating forwards, are there more items? */ - hasNextPage: Scalars['Boolean']['output']; - /** When paginating backwards, are there more items? */ - hasPreviousPage: Scalars['Boolean']['output']; - /** When paginating backwards, the cursor to continue. */ - startCursor?: Maybe; -}; - -/** A connection to a list of items. */ -export type PeopleConnection = { - __typename?: 'PeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PeopleEdge = { - __typename?: 'PeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type Person = Node & { - __typename?: 'Person'; - /** - * The birth year of the person, using the in-universe standard of BBY or ABY - - * Before the Battle of Yavin or After the Battle of Yavin. The Battle of Yavin is - * a battle that occurs at the end of Star Wars episode IV: A New Hope. - */ - birthYear?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * The eye color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have an eye. - */ - eyeColor?: Maybe; - filmConnection?: Maybe; - /** - * The gender of this person. Either "Male", "Female" or "unknown", - * "n/a" if the person does not have a gender. - */ - gender?: Maybe; - /** - * The hair color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have hair. - */ - hairColor?: Maybe; - /** The height of the person in centimeters. */ - height?: Maybe; - /** A planet that this person was born on or inhabits. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The mass of the person in kilograms. */ - mass?: Maybe; - /** The name of this person. */ - name?: Maybe; - /** The skin color of this person. */ - skinColor?: Maybe; - /** The species that this person belongs to, or null if unknown. */ - species?: Maybe; - starshipConnection?: Maybe; - vehicleConnection?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PersonFilmsConnection = { - __typename?: 'PersonFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonFilmsEdge = { - __typename?: 'PersonFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonStarshipsConnection = { - __typename?: 'PersonStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonStarshipsEdge = { - __typename?: 'PersonStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonVehiclesConnection = { - __typename?: 'PersonVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type PersonVehiclesEdge = { - __typename?: 'PersonVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type Planet = Node & { - __typename?: 'Planet'; - /** The climates of this planet. */ - climates?: Maybe>>; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The diameter of this planet in kilometers. */ - diameter?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** - * A number denoting the gravity of this planet, where "1" is normal or 1 standard - * G. "2" is twice or 2 standard Gs. "0.5" is half or 0.5 standard Gs. - */ - gravity?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The name of this planet. */ - name?: Maybe; - /** - * The number of standard days it takes for this planet to complete a single orbit - * of its local star. - */ - orbitalPeriod?: Maybe; - /** The average population of sentient beings inhabiting this planet. */ - population?: Maybe; - residentConnection?: Maybe; - /** - * The number of standard hours it takes for this planet to complete a single - * rotation on its axis. - */ - rotationPeriod?: Maybe; - /** - * The percentage of the planet surface that is naturally occurring water or bodies - * of water. - */ - surfaceWater?: Maybe; - /** The terrains of this planet. */ - terrains?: Maybe>>; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetResidentConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PlanetFilmsConnection = { - __typename?: 'PlanetFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetFilmsEdge = { - __typename?: 'PlanetFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetResidentsConnection = { - __typename?: 'PlanetResidentsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - residents?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetResidentsEdge = { - __typename?: 'PlanetResidentsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetsConnection = { - __typename?: 'PlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetsEdge = { - __typename?: 'PlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -export type Root = { - __typename?: 'Root'; - allFilms?: Maybe; - allPeople?: Maybe; - allPlanets?: Maybe; - allSpecies?: Maybe; - allStarships?: Maybe; - allVehicles?: Maybe; - film?: Maybe; - /** Fetches an object given its ID */ - node?: Maybe; - person?: Maybe; - planet?: Maybe; - species?: Maybe; - starship?: Maybe; - vehicle?: Maybe; -}; - -export type RootAllFilmsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPeopleArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPlanetsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllSpeciesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllStarshipsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllVehiclesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootFilmArgs = { - filmID?: InputMaybe; - id?: InputMaybe; -}; - -export type RootNodeArgs = { - id: Scalars['ID']['input']; -}; - -export type RootPersonArgs = { - id?: InputMaybe; - personID?: InputMaybe; -}; - -export type RootPlanetArgs = { - id?: InputMaybe; - planetID?: InputMaybe; -}; - -export type RootSpeciesArgs = { - id?: InputMaybe; - speciesID?: InputMaybe; -}; - -export type RootStarshipArgs = { - id?: InputMaybe; - starshipID?: InputMaybe; -}; - -export type RootVehicleArgs = { - id?: InputMaybe; - vehicleID?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type Species = Node & { - __typename?: 'Species'; - /** The average height of this species in centimeters. */ - averageHeight?: Maybe; - /** The average lifespan of this species in years, null if unknown. */ - averageLifespan?: Maybe; - /** The classification of this species, such as "mammal" or "reptile". */ - classification?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The designation of this species, such as "sentient". */ - designation?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * Common eye colors for this species, null if this species does not typically - * have eyes. - */ - eyeColors?: Maybe>>; - filmConnection?: Maybe; - /** - * Common hair colors for this species, null if this species does not typically - * have hair. - */ - hairColors?: Maybe>>; - /** A planet that this species originates from. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The language commonly spoken by this species. */ - language?: Maybe; - /** The name of this species. */ - name?: Maybe; - personConnection?: Maybe; - /** - * Common skin colors for this species, null if this species does not typically - * have skin. - */ - skinColors?: Maybe>>; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesPersonConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type SpeciesConnection = { - __typename?: 'SpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesEdge = { - __typename?: 'SpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesFilmsConnection = { - __typename?: 'SpeciesFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesFilmsEdge = { - __typename?: 'SpeciesFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesPeopleConnection = { - __typename?: 'SpeciesPeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesPeopleEdge = { - __typename?: 'SpeciesPeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type Starship = Node & { - __typename?: 'Starship'; - /** - * The Maximum number of Megalights this starship can travel in a standard hour. - * A "Megalight" is a standard unit of distance and has never been defined before - * within the Star Wars universe. This figure is only really useful for measuring - * the difference in speed of starships. We can assume it is similar to AU, the - * distance between our Sun (Sol) and Earth. - */ - MGLT?: Maybe; - /** The maximum number of kilograms that this starship can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this starship can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this starship new, in galactic credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this starship. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The class of this starships hyperdrive. */ - hyperdriveRating?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this starship in meters. */ - length?: Maybe; - /** The manufacturers of this starship. */ - manufacturers?: Maybe>>; - /** - * The maximum speed of this starship in atmosphere. null if this starship is - * incapable of atmosphering flight. - */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this starship. Such as "T-65 X-wing" or "DS-1 - * Orbital Battle Station". - */ - model?: Maybe; - /** The name of this starship. The common name, such as "Death Star". */ - name?: Maybe; - /** The number of non-essential people this starship can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** - * The class of this starship, such as "Starfighter" or "Deep Space Mobile - * Battlestation" - */ - starshipClass?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipPilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type StarshipFilmsConnection = { - __typename?: 'StarshipFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipFilmsEdge = { - __typename?: 'StarshipFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipPilotsConnection = { - __typename?: 'StarshipPilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipPilotsEdge = { - __typename?: 'StarshipPilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipsConnection = { - __typename?: 'StarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipsEdge = { - __typename?: 'StarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type Vehicle = Node & { - __typename?: 'Vehicle'; - /** The maximum number of kilograms that this vehicle can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this vehicle can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this vehicle new, in Galactic Credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this vehicle. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this vehicle in meters. */ - length?: Maybe; - /** The manufacturers of this vehicle. */ - manufacturers?: Maybe>>; - /** The maximum speed of this vehicle in atmosphere. */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this vehicle. Such as "All-Terrain Attack - * Transport". - */ - model?: Maybe; - /** - * The name of this vehicle. The common name, such as "Sand Crawler" or "Speeder - * bike". - */ - name?: Maybe; - /** The number of non-essential people this vehicle can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** The class of this vehicle, such as "Wheeled" or "Repulsorcraft". */ - vehicleClass?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehicleFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehiclePilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type VehicleFilmsConnection = { - __typename?: 'VehicleFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehicleFilmsEdge = { - __typename?: 'VehicleFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclePilotsConnection = { - __typename?: 'VehiclePilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehiclePilotsEdge = { - __typename?: 'VehiclePilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclesConnection = { - __typename?: 'VehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type VehiclesEdge = { - __typename?: 'VehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - export type AllFilmsWithVariablesQuery199QueryVariables = Exact<{ first: number; }>; diff --git a/examples/typescript-esm/src/gql/graphql.ts b/examples/typescript-esm/src/gql/graphql.ts index daf56fdeeb8..12561044a81 100644 --- a/examples/typescript-esm/src/gql/graphql.ts +++ b/examples/typescript-esm/src/gql/graphql.ts @@ -1,1285 +1,10 @@ /* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A single film. */ -export type Film = Node & { - __typename?: 'Film'; - characterConnection?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The name of the director of this film. */ - director?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** The episode number of this film. */ - episodeID?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The opening paragraphs at the beginning of this film. */ - openingCrawl?: Maybe; - planetConnection?: Maybe; - /** The name(s) of the producer(s) of this film. */ - producers?: Maybe>>; - /** The ISO 8601 date format of film release at original creator country. */ - releaseDate?: Maybe; - speciesConnection?: Maybe; - starshipConnection?: Maybe; - /** The title of this film. */ - title?: Maybe; - vehicleConnection?: Maybe; -}; - -/** A single film. */ -export type FilmCharacterConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmPlanetConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmSpeciesConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type FilmCharactersConnection = { - __typename?: 'FilmCharactersConnection'; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - characters?: Maybe>>; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmCharactersEdge = { - __typename?: 'FilmCharactersEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmPlanetsConnection = { - __typename?: 'FilmPlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmPlanetsEdge = { - __typename?: 'FilmPlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmSpeciesConnection = { - __typename?: 'FilmSpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmSpeciesEdge = { - __typename?: 'FilmSpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmStarshipsConnection = { - __typename?: 'FilmStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmStarshipsEdge = { - __typename?: 'FilmStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmVehiclesConnection = { - __typename?: 'FilmVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type FilmVehiclesEdge = { - __typename?: 'FilmVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmsConnection = { - __typename?: 'FilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmsEdge = { - __typename?: 'FilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An object with an ID */ -export type Node = { - /** The id of the object. */ - id: Scalars['ID']['output']; -}; - -/** Information about pagination in a connection. */ -export type PageInfo = { - __typename?: 'PageInfo'; - /** When paginating forwards, the cursor to continue. */ - endCursor?: Maybe; - /** When paginating forwards, are there more items? */ - hasNextPage: Scalars['Boolean']['output']; - /** When paginating backwards, are there more items? */ - hasPreviousPage: Scalars['Boolean']['output']; - /** When paginating backwards, the cursor to continue. */ - startCursor?: Maybe; -}; - -/** A connection to a list of items. */ -export type PeopleConnection = { - __typename?: 'PeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PeopleEdge = { - __typename?: 'PeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type Person = Node & { - __typename?: 'Person'; - /** - * The birth year of the person, using the in-universe standard of BBY or ABY - - * Before the Battle of Yavin or After the Battle of Yavin. The Battle of Yavin is - * a battle that occurs at the end of Star Wars episode IV: A New Hope. - */ - birthYear?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * The eye color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have an eye. - */ - eyeColor?: Maybe; - filmConnection?: Maybe; - /** - * The gender of this person. Either "Male", "Female" or "unknown", - * "n/a" if the person does not have a gender. - */ - gender?: Maybe; - /** - * The hair color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have hair. - */ - hairColor?: Maybe; - /** The height of the person in centimeters. */ - height?: Maybe; - /** A planet that this person was born on or inhabits. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The mass of the person in kilograms. */ - mass?: Maybe; - /** The name of this person. */ - name?: Maybe; - /** The skin color of this person. */ - skinColor?: Maybe; - /** The species that this person belongs to, or null if unknown. */ - species?: Maybe; - starshipConnection?: Maybe; - vehicleConnection?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PersonFilmsConnection = { - __typename?: 'PersonFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonFilmsEdge = { - __typename?: 'PersonFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonStarshipsConnection = { - __typename?: 'PersonStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonStarshipsEdge = { - __typename?: 'PersonStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonVehiclesConnection = { - __typename?: 'PersonVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type PersonVehiclesEdge = { - __typename?: 'PersonVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type Planet = Node & { - __typename?: 'Planet'; - /** The climates of this planet. */ - climates?: Maybe>>; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The diameter of this planet in kilometers. */ - diameter?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** - * A number denoting the gravity of this planet, where "1" is normal or 1 standard - * G. "2" is twice or 2 standard Gs. "0.5" is half or 0.5 standard Gs. - */ - gravity?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The name of this planet. */ - name?: Maybe; - /** - * The number of standard days it takes for this planet to complete a single orbit - * of its local star. - */ - orbitalPeriod?: Maybe; - /** The average population of sentient beings inhabiting this planet. */ - population?: Maybe; - residentConnection?: Maybe; - /** - * The number of standard hours it takes for this planet to complete a single - * rotation on its axis. - */ - rotationPeriod?: Maybe; - /** - * The percentage of the planet surface that is naturally occurring water or bodies - * of water. - */ - surfaceWater?: Maybe; - /** The terrains of this planet. */ - terrains?: Maybe>>; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetResidentConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PlanetFilmsConnection = { - __typename?: 'PlanetFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetFilmsEdge = { - __typename?: 'PlanetFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetResidentsConnection = { - __typename?: 'PlanetResidentsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - residents?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetResidentsEdge = { - __typename?: 'PlanetResidentsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetsConnection = { - __typename?: 'PlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetsEdge = { - __typename?: 'PlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -export type Root = { - __typename?: 'Root'; - allFilms?: Maybe; - allPeople?: Maybe; - allPlanets?: Maybe; - allSpecies?: Maybe; - allStarships?: Maybe; - allVehicles?: Maybe; - film?: Maybe; - /** Fetches an object given its ID */ - node?: Maybe; - person?: Maybe; - planet?: Maybe; - species?: Maybe; - starship?: Maybe; - vehicle?: Maybe; -}; - -export type RootAllFilmsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPeopleArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPlanetsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllSpeciesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllStarshipsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllVehiclesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootFilmArgs = { - filmID?: InputMaybe; - id?: InputMaybe; -}; - -export type RootNodeArgs = { - id: Scalars['ID']['input']; -}; - -export type RootPersonArgs = { - id?: InputMaybe; - personID?: InputMaybe; -}; - -export type RootPlanetArgs = { - id?: InputMaybe; - planetID?: InputMaybe; -}; - -export type RootSpeciesArgs = { - id?: InputMaybe; - speciesID?: InputMaybe; -}; - -export type RootStarshipArgs = { - id?: InputMaybe; - starshipID?: InputMaybe; -}; - -export type RootVehicleArgs = { - id?: InputMaybe; - vehicleID?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type Species = Node & { - __typename?: 'Species'; - /** The average height of this species in centimeters. */ - averageHeight?: Maybe; - /** The average lifespan of this species in years, null if unknown. */ - averageLifespan?: Maybe; - /** The classification of this species, such as "mammal" or "reptile". */ - classification?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The designation of this species, such as "sentient". */ - designation?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * Common eye colors for this species, null if this species does not typically - * have eyes. - */ - eyeColors?: Maybe>>; - filmConnection?: Maybe; - /** - * Common hair colors for this species, null if this species does not typically - * have hair. - */ - hairColors?: Maybe>>; - /** A planet that this species originates from. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The language commonly spoken by this species. */ - language?: Maybe; - /** The name of this species. */ - name?: Maybe; - personConnection?: Maybe; - /** - * Common skin colors for this species, null if this species does not typically - * have skin. - */ - skinColors?: Maybe>>; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesPersonConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type SpeciesConnection = { - __typename?: 'SpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesEdge = { - __typename?: 'SpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesFilmsConnection = { - __typename?: 'SpeciesFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesFilmsEdge = { - __typename?: 'SpeciesFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesPeopleConnection = { - __typename?: 'SpeciesPeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesPeopleEdge = { - __typename?: 'SpeciesPeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type Starship = Node & { - __typename?: 'Starship'; - /** - * The Maximum number of Megalights this starship can travel in a standard hour. - * A "Megalight" is a standard unit of distance and has never been defined before - * within the Star Wars universe. This figure is only really useful for measuring - * the difference in speed of starships. We can assume it is similar to AU, the - * distance between our Sun (Sol) and Earth. - */ - MGLT?: Maybe; - /** The maximum number of kilograms that this starship can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this starship can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this starship new, in galactic credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this starship. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The class of this starships hyperdrive. */ - hyperdriveRating?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this starship in meters. */ - length?: Maybe; - /** The manufacturers of this starship. */ - manufacturers?: Maybe>>; - /** - * The maximum speed of this starship in atmosphere. null if this starship is - * incapable of atmosphering flight. - */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this starship. Such as "T-65 X-wing" or "DS-1 - * Orbital Battle Station". - */ - model?: Maybe; - /** The name of this starship. The common name, such as "Death Star". */ - name?: Maybe; - /** The number of non-essential people this starship can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** - * The class of this starship, such as "Starfighter" or "Deep Space Mobile - * Battlestation" - */ - starshipClass?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipPilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type StarshipFilmsConnection = { - __typename?: 'StarshipFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipFilmsEdge = { - __typename?: 'StarshipFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipPilotsConnection = { - __typename?: 'StarshipPilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipPilotsEdge = { - __typename?: 'StarshipPilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipsConnection = { - __typename?: 'StarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipsEdge = { - __typename?: 'StarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type Vehicle = Node & { - __typename?: 'Vehicle'; - /** The maximum number of kilograms that this vehicle can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this vehicle can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this vehicle new, in Galactic Credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this vehicle. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this vehicle in meters. */ - length?: Maybe; - /** The manufacturers of this vehicle. */ - manufacturers?: Maybe>>; - /** The maximum speed of this vehicle in atmosphere. */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this vehicle. Such as "All-Terrain Attack - * Transport". - */ - model?: Maybe; - /** - * The name of this vehicle. The common name, such as "Sand Crawler" or "Speeder - * bike". - */ - name?: Maybe; - /** The number of non-essential people this vehicle can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** The class of this vehicle, such as "Wheeled" or "Repulsorcraft". */ - vehicleClass?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehicleFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehiclePilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type VehicleFilmsConnection = { - __typename?: 'VehicleFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehicleFilmsEdge = { - __typename?: 'VehicleFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclePilotsConnection = { - __typename?: 'VehiclePilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehiclePilotsEdge = { - __typename?: 'VehiclePilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclesConnection = { - __typename?: 'VehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type VehiclesEdge = { - __typename?: 'VehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - export type AllPeopleQueryQueryVariables = Exact<{ [key: string]: never }>; export type AllPeopleQueryQuery = { diff --git a/examples/typescript-graphql-request/src/gql/graphql.ts b/examples/typescript-graphql-request/src/gql/graphql.ts index 87f7239f348..d8e0b62d6d9 100644 --- a/examples/typescript-graphql-request/src/gql/graphql.ts +++ b/examples/typescript-graphql-request/src/gql/graphql.ts @@ -1,1285 +1,10 @@ /* eslint-disable */ import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A single film. */ -export type Film = Node & { - __typename?: 'Film'; - characterConnection?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The name of the director of this film. */ - director?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** The episode number of this film. */ - episodeID?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The opening paragraphs at the beginning of this film. */ - openingCrawl?: Maybe; - planetConnection?: Maybe; - /** The name(s) of the producer(s) of this film. */ - producers?: Maybe>>; - /** The ISO 8601 date format of film release at original creator country. */ - releaseDate?: Maybe; - speciesConnection?: Maybe; - starshipConnection?: Maybe; - /** The title of this film. */ - title?: Maybe; - vehicleConnection?: Maybe; -}; - -/** A single film. */ -export type FilmCharacterConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmPlanetConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmSpeciesConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type FilmCharactersConnection = { - __typename?: 'FilmCharactersConnection'; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - characters?: Maybe>>; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmCharactersEdge = { - __typename?: 'FilmCharactersEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmPlanetsConnection = { - __typename?: 'FilmPlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmPlanetsEdge = { - __typename?: 'FilmPlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmSpeciesConnection = { - __typename?: 'FilmSpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmSpeciesEdge = { - __typename?: 'FilmSpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmStarshipsConnection = { - __typename?: 'FilmStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmStarshipsEdge = { - __typename?: 'FilmStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmVehiclesConnection = { - __typename?: 'FilmVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type FilmVehiclesEdge = { - __typename?: 'FilmVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmsConnection = { - __typename?: 'FilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmsEdge = { - __typename?: 'FilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An object with an ID */ -export type Node = { - /** The id of the object. */ - id: Scalars['ID']['output']; -}; - -/** Information about pagination in a connection. */ -export type PageInfo = { - __typename?: 'PageInfo'; - /** When paginating forwards, the cursor to continue. */ - endCursor?: Maybe; - /** When paginating forwards, are there more items? */ - hasNextPage: Scalars['Boolean']['output']; - /** When paginating backwards, are there more items? */ - hasPreviousPage: Scalars['Boolean']['output']; - /** When paginating backwards, the cursor to continue. */ - startCursor?: Maybe; -}; - -/** A connection to a list of items. */ -export type PeopleConnection = { - __typename?: 'PeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PeopleEdge = { - __typename?: 'PeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type Person = Node & { - __typename?: 'Person'; - /** - * The birth year of the person, using the in-universe standard of BBY or ABY - - * Before the Battle of Yavin or After the Battle of Yavin. The Battle of Yavin is - * a battle that occurs at the end of Star Wars episode IV: A New Hope. - */ - birthYear?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * The eye color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have an eye. - */ - eyeColor?: Maybe; - filmConnection?: Maybe; - /** - * The gender of this person. Either "Male", "Female" or "unknown", - * "n/a" if the person does not have a gender. - */ - gender?: Maybe; - /** - * The hair color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have hair. - */ - hairColor?: Maybe; - /** The height of the person in centimeters. */ - height?: Maybe; - /** A planet that this person was born on or inhabits. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The mass of the person in kilograms. */ - mass?: Maybe; - /** The name of this person. */ - name?: Maybe; - /** The skin color of this person. */ - skinColor?: Maybe; - /** The species that this person belongs to, or null if unknown. */ - species?: Maybe; - starshipConnection?: Maybe; - vehicleConnection?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PersonFilmsConnection = { - __typename?: 'PersonFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonFilmsEdge = { - __typename?: 'PersonFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonStarshipsConnection = { - __typename?: 'PersonStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonStarshipsEdge = { - __typename?: 'PersonStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonVehiclesConnection = { - __typename?: 'PersonVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type PersonVehiclesEdge = { - __typename?: 'PersonVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type Planet = Node & { - __typename?: 'Planet'; - /** The climates of this planet. */ - climates?: Maybe>>; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The diameter of this planet in kilometers. */ - diameter?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** - * A number denoting the gravity of this planet, where "1" is normal or 1 standard - * G. "2" is twice or 2 standard Gs. "0.5" is half or 0.5 standard Gs. - */ - gravity?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The name of this planet. */ - name?: Maybe; - /** - * The number of standard days it takes for this planet to complete a single orbit - * of its local star. - */ - orbitalPeriod?: Maybe; - /** The average population of sentient beings inhabiting this planet. */ - population?: Maybe; - residentConnection?: Maybe; - /** - * The number of standard hours it takes for this planet to complete a single - * rotation on its axis. - */ - rotationPeriod?: Maybe; - /** - * The percentage of the planet surface that is naturally occurring water or bodies - * of water. - */ - surfaceWater?: Maybe; - /** The terrains of this planet. */ - terrains?: Maybe>>; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetResidentConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PlanetFilmsConnection = { - __typename?: 'PlanetFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetFilmsEdge = { - __typename?: 'PlanetFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetResidentsConnection = { - __typename?: 'PlanetResidentsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - residents?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetResidentsEdge = { - __typename?: 'PlanetResidentsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetsConnection = { - __typename?: 'PlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetsEdge = { - __typename?: 'PlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -export type Root = { - __typename?: 'Root'; - allFilms?: Maybe; - allPeople?: Maybe; - allPlanets?: Maybe; - allSpecies?: Maybe; - allStarships?: Maybe; - allVehicles?: Maybe; - film?: Maybe; - /** Fetches an object given its ID */ - node?: Maybe; - person?: Maybe; - planet?: Maybe; - species?: Maybe; - starship?: Maybe; - vehicle?: Maybe; -}; - -export type RootAllFilmsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPeopleArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPlanetsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllSpeciesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllStarshipsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllVehiclesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootFilmArgs = { - filmID?: InputMaybe; - id?: InputMaybe; -}; - -export type RootNodeArgs = { - id: Scalars['ID']['input']; -}; - -export type RootPersonArgs = { - id?: InputMaybe; - personID?: InputMaybe; -}; - -export type RootPlanetArgs = { - id?: InputMaybe; - planetID?: InputMaybe; -}; - -export type RootSpeciesArgs = { - id?: InputMaybe; - speciesID?: InputMaybe; -}; - -export type RootStarshipArgs = { - id?: InputMaybe; - starshipID?: InputMaybe; -}; - -export type RootVehicleArgs = { - id?: InputMaybe; - vehicleID?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type Species = Node & { - __typename?: 'Species'; - /** The average height of this species in centimeters. */ - averageHeight?: Maybe; - /** The average lifespan of this species in years, null if unknown. */ - averageLifespan?: Maybe; - /** The classification of this species, such as "mammal" or "reptile". */ - classification?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The designation of this species, such as "sentient". */ - designation?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * Common eye colors for this species, null if this species does not typically - * have eyes. - */ - eyeColors?: Maybe>>; - filmConnection?: Maybe; - /** - * Common hair colors for this species, null if this species does not typically - * have hair. - */ - hairColors?: Maybe>>; - /** A planet that this species originates from. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The language commonly spoken by this species. */ - language?: Maybe; - /** The name of this species. */ - name?: Maybe; - personConnection?: Maybe; - /** - * Common skin colors for this species, null if this species does not typically - * have skin. - */ - skinColors?: Maybe>>; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesPersonConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type SpeciesConnection = { - __typename?: 'SpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesEdge = { - __typename?: 'SpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesFilmsConnection = { - __typename?: 'SpeciesFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesFilmsEdge = { - __typename?: 'SpeciesFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesPeopleConnection = { - __typename?: 'SpeciesPeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesPeopleEdge = { - __typename?: 'SpeciesPeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type Starship = Node & { - __typename?: 'Starship'; - /** - * The Maximum number of Megalights this starship can travel in a standard hour. - * A "Megalight" is a standard unit of distance and has never been defined before - * within the Star Wars universe. This figure is only really useful for measuring - * the difference in speed of starships. We can assume it is similar to AU, the - * distance between our Sun (Sol) and Earth. - */ - MGLT?: Maybe; - /** The maximum number of kilograms that this starship can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this starship can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this starship new, in galactic credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this starship. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The class of this starships hyperdrive. */ - hyperdriveRating?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this starship in meters. */ - length?: Maybe; - /** The manufacturers of this starship. */ - manufacturers?: Maybe>>; - /** - * The maximum speed of this starship in atmosphere. null if this starship is - * incapable of atmosphering flight. - */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this starship. Such as "T-65 X-wing" or "DS-1 - * Orbital Battle Station". - */ - model?: Maybe; - /** The name of this starship. The common name, such as "Death Star". */ - name?: Maybe; - /** The number of non-essential people this starship can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** - * The class of this starship, such as "Starfighter" or "Deep Space Mobile - * Battlestation" - */ - starshipClass?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipPilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type StarshipFilmsConnection = { - __typename?: 'StarshipFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipFilmsEdge = { - __typename?: 'StarshipFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipPilotsConnection = { - __typename?: 'StarshipPilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipPilotsEdge = { - __typename?: 'StarshipPilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipsConnection = { - __typename?: 'StarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipsEdge = { - __typename?: 'StarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type Vehicle = Node & { - __typename?: 'Vehicle'; - /** The maximum number of kilograms that this vehicle can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this vehicle can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this vehicle new, in Galactic Credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this vehicle. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this vehicle in meters. */ - length?: Maybe; - /** The manufacturers of this vehicle. */ - manufacturers?: Maybe>>; - /** The maximum speed of this vehicle in atmosphere. */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this vehicle. Such as "All-Terrain Attack - * Transport". - */ - model?: Maybe; - /** - * The name of this vehicle. The common name, such as "Sand Crawler" or "Speeder - * bike". - */ - name?: Maybe; - /** The number of non-essential people this vehicle can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** The class of this vehicle, such as "Wheeled" or "Repulsorcraft". */ - vehicleClass?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehicleFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehiclePilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type VehicleFilmsConnection = { - __typename?: 'VehicleFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehicleFilmsEdge = { - __typename?: 'VehicleFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclePilotsConnection = { - __typename?: 'VehiclePilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehiclePilotsEdge = { - __typename?: 'VehiclePilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclesConnection = { - __typename?: 'VehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type VehiclesEdge = { - __typename?: 'VehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - export type AllPeopleQueryQueryVariables = Exact<{ [key: string]: never }>; export type AllPeopleQueryQuery = { diff --git a/examples/vite/vite-react-cts/src/gql/graphql.ts b/examples/vite/vite-react-cts/src/gql/graphql.ts index 9e980a0030e..1f179c7d1c3 100644 --- a/examples/vite/vite-react-cts/src/gql/graphql.ts +++ b/examples/vite/vite-react-cts/src/gql/graphql.ts @@ -1,1285 +1,10 @@ /* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A single film. */ -export type Film = Node & { - __typename?: 'Film'; - characterConnection?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The name of the director of this film. */ - director?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** The episode number of this film. */ - episodeID?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The opening paragraphs at the beginning of this film. */ - openingCrawl?: Maybe; - planetConnection?: Maybe; - /** The name(s) of the producer(s) of this film. */ - producers?: Maybe>>; - /** The ISO 8601 date format of film release at original creator country. */ - releaseDate?: Maybe; - speciesConnection?: Maybe; - starshipConnection?: Maybe; - /** The title of this film. */ - title?: Maybe; - vehicleConnection?: Maybe; -}; - -/** A single film. */ -export type FilmCharacterConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmPlanetConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmSpeciesConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type FilmCharactersConnection = { - __typename?: 'FilmCharactersConnection'; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - characters?: Maybe>>; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmCharactersEdge = { - __typename?: 'FilmCharactersEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmPlanetsConnection = { - __typename?: 'FilmPlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmPlanetsEdge = { - __typename?: 'FilmPlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmSpeciesConnection = { - __typename?: 'FilmSpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmSpeciesEdge = { - __typename?: 'FilmSpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmStarshipsConnection = { - __typename?: 'FilmStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmStarshipsEdge = { - __typename?: 'FilmStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmVehiclesConnection = { - __typename?: 'FilmVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type FilmVehiclesEdge = { - __typename?: 'FilmVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmsConnection = { - __typename?: 'FilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmsEdge = { - __typename?: 'FilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An object with an ID */ -export type Node = { - /** The id of the object. */ - id: Scalars['ID']['output']; -}; - -/** Information about pagination in a connection. */ -export type PageInfo = { - __typename?: 'PageInfo'; - /** When paginating forwards, the cursor to continue. */ - endCursor?: Maybe; - /** When paginating forwards, are there more items? */ - hasNextPage: Scalars['Boolean']['output']; - /** When paginating backwards, are there more items? */ - hasPreviousPage: Scalars['Boolean']['output']; - /** When paginating backwards, the cursor to continue. */ - startCursor?: Maybe; -}; - -/** A connection to a list of items. */ -export type PeopleConnection = { - __typename?: 'PeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PeopleEdge = { - __typename?: 'PeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type Person = Node & { - __typename?: 'Person'; - /** - * The birth year of the person, using the in-universe standard of BBY or ABY - - * Before the Battle of Yavin or After the Battle of Yavin. The Battle of Yavin is - * a battle that occurs at the end of Star Wars episode IV: A New Hope. - */ - birthYear?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * The eye color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have an eye. - */ - eyeColor?: Maybe; - filmConnection?: Maybe; - /** - * The gender of this person. Either "Male", "Female" or "unknown", - * "n/a" if the person does not have a gender. - */ - gender?: Maybe; - /** - * The hair color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have hair. - */ - hairColor?: Maybe; - /** The height of the person in centimeters. */ - height?: Maybe; - /** A planet that this person was born on or inhabits. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The mass of the person in kilograms. */ - mass?: Maybe; - /** The name of this person. */ - name?: Maybe; - /** The skin color of this person. */ - skinColor?: Maybe; - /** The species that this person belongs to, or null if unknown. */ - species?: Maybe; - starshipConnection?: Maybe; - vehicleConnection?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PersonFilmsConnection = { - __typename?: 'PersonFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonFilmsEdge = { - __typename?: 'PersonFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonStarshipsConnection = { - __typename?: 'PersonStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonStarshipsEdge = { - __typename?: 'PersonStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonVehiclesConnection = { - __typename?: 'PersonVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type PersonVehiclesEdge = { - __typename?: 'PersonVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type Planet = Node & { - __typename?: 'Planet'; - /** The climates of this planet. */ - climates?: Maybe>>; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The diameter of this planet in kilometers. */ - diameter?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** - * A number denoting the gravity of this planet, where "1" is normal or 1 standard - * G. "2" is twice or 2 standard Gs. "0.5" is half or 0.5 standard Gs. - */ - gravity?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The name of this planet. */ - name?: Maybe; - /** - * The number of standard days it takes for this planet to complete a single orbit - * of its local star. - */ - orbitalPeriod?: Maybe; - /** The average population of sentient beings inhabiting this planet. */ - population?: Maybe; - residentConnection?: Maybe; - /** - * The number of standard hours it takes for this planet to complete a single - * rotation on its axis. - */ - rotationPeriod?: Maybe; - /** - * The percentage of the planet surface that is naturally occurring water or bodies - * of water. - */ - surfaceWater?: Maybe; - /** The terrains of this planet. */ - terrains?: Maybe>>; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetResidentConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PlanetFilmsConnection = { - __typename?: 'PlanetFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetFilmsEdge = { - __typename?: 'PlanetFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetResidentsConnection = { - __typename?: 'PlanetResidentsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - residents?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetResidentsEdge = { - __typename?: 'PlanetResidentsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetsConnection = { - __typename?: 'PlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetsEdge = { - __typename?: 'PlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -export type Root = { - __typename?: 'Root'; - allFilms?: Maybe; - allPeople?: Maybe; - allPlanets?: Maybe; - allSpecies?: Maybe; - allStarships?: Maybe; - allVehicles?: Maybe; - film?: Maybe; - /** Fetches an object given its ID */ - node?: Maybe; - person?: Maybe; - planet?: Maybe; - species?: Maybe; - starship?: Maybe; - vehicle?: Maybe; -}; - -export type RootAllFilmsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPeopleArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPlanetsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllSpeciesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllStarshipsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllVehiclesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootFilmArgs = { - filmID?: InputMaybe; - id?: InputMaybe; -}; - -export type RootNodeArgs = { - id: Scalars['ID']['input']; -}; - -export type RootPersonArgs = { - id?: InputMaybe; - personID?: InputMaybe; -}; - -export type RootPlanetArgs = { - id?: InputMaybe; - planetID?: InputMaybe; -}; - -export type RootSpeciesArgs = { - id?: InputMaybe; - speciesID?: InputMaybe; -}; - -export type RootStarshipArgs = { - id?: InputMaybe; - starshipID?: InputMaybe; -}; - -export type RootVehicleArgs = { - id?: InputMaybe; - vehicleID?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type Species = Node & { - __typename?: 'Species'; - /** The average height of this species in centimeters. */ - averageHeight?: Maybe; - /** The average lifespan of this species in years, null if unknown. */ - averageLifespan?: Maybe; - /** The classification of this species, such as "mammal" or "reptile". */ - classification?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The designation of this species, such as "sentient". */ - designation?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * Common eye colors for this species, null if this species does not typically - * have eyes. - */ - eyeColors?: Maybe>>; - filmConnection?: Maybe; - /** - * Common hair colors for this species, null if this species does not typically - * have hair. - */ - hairColors?: Maybe>>; - /** A planet that this species originates from. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The language commonly spoken by this species. */ - language?: Maybe; - /** The name of this species. */ - name?: Maybe; - personConnection?: Maybe; - /** - * Common skin colors for this species, null if this species does not typically - * have skin. - */ - skinColors?: Maybe>>; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesPersonConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type SpeciesConnection = { - __typename?: 'SpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesEdge = { - __typename?: 'SpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesFilmsConnection = { - __typename?: 'SpeciesFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesFilmsEdge = { - __typename?: 'SpeciesFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesPeopleConnection = { - __typename?: 'SpeciesPeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesPeopleEdge = { - __typename?: 'SpeciesPeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type Starship = Node & { - __typename?: 'Starship'; - /** - * The Maximum number of Megalights this starship can travel in a standard hour. - * A "Megalight" is a standard unit of distance and has never been defined before - * within the Star Wars universe. This figure is only really useful for measuring - * the difference in speed of starships. We can assume it is similar to AU, the - * distance between our Sun (Sol) and Earth. - */ - MGLT?: Maybe; - /** The maximum number of kilograms that this starship can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this starship can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this starship new, in galactic credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this starship. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The class of this starships hyperdrive. */ - hyperdriveRating?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this starship in meters. */ - length?: Maybe; - /** The manufacturers of this starship. */ - manufacturers?: Maybe>>; - /** - * The maximum speed of this starship in atmosphere. null if this starship is - * incapable of atmosphering flight. - */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this starship. Such as "T-65 X-wing" or "DS-1 - * Orbital Battle Station". - */ - model?: Maybe; - /** The name of this starship. The common name, such as "Death Star". */ - name?: Maybe; - /** The number of non-essential people this starship can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** - * The class of this starship, such as "Starfighter" or "Deep Space Mobile - * Battlestation" - */ - starshipClass?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipPilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type StarshipFilmsConnection = { - __typename?: 'StarshipFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipFilmsEdge = { - __typename?: 'StarshipFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipPilotsConnection = { - __typename?: 'StarshipPilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipPilotsEdge = { - __typename?: 'StarshipPilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipsConnection = { - __typename?: 'StarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipsEdge = { - __typename?: 'StarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type Vehicle = Node & { - __typename?: 'Vehicle'; - /** The maximum number of kilograms that this vehicle can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this vehicle can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this vehicle new, in Galactic Credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this vehicle. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this vehicle in meters. */ - length?: Maybe; - /** The manufacturers of this vehicle. */ - manufacturers?: Maybe>>; - /** The maximum speed of this vehicle in atmosphere. */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this vehicle. Such as "All-Terrain Attack - * Transport". - */ - model?: Maybe; - /** - * The name of this vehicle. The common name, such as "Sand Crawler" or "Speeder - * bike". - */ - name?: Maybe; - /** The number of non-essential people this vehicle can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** The class of this vehicle, such as "Wheeled" or "Repulsorcraft". */ - vehicleClass?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehicleFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehiclePilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type VehicleFilmsConnection = { - __typename?: 'VehicleFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehicleFilmsEdge = { - __typename?: 'VehicleFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclePilotsConnection = { - __typename?: 'VehiclePilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehiclePilotsEdge = { - __typename?: 'VehiclePilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclesConnection = { - __typename?: 'VehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type VehiclesEdge = { - __typename?: 'VehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - export type FilmItemFragment = { __typename?: 'Film'; id: string; diff --git a/examples/vite/vite-react-mts/src/gql/graphql.ts b/examples/vite/vite-react-mts/src/gql/graphql.ts index 9e980a0030e..1f179c7d1c3 100644 --- a/examples/vite/vite-react-mts/src/gql/graphql.ts +++ b/examples/vite/vite-react-mts/src/gql/graphql.ts @@ -1,1285 +1,10 @@ /* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A single film. */ -export type Film = Node & { - __typename?: 'Film'; - characterConnection?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The name of the director of this film. */ - director?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** The episode number of this film. */ - episodeID?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The opening paragraphs at the beginning of this film. */ - openingCrawl?: Maybe; - planetConnection?: Maybe; - /** The name(s) of the producer(s) of this film. */ - producers?: Maybe>>; - /** The ISO 8601 date format of film release at original creator country. */ - releaseDate?: Maybe; - speciesConnection?: Maybe; - starshipConnection?: Maybe; - /** The title of this film. */ - title?: Maybe; - vehicleConnection?: Maybe; -}; - -/** A single film. */ -export type FilmCharacterConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmPlanetConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmSpeciesConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type FilmCharactersConnection = { - __typename?: 'FilmCharactersConnection'; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - characters?: Maybe>>; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmCharactersEdge = { - __typename?: 'FilmCharactersEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmPlanetsConnection = { - __typename?: 'FilmPlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmPlanetsEdge = { - __typename?: 'FilmPlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmSpeciesConnection = { - __typename?: 'FilmSpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmSpeciesEdge = { - __typename?: 'FilmSpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmStarshipsConnection = { - __typename?: 'FilmStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmStarshipsEdge = { - __typename?: 'FilmStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmVehiclesConnection = { - __typename?: 'FilmVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type FilmVehiclesEdge = { - __typename?: 'FilmVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmsConnection = { - __typename?: 'FilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmsEdge = { - __typename?: 'FilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An object with an ID */ -export type Node = { - /** The id of the object. */ - id: Scalars['ID']['output']; -}; - -/** Information about pagination in a connection. */ -export type PageInfo = { - __typename?: 'PageInfo'; - /** When paginating forwards, the cursor to continue. */ - endCursor?: Maybe; - /** When paginating forwards, are there more items? */ - hasNextPage: Scalars['Boolean']['output']; - /** When paginating backwards, are there more items? */ - hasPreviousPage: Scalars['Boolean']['output']; - /** When paginating backwards, the cursor to continue. */ - startCursor?: Maybe; -}; - -/** A connection to a list of items. */ -export type PeopleConnection = { - __typename?: 'PeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PeopleEdge = { - __typename?: 'PeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type Person = Node & { - __typename?: 'Person'; - /** - * The birth year of the person, using the in-universe standard of BBY or ABY - - * Before the Battle of Yavin or After the Battle of Yavin. The Battle of Yavin is - * a battle that occurs at the end of Star Wars episode IV: A New Hope. - */ - birthYear?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * The eye color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have an eye. - */ - eyeColor?: Maybe; - filmConnection?: Maybe; - /** - * The gender of this person. Either "Male", "Female" or "unknown", - * "n/a" if the person does not have a gender. - */ - gender?: Maybe; - /** - * The hair color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have hair. - */ - hairColor?: Maybe; - /** The height of the person in centimeters. */ - height?: Maybe; - /** A planet that this person was born on or inhabits. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The mass of the person in kilograms. */ - mass?: Maybe; - /** The name of this person. */ - name?: Maybe; - /** The skin color of this person. */ - skinColor?: Maybe; - /** The species that this person belongs to, or null if unknown. */ - species?: Maybe; - starshipConnection?: Maybe; - vehicleConnection?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PersonFilmsConnection = { - __typename?: 'PersonFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonFilmsEdge = { - __typename?: 'PersonFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonStarshipsConnection = { - __typename?: 'PersonStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonStarshipsEdge = { - __typename?: 'PersonStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonVehiclesConnection = { - __typename?: 'PersonVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type PersonVehiclesEdge = { - __typename?: 'PersonVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type Planet = Node & { - __typename?: 'Planet'; - /** The climates of this planet. */ - climates?: Maybe>>; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The diameter of this planet in kilometers. */ - diameter?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** - * A number denoting the gravity of this planet, where "1" is normal or 1 standard - * G. "2" is twice or 2 standard Gs. "0.5" is half or 0.5 standard Gs. - */ - gravity?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The name of this planet. */ - name?: Maybe; - /** - * The number of standard days it takes for this planet to complete a single orbit - * of its local star. - */ - orbitalPeriod?: Maybe; - /** The average population of sentient beings inhabiting this planet. */ - population?: Maybe; - residentConnection?: Maybe; - /** - * The number of standard hours it takes for this planet to complete a single - * rotation on its axis. - */ - rotationPeriod?: Maybe; - /** - * The percentage of the planet surface that is naturally occurring water or bodies - * of water. - */ - surfaceWater?: Maybe; - /** The terrains of this planet. */ - terrains?: Maybe>>; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetResidentConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PlanetFilmsConnection = { - __typename?: 'PlanetFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetFilmsEdge = { - __typename?: 'PlanetFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetResidentsConnection = { - __typename?: 'PlanetResidentsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - residents?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetResidentsEdge = { - __typename?: 'PlanetResidentsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetsConnection = { - __typename?: 'PlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetsEdge = { - __typename?: 'PlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -export type Root = { - __typename?: 'Root'; - allFilms?: Maybe; - allPeople?: Maybe; - allPlanets?: Maybe; - allSpecies?: Maybe; - allStarships?: Maybe; - allVehicles?: Maybe; - film?: Maybe; - /** Fetches an object given its ID */ - node?: Maybe; - person?: Maybe; - planet?: Maybe; - species?: Maybe; - starship?: Maybe; - vehicle?: Maybe; -}; - -export type RootAllFilmsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPeopleArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPlanetsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllSpeciesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllStarshipsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllVehiclesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootFilmArgs = { - filmID?: InputMaybe; - id?: InputMaybe; -}; - -export type RootNodeArgs = { - id: Scalars['ID']['input']; -}; - -export type RootPersonArgs = { - id?: InputMaybe; - personID?: InputMaybe; -}; - -export type RootPlanetArgs = { - id?: InputMaybe; - planetID?: InputMaybe; -}; - -export type RootSpeciesArgs = { - id?: InputMaybe; - speciesID?: InputMaybe; -}; - -export type RootStarshipArgs = { - id?: InputMaybe; - starshipID?: InputMaybe; -}; - -export type RootVehicleArgs = { - id?: InputMaybe; - vehicleID?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type Species = Node & { - __typename?: 'Species'; - /** The average height of this species in centimeters. */ - averageHeight?: Maybe; - /** The average lifespan of this species in years, null if unknown. */ - averageLifespan?: Maybe; - /** The classification of this species, such as "mammal" or "reptile". */ - classification?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The designation of this species, such as "sentient". */ - designation?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * Common eye colors for this species, null if this species does not typically - * have eyes. - */ - eyeColors?: Maybe>>; - filmConnection?: Maybe; - /** - * Common hair colors for this species, null if this species does not typically - * have hair. - */ - hairColors?: Maybe>>; - /** A planet that this species originates from. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The language commonly spoken by this species. */ - language?: Maybe; - /** The name of this species. */ - name?: Maybe; - personConnection?: Maybe; - /** - * Common skin colors for this species, null if this species does not typically - * have skin. - */ - skinColors?: Maybe>>; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesPersonConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type SpeciesConnection = { - __typename?: 'SpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesEdge = { - __typename?: 'SpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesFilmsConnection = { - __typename?: 'SpeciesFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesFilmsEdge = { - __typename?: 'SpeciesFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesPeopleConnection = { - __typename?: 'SpeciesPeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesPeopleEdge = { - __typename?: 'SpeciesPeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type Starship = Node & { - __typename?: 'Starship'; - /** - * The Maximum number of Megalights this starship can travel in a standard hour. - * A "Megalight" is a standard unit of distance and has never been defined before - * within the Star Wars universe. This figure is only really useful for measuring - * the difference in speed of starships. We can assume it is similar to AU, the - * distance between our Sun (Sol) and Earth. - */ - MGLT?: Maybe; - /** The maximum number of kilograms that this starship can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this starship can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this starship new, in galactic credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this starship. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The class of this starships hyperdrive. */ - hyperdriveRating?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this starship in meters. */ - length?: Maybe; - /** The manufacturers of this starship. */ - manufacturers?: Maybe>>; - /** - * The maximum speed of this starship in atmosphere. null if this starship is - * incapable of atmosphering flight. - */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this starship. Such as "T-65 X-wing" or "DS-1 - * Orbital Battle Station". - */ - model?: Maybe; - /** The name of this starship. The common name, such as "Death Star". */ - name?: Maybe; - /** The number of non-essential people this starship can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** - * The class of this starship, such as "Starfighter" or "Deep Space Mobile - * Battlestation" - */ - starshipClass?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipPilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type StarshipFilmsConnection = { - __typename?: 'StarshipFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipFilmsEdge = { - __typename?: 'StarshipFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipPilotsConnection = { - __typename?: 'StarshipPilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipPilotsEdge = { - __typename?: 'StarshipPilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipsConnection = { - __typename?: 'StarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipsEdge = { - __typename?: 'StarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type Vehicle = Node & { - __typename?: 'Vehicle'; - /** The maximum number of kilograms that this vehicle can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this vehicle can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this vehicle new, in Galactic Credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this vehicle. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this vehicle in meters. */ - length?: Maybe; - /** The manufacturers of this vehicle. */ - manufacturers?: Maybe>>; - /** The maximum speed of this vehicle in atmosphere. */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this vehicle. Such as "All-Terrain Attack - * Transport". - */ - model?: Maybe; - /** - * The name of this vehicle. The common name, such as "Sand Crawler" or "Speeder - * bike". - */ - name?: Maybe; - /** The number of non-essential people this vehicle can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** The class of this vehicle, such as "Wheeled" or "Repulsorcraft". */ - vehicleClass?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehicleFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehiclePilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type VehicleFilmsConnection = { - __typename?: 'VehicleFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehicleFilmsEdge = { - __typename?: 'VehicleFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclePilotsConnection = { - __typename?: 'VehiclePilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehiclePilotsEdge = { - __typename?: 'VehiclePilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclesConnection = { - __typename?: 'VehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type VehiclesEdge = { - __typename?: 'VehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - export type FilmItemFragment = { __typename?: 'Film'; id: string; diff --git a/examples/vite/vite-react-ts/src/gql/graphql.ts b/examples/vite/vite-react-ts/src/gql/graphql.ts index 9e980a0030e..1f179c7d1c3 100644 --- a/examples/vite/vite-react-ts/src/gql/graphql.ts +++ b/examples/vite/vite-react-ts/src/gql/graphql.ts @@ -1,1285 +1,10 @@ /* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A single film. */ -export type Film = Node & { - __typename?: 'Film'; - characterConnection?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The name of the director of this film. */ - director?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** The episode number of this film. */ - episodeID?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The opening paragraphs at the beginning of this film. */ - openingCrawl?: Maybe; - planetConnection?: Maybe; - /** The name(s) of the producer(s) of this film. */ - producers?: Maybe>>; - /** The ISO 8601 date format of film release at original creator country. */ - releaseDate?: Maybe; - speciesConnection?: Maybe; - starshipConnection?: Maybe; - /** The title of this film. */ - title?: Maybe; - vehicleConnection?: Maybe; -}; - -/** A single film. */ -export type FilmCharacterConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmPlanetConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmSpeciesConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type FilmCharactersConnection = { - __typename?: 'FilmCharactersConnection'; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - characters?: Maybe>>; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmCharactersEdge = { - __typename?: 'FilmCharactersEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmPlanetsConnection = { - __typename?: 'FilmPlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmPlanetsEdge = { - __typename?: 'FilmPlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmSpeciesConnection = { - __typename?: 'FilmSpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmSpeciesEdge = { - __typename?: 'FilmSpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmStarshipsConnection = { - __typename?: 'FilmStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmStarshipsEdge = { - __typename?: 'FilmStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmVehiclesConnection = { - __typename?: 'FilmVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type FilmVehiclesEdge = { - __typename?: 'FilmVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmsConnection = { - __typename?: 'FilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmsEdge = { - __typename?: 'FilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An object with an ID */ -export type Node = { - /** The id of the object. */ - id: Scalars['ID']['output']; -}; - -/** Information about pagination in a connection. */ -export type PageInfo = { - __typename?: 'PageInfo'; - /** When paginating forwards, the cursor to continue. */ - endCursor?: Maybe; - /** When paginating forwards, are there more items? */ - hasNextPage: Scalars['Boolean']['output']; - /** When paginating backwards, are there more items? */ - hasPreviousPage: Scalars['Boolean']['output']; - /** When paginating backwards, the cursor to continue. */ - startCursor?: Maybe; -}; - -/** A connection to a list of items. */ -export type PeopleConnection = { - __typename?: 'PeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PeopleEdge = { - __typename?: 'PeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type Person = Node & { - __typename?: 'Person'; - /** - * The birth year of the person, using the in-universe standard of BBY or ABY - - * Before the Battle of Yavin or After the Battle of Yavin. The Battle of Yavin is - * a battle that occurs at the end of Star Wars episode IV: A New Hope. - */ - birthYear?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * The eye color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have an eye. - */ - eyeColor?: Maybe; - filmConnection?: Maybe; - /** - * The gender of this person. Either "Male", "Female" or "unknown", - * "n/a" if the person does not have a gender. - */ - gender?: Maybe; - /** - * The hair color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have hair. - */ - hairColor?: Maybe; - /** The height of the person in centimeters. */ - height?: Maybe; - /** A planet that this person was born on or inhabits. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The mass of the person in kilograms. */ - mass?: Maybe; - /** The name of this person. */ - name?: Maybe; - /** The skin color of this person. */ - skinColor?: Maybe; - /** The species that this person belongs to, or null if unknown. */ - species?: Maybe; - starshipConnection?: Maybe; - vehicleConnection?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PersonFilmsConnection = { - __typename?: 'PersonFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonFilmsEdge = { - __typename?: 'PersonFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonStarshipsConnection = { - __typename?: 'PersonStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonStarshipsEdge = { - __typename?: 'PersonStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonVehiclesConnection = { - __typename?: 'PersonVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type PersonVehiclesEdge = { - __typename?: 'PersonVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type Planet = Node & { - __typename?: 'Planet'; - /** The climates of this planet. */ - climates?: Maybe>>; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The diameter of this planet in kilometers. */ - diameter?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** - * A number denoting the gravity of this planet, where "1" is normal or 1 standard - * G. "2" is twice or 2 standard Gs. "0.5" is half or 0.5 standard Gs. - */ - gravity?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The name of this planet. */ - name?: Maybe; - /** - * The number of standard days it takes for this planet to complete a single orbit - * of its local star. - */ - orbitalPeriod?: Maybe; - /** The average population of sentient beings inhabiting this planet. */ - population?: Maybe; - residentConnection?: Maybe; - /** - * The number of standard hours it takes for this planet to complete a single - * rotation on its axis. - */ - rotationPeriod?: Maybe; - /** - * The percentage of the planet surface that is naturally occurring water or bodies - * of water. - */ - surfaceWater?: Maybe; - /** The terrains of this planet. */ - terrains?: Maybe>>; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetResidentConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PlanetFilmsConnection = { - __typename?: 'PlanetFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetFilmsEdge = { - __typename?: 'PlanetFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetResidentsConnection = { - __typename?: 'PlanetResidentsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - residents?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetResidentsEdge = { - __typename?: 'PlanetResidentsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetsConnection = { - __typename?: 'PlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetsEdge = { - __typename?: 'PlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -export type Root = { - __typename?: 'Root'; - allFilms?: Maybe; - allPeople?: Maybe; - allPlanets?: Maybe; - allSpecies?: Maybe; - allStarships?: Maybe; - allVehicles?: Maybe; - film?: Maybe; - /** Fetches an object given its ID */ - node?: Maybe; - person?: Maybe; - planet?: Maybe; - species?: Maybe; - starship?: Maybe; - vehicle?: Maybe; -}; - -export type RootAllFilmsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPeopleArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPlanetsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllSpeciesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllStarshipsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllVehiclesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootFilmArgs = { - filmID?: InputMaybe; - id?: InputMaybe; -}; - -export type RootNodeArgs = { - id: Scalars['ID']['input']; -}; - -export type RootPersonArgs = { - id?: InputMaybe; - personID?: InputMaybe; -}; - -export type RootPlanetArgs = { - id?: InputMaybe; - planetID?: InputMaybe; -}; - -export type RootSpeciesArgs = { - id?: InputMaybe; - speciesID?: InputMaybe; -}; - -export type RootStarshipArgs = { - id?: InputMaybe; - starshipID?: InputMaybe; -}; - -export type RootVehicleArgs = { - id?: InputMaybe; - vehicleID?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type Species = Node & { - __typename?: 'Species'; - /** The average height of this species in centimeters. */ - averageHeight?: Maybe; - /** The average lifespan of this species in years, null if unknown. */ - averageLifespan?: Maybe; - /** The classification of this species, such as "mammal" or "reptile". */ - classification?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The designation of this species, such as "sentient". */ - designation?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * Common eye colors for this species, null if this species does not typically - * have eyes. - */ - eyeColors?: Maybe>>; - filmConnection?: Maybe; - /** - * Common hair colors for this species, null if this species does not typically - * have hair. - */ - hairColors?: Maybe>>; - /** A planet that this species originates from. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The language commonly spoken by this species. */ - language?: Maybe; - /** The name of this species. */ - name?: Maybe; - personConnection?: Maybe; - /** - * Common skin colors for this species, null if this species does not typically - * have skin. - */ - skinColors?: Maybe>>; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesPersonConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type SpeciesConnection = { - __typename?: 'SpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesEdge = { - __typename?: 'SpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesFilmsConnection = { - __typename?: 'SpeciesFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesFilmsEdge = { - __typename?: 'SpeciesFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesPeopleConnection = { - __typename?: 'SpeciesPeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesPeopleEdge = { - __typename?: 'SpeciesPeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type Starship = Node & { - __typename?: 'Starship'; - /** - * The Maximum number of Megalights this starship can travel in a standard hour. - * A "Megalight" is a standard unit of distance and has never been defined before - * within the Star Wars universe. This figure is only really useful for measuring - * the difference in speed of starships. We can assume it is similar to AU, the - * distance between our Sun (Sol) and Earth. - */ - MGLT?: Maybe; - /** The maximum number of kilograms that this starship can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this starship can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this starship new, in galactic credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this starship. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The class of this starships hyperdrive. */ - hyperdriveRating?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this starship in meters. */ - length?: Maybe; - /** The manufacturers of this starship. */ - manufacturers?: Maybe>>; - /** - * The maximum speed of this starship in atmosphere. null if this starship is - * incapable of atmosphering flight. - */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this starship. Such as "T-65 X-wing" or "DS-1 - * Orbital Battle Station". - */ - model?: Maybe; - /** The name of this starship. The common name, such as "Death Star". */ - name?: Maybe; - /** The number of non-essential people this starship can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** - * The class of this starship, such as "Starfighter" or "Deep Space Mobile - * Battlestation" - */ - starshipClass?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipPilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type StarshipFilmsConnection = { - __typename?: 'StarshipFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipFilmsEdge = { - __typename?: 'StarshipFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipPilotsConnection = { - __typename?: 'StarshipPilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipPilotsEdge = { - __typename?: 'StarshipPilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipsConnection = { - __typename?: 'StarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipsEdge = { - __typename?: 'StarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type Vehicle = Node & { - __typename?: 'Vehicle'; - /** The maximum number of kilograms that this vehicle can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this vehicle can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this vehicle new, in Galactic Credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this vehicle. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this vehicle in meters. */ - length?: Maybe; - /** The manufacturers of this vehicle. */ - manufacturers?: Maybe>>; - /** The maximum speed of this vehicle in atmosphere. */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this vehicle. Such as "All-Terrain Attack - * Transport". - */ - model?: Maybe; - /** - * The name of this vehicle. The common name, such as "Sand Crawler" or "Speeder - * bike". - */ - name?: Maybe; - /** The number of non-essential people this vehicle can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** The class of this vehicle, such as "Wheeled" or "Repulsorcraft". */ - vehicleClass?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehicleFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehiclePilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type VehicleFilmsConnection = { - __typename?: 'VehicleFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehicleFilmsEdge = { - __typename?: 'VehicleFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclePilotsConnection = { - __typename?: 'VehiclePilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehiclePilotsEdge = { - __typename?: 'VehiclePilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclesConnection = { - __typename?: 'VehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type VehiclesEdge = { - __typename?: 'VehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - export type FilmItemFragment = { __typename?: 'Film'; id: string; diff --git a/examples/vue/apollo-composable/src/gql/graphql.ts b/examples/vue/apollo-composable/src/gql/graphql.ts index 9d071c8d1df..b9b34fd54d4 100644 --- a/examples/vue/apollo-composable/src/gql/graphql.ts +++ b/examples/vue/apollo-composable/src/gql/graphql.ts @@ -1,1285 +1,10 @@ /* eslint-disable */ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A single film. */ -export type Film = Node & { - __typename?: 'Film'; - characterConnection?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The name of the director of this film. */ - director?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** The episode number of this film. */ - episodeID?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The opening paragraphs at the beginning of this film. */ - openingCrawl?: Maybe; - planetConnection?: Maybe; - /** The name(s) of the producer(s) of this film. */ - producers?: Maybe>>; - /** The ISO 8601 date format of film release at original creator country. */ - releaseDate?: Maybe; - speciesConnection?: Maybe; - starshipConnection?: Maybe; - /** The title of this film. */ - title?: Maybe; - vehicleConnection?: Maybe; -}; - -/** A single film. */ -export type FilmCharacterConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmPlanetConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmSpeciesConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type FilmCharactersConnection = { - __typename?: 'FilmCharactersConnection'; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - characters?: Maybe>>; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmCharactersEdge = { - __typename?: 'FilmCharactersEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmPlanetsConnection = { - __typename?: 'FilmPlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmPlanetsEdge = { - __typename?: 'FilmPlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmSpeciesConnection = { - __typename?: 'FilmSpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmSpeciesEdge = { - __typename?: 'FilmSpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmStarshipsConnection = { - __typename?: 'FilmStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmStarshipsEdge = { - __typename?: 'FilmStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmVehiclesConnection = { - __typename?: 'FilmVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type FilmVehiclesEdge = { - __typename?: 'FilmVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmsConnection = { - __typename?: 'FilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmsEdge = { - __typename?: 'FilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An object with an ID */ -export type Node = { - /** The id of the object. */ - id: Scalars['ID']['output']; -}; - -/** Information about pagination in a connection. */ -export type PageInfo = { - __typename?: 'PageInfo'; - /** When paginating forwards, the cursor to continue. */ - endCursor?: Maybe; - /** When paginating forwards, are there more items? */ - hasNextPage: Scalars['Boolean']['output']; - /** When paginating backwards, are there more items? */ - hasPreviousPage: Scalars['Boolean']['output']; - /** When paginating backwards, the cursor to continue. */ - startCursor?: Maybe; -}; - -/** A connection to a list of items. */ -export type PeopleConnection = { - __typename?: 'PeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PeopleEdge = { - __typename?: 'PeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type Person = Node & { - __typename?: 'Person'; - /** - * The birth year of the person, using the in-universe standard of BBY or ABY - - * Before the Battle of Yavin or After the Battle of Yavin. The Battle of Yavin is - * a battle that occurs at the end of Star Wars episode IV: A New Hope. - */ - birthYear?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * The eye color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have an eye. - */ - eyeColor?: Maybe; - filmConnection?: Maybe; - /** - * The gender of this person. Either "Male", "Female" or "unknown", - * "n/a" if the person does not have a gender. - */ - gender?: Maybe; - /** - * The hair color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have hair. - */ - hairColor?: Maybe; - /** The height of the person in centimeters. */ - height?: Maybe; - /** A planet that this person was born on or inhabits. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The mass of the person in kilograms. */ - mass?: Maybe; - /** The name of this person. */ - name?: Maybe; - /** The skin color of this person. */ - skinColor?: Maybe; - /** The species that this person belongs to, or null if unknown. */ - species?: Maybe; - starshipConnection?: Maybe; - vehicleConnection?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PersonFilmsConnection = { - __typename?: 'PersonFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonFilmsEdge = { - __typename?: 'PersonFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonStarshipsConnection = { - __typename?: 'PersonStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonStarshipsEdge = { - __typename?: 'PersonStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonVehiclesConnection = { - __typename?: 'PersonVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type PersonVehiclesEdge = { - __typename?: 'PersonVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type Planet = Node & { - __typename?: 'Planet'; - /** The climates of this planet. */ - climates?: Maybe>>; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The diameter of this planet in kilometers. */ - diameter?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** - * A number denoting the gravity of this planet, where "1" is normal or 1 standard - * G. "2" is twice or 2 standard Gs. "0.5" is half or 0.5 standard Gs. - */ - gravity?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The name of this planet. */ - name?: Maybe; - /** - * The number of standard days it takes for this planet to complete a single orbit - * of its local star. - */ - orbitalPeriod?: Maybe; - /** The average population of sentient beings inhabiting this planet. */ - population?: Maybe; - residentConnection?: Maybe; - /** - * The number of standard hours it takes for this planet to complete a single - * rotation on its axis. - */ - rotationPeriod?: Maybe; - /** - * The percentage of the planet surface that is naturally occurring water or bodies - * of water. - */ - surfaceWater?: Maybe; - /** The terrains of this planet. */ - terrains?: Maybe>>; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetResidentConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PlanetFilmsConnection = { - __typename?: 'PlanetFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetFilmsEdge = { - __typename?: 'PlanetFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetResidentsConnection = { - __typename?: 'PlanetResidentsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - residents?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetResidentsEdge = { - __typename?: 'PlanetResidentsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetsConnection = { - __typename?: 'PlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetsEdge = { - __typename?: 'PlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -export type Root = { - __typename?: 'Root'; - allFilms?: Maybe; - allPeople?: Maybe; - allPlanets?: Maybe; - allSpecies?: Maybe; - allStarships?: Maybe; - allVehicles?: Maybe; - film?: Maybe; - /** Fetches an object given its ID */ - node?: Maybe; - person?: Maybe; - planet?: Maybe; - species?: Maybe; - starship?: Maybe; - vehicle?: Maybe; -}; - -export type RootAllFilmsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPeopleArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPlanetsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllSpeciesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllStarshipsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllVehiclesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootFilmArgs = { - filmID?: InputMaybe; - id?: InputMaybe; -}; - -export type RootNodeArgs = { - id: Scalars['ID']['input']; -}; - -export type RootPersonArgs = { - id?: InputMaybe; - personID?: InputMaybe; -}; - -export type RootPlanetArgs = { - id?: InputMaybe; - planetID?: InputMaybe; -}; - -export type RootSpeciesArgs = { - id?: InputMaybe; - speciesID?: InputMaybe; -}; - -export type RootStarshipArgs = { - id?: InputMaybe; - starshipID?: InputMaybe; -}; - -export type RootVehicleArgs = { - id?: InputMaybe; - vehicleID?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type Species = Node & { - __typename?: 'Species'; - /** The average height of this species in centimeters. */ - averageHeight?: Maybe; - /** The average lifespan of this species in years, null if unknown. */ - averageLifespan?: Maybe; - /** The classification of this species, such as "mammal" or "reptile". */ - classification?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The designation of this species, such as "sentient". */ - designation?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * Common eye colors for this species, null if this species does not typically - * have eyes. - */ - eyeColors?: Maybe>>; - filmConnection?: Maybe; - /** - * Common hair colors for this species, null if this species does not typically - * have hair. - */ - hairColors?: Maybe>>; - /** A planet that this species originates from. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The language commonly spoken by this species. */ - language?: Maybe; - /** The name of this species. */ - name?: Maybe; - personConnection?: Maybe; - /** - * Common skin colors for this species, null if this species does not typically - * have skin. - */ - skinColors?: Maybe>>; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesPersonConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type SpeciesConnection = { - __typename?: 'SpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesEdge = { - __typename?: 'SpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesFilmsConnection = { - __typename?: 'SpeciesFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesFilmsEdge = { - __typename?: 'SpeciesFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesPeopleConnection = { - __typename?: 'SpeciesPeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesPeopleEdge = { - __typename?: 'SpeciesPeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type Starship = Node & { - __typename?: 'Starship'; - /** - * The Maximum number of Megalights this starship can travel in a standard hour. - * A "Megalight" is a standard unit of distance and has never been defined before - * within the Star Wars universe. This figure is only really useful for measuring - * the difference in speed of starships. We can assume it is similar to AU, the - * distance between our Sun (Sol) and Earth. - */ - MGLT?: Maybe; - /** The maximum number of kilograms that this starship can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this starship can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this starship new, in galactic credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this starship. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The class of this starships hyperdrive. */ - hyperdriveRating?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this starship in meters. */ - length?: Maybe; - /** The manufacturers of this starship. */ - manufacturers?: Maybe>>; - /** - * The maximum speed of this starship in atmosphere. null if this starship is - * incapable of atmosphering flight. - */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this starship. Such as "T-65 X-wing" or "DS-1 - * Orbital Battle Station". - */ - model?: Maybe; - /** The name of this starship. The common name, such as "Death Star". */ - name?: Maybe; - /** The number of non-essential people this starship can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** - * The class of this starship, such as "Starfighter" or "Deep Space Mobile - * Battlestation" - */ - starshipClass?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipPilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type StarshipFilmsConnection = { - __typename?: 'StarshipFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipFilmsEdge = { - __typename?: 'StarshipFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipPilotsConnection = { - __typename?: 'StarshipPilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipPilotsEdge = { - __typename?: 'StarshipPilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipsConnection = { - __typename?: 'StarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipsEdge = { - __typename?: 'StarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type Vehicle = Node & { - __typename?: 'Vehicle'; - /** The maximum number of kilograms that this vehicle can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this vehicle can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this vehicle new, in Galactic Credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this vehicle. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this vehicle in meters. */ - length?: Maybe; - /** The manufacturers of this vehicle. */ - manufacturers?: Maybe>>; - /** The maximum speed of this vehicle in atmosphere. */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this vehicle. Such as "All-Terrain Attack - * Transport". - */ - model?: Maybe; - /** - * The name of this vehicle. The common name, such as "Sand Crawler" or "Speeder - * bike". - */ - name?: Maybe; - /** The number of non-essential people this vehicle can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** The class of this vehicle, such as "Wheeled" or "Repulsorcraft". */ - vehicleClass?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehicleFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehiclePilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type VehicleFilmsConnection = { - __typename?: 'VehicleFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehicleFilmsEdge = { - __typename?: 'VehicleFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclePilotsConnection = { - __typename?: 'VehiclePilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehiclePilotsEdge = { - __typename?: 'VehiclePilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclesConnection = { - __typename?: 'VehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type VehiclesEdge = { - __typename?: 'VehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ first: number; }>; diff --git a/examples/vue/urql/src/gql/graphql.ts b/examples/vue/urql/src/gql/graphql.ts index 9d071c8d1df..b9b34fd54d4 100644 --- a/examples/vue/urql/src/gql/graphql.ts +++ b/examples/vue/urql/src/gql/graphql.ts @@ -1,1285 +1,10 @@ /* eslint-disable */ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A single film. */ -export type Film = Node & { - __typename?: 'Film'; - characterConnection?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The name of the director of this film. */ - director?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** The episode number of this film. */ - episodeID?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The opening paragraphs at the beginning of this film. */ - openingCrawl?: Maybe; - planetConnection?: Maybe; - /** The name(s) of the producer(s) of this film. */ - producers?: Maybe>>; - /** The ISO 8601 date format of film release at original creator country. */ - releaseDate?: Maybe; - speciesConnection?: Maybe; - starshipConnection?: Maybe; - /** The title of this film. */ - title?: Maybe; - vehicleConnection?: Maybe; -}; - -/** A single film. */ -export type FilmCharacterConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmPlanetConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmSpeciesConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type FilmCharactersConnection = { - __typename?: 'FilmCharactersConnection'; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - characters?: Maybe>>; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmCharactersEdge = { - __typename?: 'FilmCharactersEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmPlanetsConnection = { - __typename?: 'FilmPlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmPlanetsEdge = { - __typename?: 'FilmPlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmSpeciesConnection = { - __typename?: 'FilmSpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmSpeciesEdge = { - __typename?: 'FilmSpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmStarshipsConnection = { - __typename?: 'FilmStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmStarshipsEdge = { - __typename?: 'FilmStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmVehiclesConnection = { - __typename?: 'FilmVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type FilmVehiclesEdge = { - __typename?: 'FilmVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmsConnection = { - __typename?: 'FilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmsEdge = { - __typename?: 'FilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An object with an ID */ -export type Node = { - /** The id of the object. */ - id: Scalars['ID']['output']; -}; - -/** Information about pagination in a connection. */ -export type PageInfo = { - __typename?: 'PageInfo'; - /** When paginating forwards, the cursor to continue. */ - endCursor?: Maybe; - /** When paginating forwards, are there more items? */ - hasNextPage: Scalars['Boolean']['output']; - /** When paginating backwards, are there more items? */ - hasPreviousPage: Scalars['Boolean']['output']; - /** When paginating backwards, the cursor to continue. */ - startCursor?: Maybe; -}; - -/** A connection to a list of items. */ -export type PeopleConnection = { - __typename?: 'PeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PeopleEdge = { - __typename?: 'PeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type Person = Node & { - __typename?: 'Person'; - /** - * The birth year of the person, using the in-universe standard of BBY or ABY - - * Before the Battle of Yavin or After the Battle of Yavin. The Battle of Yavin is - * a battle that occurs at the end of Star Wars episode IV: A New Hope. - */ - birthYear?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * The eye color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have an eye. - */ - eyeColor?: Maybe; - filmConnection?: Maybe; - /** - * The gender of this person. Either "Male", "Female" or "unknown", - * "n/a" if the person does not have a gender. - */ - gender?: Maybe; - /** - * The hair color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have hair. - */ - hairColor?: Maybe; - /** The height of the person in centimeters. */ - height?: Maybe; - /** A planet that this person was born on or inhabits. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The mass of the person in kilograms. */ - mass?: Maybe; - /** The name of this person. */ - name?: Maybe; - /** The skin color of this person. */ - skinColor?: Maybe; - /** The species that this person belongs to, or null if unknown. */ - species?: Maybe; - starshipConnection?: Maybe; - vehicleConnection?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PersonFilmsConnection = { - __typename?: 'PersonFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonFilmsEdge = { - __typename?: 'PersonFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonStarshipsConnection = { - __typename?: 'PersonStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonStarshipsEdge = { - __typename?: 'PersonStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonVehiclesConnection = { - __typename?: 'PersonVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type PersonVehiclesEdge = { - __typename?: 'PersonVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type Planet = Node & { - __typename?: 'Planet'; - /** The climates of this planet. */ - climates?: Maybe>>; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The diameter of this planet in kilometers. */ - diameter?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** - * A number denoting the gravity of this planet, where "1" is normal or 1 standard - * G. "2" is twice or 2 standard Gs. "0.5" is half or 0.5 standard Gs. - */ - gravity?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The name of this planet. */ - name?: Maybe; - /** - * The number of standard days it takes for this planet to complete a single orbit - * of its local star. - */ - orbitalPeriod?: Maybe; - /** The average population of sentient beings inhabiting this planet. */ - population?: Maybe; - residentConnection?: Maybe; - /** - * The number of standard hours it takes for this planet to complete a single - * rotation on its axis. - */ - rotationPeriod?: Maybe; - /** - * The percentage of the planet surface that is naturally occurring water or bodies - * of water. - */ - surfaceWater?: Maybe; - /** The terrains of this planet. */ - terrains?: Maybe>>; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetResidentConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PlanetFilmsConnection = { - __typename?: 'PlanetFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetFilmsEdge = { - __typename?: 'PlanetFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetResidentsConnection = { - __typename?: 'PlanetResidentsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - residents?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetResidentsEdge = { - __typename?: 'PlanetResidentsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetsConnection = { - __typename?: 'PlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetsEdge = { - __typename?: 'PlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -export type Root = { - __typename?: 'Root'; - allFilms?: Maybe; - allPeople?: Maybe; - allPlanets?: Maybe; - allSpecies?: Maybe; - allStarships?: Maybe; - allVehicles?: Maybe; - film?: Maybe; - /** Fetches an object given its ID */ - node?: Maybe; - person?: Maybe; - planet?: Maybe; - species?: Maybe; - starship?: Maybe; - vehicle?: Maybe; -}; - -export type RootAllFilmsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPeopleArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPlanetsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllSpeciesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllStarshipsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllVehiclesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootFilmArgs = { - filmID?: InputMaybe; - id?: InputMaybe; -}; - -export type RootNodeArgs = { - id: Scalars['ID']['input']; -}; - -export type RootPersonArgs = { - id?: InputMaybe; - personID?: InputMaybe; -}; - -export type RootPlanetArgs = { - id?: InputMaybe; - planetID?: InputMaybe; -}; - -export type RootSpeciesArgs = { - id?: InputMaybe; - speciesID?: InputMaybe; -}; - -export type RootStarshipArgs = { - id?: InputMaybe; - starshipID?: InputMaybe; -}; - -export type RootVehicleArgs = { - id?: InputMaybe; - vehicleID?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type Species = Node & { - __typename?: 'Species'; - /** The average height of this species in centimeters. */ - averageHeight?: Maybe; - /** The average lifespan of this species in years, null if unknown. */ - averageLifespan?: Maybe; - /** The classification of this species, such as "mammal" or "reptile". */ - classification?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The designation of this species, such as "sentient". */ - designation?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * Common eye colors for this species, null if this species does not typically - * have eyes. - */ - eyeColors?: Maybe>>; - filmConnection?: Maybe; - /** - * Common hair colors for this species, null if this species does not typically - * have hair. - */ - hairColors?: Maybe>>; - /** A planet that this species originates from. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The language commonly spoken by this species. */ - language?: Maybe; - /** The name of this species. */ - name?: Maybe; - personConnection?: Maybe; - /** - * Common skin colors for this species, null if this species does not typically - * have skin. - */ - skinColors?: Maybe>>; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesPersonConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type SpeciesConnection = { - __typename?: 'SpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesEdge = { - __typename?: 'SpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesFilmsConnection = { - __typename?: 'SpeciesFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesFilmsEdge = { - __typename?: 'SpeciesFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesPeopleConnection = { - __typename?: 'SpeciesPeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesPeopleEdge = { - __typename?: 'SpeciesPeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type Starship = Node & { - __typename?: 'Starship'; - /** - * The Maximum number of Megalights this starship can travel in a standard hour. - * A "Megalight" is a standard unit of distance and has never been defined before - * within the Star Wars universe. This figure is only really useful for measuring - * the difference in speed of starships. We can assume it is similar to AU, the - * distance between our Sun (Sol) and Earth. - */ - MGLT?: Maybe; - /** The maximum number of kilograms that this starship can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this starship can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this starship new, in galactic credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this starship. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The class of this starships hyperdrive. */ - hyperdriveRating?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this starship in meters. */ - length?: Maybe; - /** The manufacturers of this starship. */ - manufacturers?: Maybe>>; - /** - * The maximum speed of this starship in atmosphere. null if this starship is - * incapable of atmosphering flight. - */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this starship. Such as "T-65 X-wing" or "DS-1 - * Orbital Battle Station". - */ - model?: Maybe; - /** The name of this starship. The common name, such as "Death Star". */ - name?: Maybe; - /** The number of non-essential people this starship can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** - * The class of this starship, such as "Starfighter" or "Deep Space Mobile - * Battlestation" - */ - starshipClass?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipPilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type StarshipFilmsConnection = { - __typename?: 'StarshipFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipFilmsEdge = { - __typename?: 'StarshipFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipPilotsConnection = { - __typename?: 'StarshipPilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipPilotsEdge = { - __typename?: 'StarshipPilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipsConnection = { - __typename?: 'StarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipsEdge = { - __typename?: 'StarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type Vehicle = Node & { - __typename?: 'Vehicle'; - /** The maximum number of kilograms that this vehicle can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this vehicle can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this vehicle new, in Galactic Credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this vehicle. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this vehicle in meters. */ - length?: Maybe; - /** The manufacturers of this vehicle. */ - manufacturers?: Maybe>>; - /** The maximum speed of this vehicle in atmosphere. */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this vehicle. Such as "All-Terrain Attack - * Transport". - */ - model?: Maybe; - /** - * The name of this vehicle. The common name, such as "Sand Crawler" or "Speeder - * bike". - */ - name?: Maybe; - /** The number of non-essential people this vehicle can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** The class of this vehicle, such as "Wheeled" or "Repulsorcraft". */ - vehicleClass?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehicleFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehiclePilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type VehicleFilmsConnection = { - __typename?: 'VehicleFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehicleFilmsEdge = { - __typename?: 'VehicleFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclePilotsConnection = { - __typename?: 'VehiclePilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehiclePilotsEdge = { - __typename?: 'VehiclePilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclesConnection = { - __typename?: 'VehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type VehiclesEdge = { - __typename?: 'VehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ first: number; }>; diff --git a/examples/vue/villus/src/gql/graphql.ts b/examples/vue/villus/src/gql/graphql.ts index 9d071c8d1df..b9b34fd54d4 100644 --- a/examples/vue/villus/src/gql/graphql.ts +++ b/examples/vue/villus/src/gql/graphql.ts @@ -1,1285 +1,10 @@ /* eslint-disable */ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -/** A single film. */ -export type Film = Node & { - __typename?: 'Film'; - characterConnection?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The name of the director of this film. */ - director?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** The episode number of this film. */ - episodeID?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The opening paragraphs at the beginning of this film. */ - openingCrawl?: Maybe; - planetConnection?: Maybe; - /** The name(s) of the producer(s) of this film. */ - producers?: Maybe>>; - /** The ISO 8601 date format of film release at original creator country. */ - releaseDate?: Maybe; - speciesConnection?: Maybe; - starshipConnection?: Maybe; - /** The title of this film. */ - title?: Maybe; - vehicleConnection?: Maybe; -}; - -/** A single film. */ -export type FilmCharacterConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmPlanetConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmSpeciesConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single film. */ -export type FilmVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type FilmCharactersConnection = { - __typename?: 'FilmCharactersConnection'; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - characters?: Maybe>>; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmCharactersEdge = { - __typename?: 'FilmCharactersEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmPlanetsConnection = { - __typename?: 'FilmPlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmPlanetsEdge = { - __typename?: 'FilmPlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmSpeciesConnection = { - __typename?: 'FilmSpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmSpeciesEdge = { - __typename?: 'FilmSpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmStarshipsConnection = { - __typename?: 'FilmStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmStarshipsEdge = { - __typename?: 'FilmStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmVehiclesConnection = { - __typename?: 'FilmVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type FilmVehiclesEdge = { - __typename?: 'FilmVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type FilmsConnection = { - __typename?: 'FilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type FilmsEdge = { - __typename?: 'FilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An object with an ID */ -export type Node = { - /** The id of the object. */ - id: Scalars['ID']['output']; -}; - -/** Information about pagination in a connection. */ -export type PageInfo = { - __typename?: 'PageInfo'; - /** When paginating forwards, the cursor to continue. */ - endCursor?: Maybe; - /** When paginating forwards, are there more items? */ - hasNextPage: Scalars['Boolean']['output']; - /** When paginating backwards, are there more items? */ - hasPreviousPage: Scalars['Boolean']['output']; - /** When paginating backwards, the cursor to continue. */ - startCursor?: Maybe; -}; - -/** A connection to a list of items. */ -export type PeopleConnection = { - __typename?: 'PeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PeopleEdge = { - __typename?: 'PeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type Person = Node & { - __typename?: 'Person'; - /** - * The birth year of the person, using the in-universe standard of BBY or ABY - - * Before the Battle of Yavin or After the Battle of Yavin. The Battle of Yavin is - * a battle that occurs at the end of Star Wars episode IV: A New Hope. - */ - birthYear?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * The eye color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have an eye. - */ - eyeColor?: Maybe; - filmConnection?: Maybe; - /** - * The gender of this person. Either "Male", "Female" or "unknown", - * "n/a" if the person does not have a gender. - */ - gender?: Maybe; - /** - * The hair color of this person. Will be "unknown" if not known or "n/a" if the - * person does not have hair. - */ - hairColor?: Maybe; - /** The height of the person in centimeters. */ - height?: Maybe; - /** A planet that this person was born on or inhabits. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The mass of the person in kilograms. */ - mass?: Maybe; - /** The name of this person. */ - name?: Maybe; - /** The skin color of this person. */ - skinColor?: Maybe; - /** The species that this person belongs to, or null if unknown. */ - species?: Maybe; - starshipConnection?: Maybe; - vehicleConnection?: Maybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonStarshipConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** An individual person or character within the Star Wars universe. */ -export type PersonVehicleConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PersonFilmsConnection = { - __typename?: 'PersonFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonFilmsEdge = { - __typename?: 'PersonFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonStarshipsConnection = { - __typename?: 'PersonStarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PersonStarshipsEdge = { - __typename?: 'PersonStarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PersonVehiclesConnection = { - __typename?: 'PersonVehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type PersonVehiclesEdge = { - __typename?: 'PersonVehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type Planet = Node & { - __typename?: 'Planet'; - /** The climates of this planet. */ - climates?: Maybe>>; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The diameter of this planet in kilometers. */ - diameter?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** - * A number denoting the gravity of this planet, where "1" is normal or 1 standard - * G. "2" is twice or 2 standard Gs. "0.5" is half or 0.5 standard Gs. - */ - gravity?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The name of this planet. */ - name?: Maybe; - /** - * The number of standard days it takes for this planet to complete a single orbit - * of its local star. - */ - orbitalPeriod?: Maybe; - /** The average population of sentient beings inhabiting this planet. */ - population?: Maybe; - residentConnection?: Maybe; - /** - * The number of standard hours it takes for this planet to complete a single - * rotation on its axis. - */ - rotationPeriod?: Maybe; - /** - * The percentage of the planet surface that is naturally occurring water or bodies - * of water. - */ - surfaceWater?: Maybe; - /** The terrains of this planet. */ - terrains?: Maybe>>; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** - * A large mass, planet or planetoid in the Star Wars Universe, at the time of - * 0 ABY. - */ -export type PlanetResidentConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type PlanetFilmsConnection = { - __typename?: 'PlanetFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetFilmsEdge = { - __typename?: 'PlanetFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetResidentsConnection = { - __typename?: 'PlanetResidentsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - residents?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetResidentsEdge = { - __typename?: 'PlanetResidentsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type PlanetsConnection = { - __typename?: 'PlanetsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - planets?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type PlanetsEdge = { - __typename?: 'PlanetsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -export type Root = { - __typename?: 'Root'; - allFilms?: Maybe; - allPeople?: Maybe; - allPlanets?: Maybe; - allSpecies?: Maybe; - allStarships?: Maybe; - allVehicles?: Maybe; - film?: Maybe; - /** Fetches an object given its ID */ - node?: Maybe; - person?: Maybe; - planet?: Maybe; - species?: Maybe; - starship?: Maybe; - vehicle?: Maybe; -}; - -export type RootAllFilmsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPeopleArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllPlanetsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllSpeciesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllStarshipsArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootAllVehiclesArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -export type RootFilmArgs = { - filmID?: InputMaybe; - id?: InputMaybe; -}; - -export type RootNodeArgs = { - id: Scalars['ID']['input']; -}; - -export type RootPersonArgs = { - id?: InputMaybe; - personID?: InputMaybe; -}; - -export type RootPlanetArgs = { - id?: InputMaybe; - planetID?: InputMaybe; -}; - -export type RootSpeciesArgs = { - id?: InputMaybe; - speciesID?: InputMaybe; -}; - -export type RootStarshipArgs = { - id?: InputMaybe; - starshipID?: InputMaybe; -}; - -export type RootVehicleArgs = { - id?: InputMaybe; - vehicleID?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type Species = Node & { - __typename?: 'Species'; - /** The average height of this species in centimeters. */ - averageHeight?: Maybe; - /** The average lifespan of this species in years, null if unknown. */ - averageLifespan?: Maybe; - /** The classification of this species, such as "mammal" or "reptile". */ - classification?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The designation of this species, such as "sentient". */ - designation?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - /** - * Common eye colors for this species, null if this species does not typically - * have eyes. - */ - eyeColors?: Maybe>>; - filmConnection?: Maybe; - /** - * Common hair colors for this species, null if this species does not typically - * have hair. - */ - hairColors?: Maybe>>; - /** A planet that this species originates from. */ - homeworld?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The language commonly spoken by this species. */ - language?: Maybe; - /** The name of this species. */ - name?: Maybe; - personConnection?: Maybe; - /** - * Common skin colors for this species, null if this species does not typically - * have skin. - */ - skinColors?: Maybe>>; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A type of person or character within the Star Wars Universe. */ -export type SpeciesPersonConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type SpeciesConnection = { - __typename?: 'SpeciesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - species?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesEdge = { - __typename?: 'SpeciesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesFilmsConnection = { - __typename?: 'SpeciesFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesFilmsEdge = { - __typename?: 'SpeciesFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type SpeciesPeopleConnection = { - __typename?: 'SpeciesPeopleConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - people?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type SpeciesPeopleEdge = { - __typename?: 'SpeciesPeopleEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type Starship = Node & { - __typename?: 'Starship'; - /** - * The Maximum number of Megalights this starship can travel in a standard hour. - * A "Megalight" is a standard unit of distance and has never been defined before - * within the Star Wars universe. This figure is only really useful for measuring - * the difference in speed of starships. We can assume it is similar to AU, the - * distance between our Sun (Sol) and Earth. - */ - MGLT?: Maybe; - /** The maximum number of kilograms that this starship can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this starship can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this starship new, in galactic credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this starship. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The class of this starships hyperdrive. */ - hyperdriveRating?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this starship in meters. */ - length?: Maybe; - /** The manufacturers of this starship. */ - manufacturers?: Maybe>>; - /** - * The maximum speed of this starship in atmosphere. null if this starship is - * incapable of atmosphering flight. - */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this starship. Such as "T-65 X-wing" or "DS-1 - * Orbital Battle Station". - */ - model?: Maybe; - /** The name of this starship. The common name, such as "Death Star". */ - name?: Maybe; - /** The number of non-essential people this starship can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** - * The class of this starship, such as "Starfighter" or "Deep Space Mobile - * Battlestation" - */ - starshipClass?: Maybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that has hyperdrive capability. */ -export type StarshipPilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type StarshipFilmsConnection = { - __typename?: 'StarshipFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipFilmsEdge = { - __typename?: 'StarshipFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipPilotsConnection = { - __typename?: 'StarshipPilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipPilotsEdge = { - __typename?: 'StarshipPilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type StarshipsConnection = { - __typename?: 'StarshipsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - starships?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type StarshipsEdge = { - __typename?: 'StarshipsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type Vehicle = Node & { - __typename?: 'Vehicle'; - /** The maximum number of kilograms that this vehicle can transport. */ - cargoCapacity?: Maybe; - /** - * The maximum length of time that this vehicle can provide consumables for its - * entire crew without having to resupply. - */ - consumables?: Maybe; - /** The cost of this vehicle new, in Galactic Credits. */ - costInCredits?: Maybe; - /** The ISO 8601 date format of the time that this resource was created. */ - created?: Maybe; - /** The number of personnel needed to run or pilot this vehicle. */ - crew?: Maybe; - /** The ISO 8601 date format of the time that this resource was edited. */ - edited?: Maybe; - filmConnection?: Maybe; - /** The ID of an object */ - id: Scalars['ID']['output']; - /** The length of this vehicle in meters. */ - length?: Maybe; - /** The manufacturers of this vehicle. */ - manufacturers?: Maybe>>; - /** The maximum speed of this vehicle in atmosphere. */ - maxAtmospheringSpeed?: Maybe; - /** - * The model or official name of this vehicle. Such as "All-Terrain Attack - * Transport". - */ - model?: Maybe; - /** - * The name of this vehicle. The common name, such as "Sand Crawler" or "Speeder - * bike". - */ - name?: Maybe; - /** The number of non-essential people this vehicle can transport. */ - passengers?: Maybe; - pilotConnection?: Maybe; - /** The class of this vehicle, such as "Wheeled" or "Repulsorcraft". */ - vehicleClass?: Maybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehicleFilmConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A single transport craft that does not have hyperdrive capability */ -export type VehiclePilotConnectionArgs = { - after?: InputMaybe; - before?: InputMaybe; - first?: InputMaybe; - last?: InputMaybe; -}; - -/** A connection to a list of items. */ -export type VehicleFilmsConnection = { - __typename?: 'VehicleFilmsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - films?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehicleFilmsEdge = { - __typename?: 'VehicleFilmsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclePilotsConnection = { - __typename?: 'VehiclePilotsConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - pilots?: Maybe>>; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; -}; - -/** An edge in a connection. */ -export type VehiclePilotsEdge = { - __typename?: 'VehiclePilotsEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - -/** A connection to a list of items. */ -export type VehiclesConnection = { - __typename?: 'VehiclesConnection'; - /** A list of edges. */ - edges?: Maybe>>; - /** Information to aid in pagination. */ - pageInfo: PageInfo; - /** - * A count of the total number of objects in this connection, ignoring pagination. - * This allows a client to fetch the first five objects by passing "5" as the - * argument to "first", then fetch the total count so it could display "5 of 83", - * for example. - */ - totalCount?: Maybe; - /** - * A list of all of the objects returned in the connection. This is a convenience - * field provided for quickly exploring the API; rather than querying for - * "{ edges { node } }" when no edge data is needed, this field can be be used - * instead. Note that when clients like Relay need to fetch the "cursor" field on - * the edge to enable efficient pagination, this shortcut cannot be used, and the - * full "{ edges { node } }" version should be used instead. - */ - vehicles?: Maybe>>; -}; - -/** An edge in a connection. */ -export type VehiclesEdge = { - __typename?: 'VehiclesEdge'; - /** A cursor for use in pagination */ - cursor: Scalars['String']['output']; - /** The item at the end of the edge */ - node?: Maybe; -}; - export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ first: number; }>; diff --git a/examples/yoga-tests/src/gql/graphql.ts b/examples/yoga-tests/src/gql/graphql.ts index ed3cd2a2646..ad230c423b5 100644 --- a/examples/yoga-tests/src/gql/graphql.ts +++ b/examples/yoga-tests/src/gql/graphql.ts @@ -1,40 +1,10 @@ /* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; -export type Maybe = T | null; -export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; +type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -type Exact = { [K in keyof T]: T[K] }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string }; - String: { input: string; output: string }; - Boolean: { input: boolean; output: boolean }; - Int: { input: number; output: number }; - Float: { input: number; output: number }; -}; - -export type Mutation = { - __typename?: 'Mutation'; - echo: Scalars['String']['output']; -}; - -export type MutationEchoArgs = { - message: Scalars['String']['input']; -}; - -export type Query = { - __typename?: 'Query'; - hello: Scalars['String']['output']; -}; - export type HelloQueryQueryVariables = Exact<{ [key: string]: never }>; export type HelloQueryQuery = { __typename?: 'Query'; hello: string }; diff --git a/packages/plugins/typescript/operations/src/index.ts b/packages/plugins/typescript/operations/src/index.ts index cf257624180..1a65049286b 100644 --- a/packages/plugins/typescript/operations/src/index.ts +++ b/packages/plugins/typescript/operations/src/index.ts @@ -81,9 +81,7 @@ export const plugin: PluginFunction< // It will leave the node as an object. // Here, we filter in nodes that have been turned into strings, i.e. they have been transformed // This way, we do not have to explicitly declare a method for every node type to convert them to null - const schemaTypesDefinitions = schemaTypes.definitions - .filter(def => typeof def === 'string') - .join('\n'); + const schemaTypesDefinitions = schemaTypes.definitions.filter(def => typeof def === 'string'); let content = [...schemaTypesDefinitions, ...operationsDefinitions].join('\n'); @@ -101,6 +99,7 @@ export const plugin: PluginFunction< ...visitor.getEnumsImports(), ...visitor.getGlobalDeclarations(visitor.config.noExport), visitor.getExactUtilityType(), + visitor.getIncrementalUtilityType(), ], content, }; diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 1d1335f26c3..d5c86b91ea5 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -15,6 +15,7 @@ import { type GraphQLOutputType, type GraphQLSchema, } from 'graphql'; +import { normalizeImportExtension } from '@graphql-codegen/plugin-helpers'; import { BaseDocumentsVisitor, convertSchemaEnumToDeclarationBlockString, @@ -248,8 +249,11 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< identifiers: [], }, typesImport: true, - // FIXME: rebase with master for the new extension - emitLegacyCommonJSImports: true, + emitLegacyCommonJSImports: this.config.emitLegacyCommonJSImports, + importExtension: normalizeImportExtension({ + emitLegacyCommonJSImports: this.config.emitLegacyCommonJSImports, + importExtension: this.config.importExtension, + }), }), ]; } @@ -299,8 +303,15 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< } public getEnumsImports(): string[] { + const usedEnumMap: ParsedEnumValuesMap = {}; + for (const [enumName, enumDetails] of Object.entries(this.config.enumValues)) { + if (this._usedNamedInputTypes[enumName]) { + usedEnumMap[enumName] = enumDetails; + } + } + return getEnumsImports({ - enumValues: this.config.enumValues, + enumValues: usedEnumMap, useTypeImports: this.config.useTypeImports, }); } @@ -312,4 +323,15 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< return 'type Exact = { [K in keyof T]: T[K] };'; } + + getIncrementalUtilityType(): string | null { + if (!this.config.generatesOperationTypes) { + return null; + } + + // Note: `export` here is important for 2 reasons + // 1. It is not always used in the rest of the file, so this is a safe way to avoid lint rules (in tsconfig or eslint) complaining it's not used in the current file. + // 2. In Client Preset, it is used by fragment-masking.ts, so it needs `export` + return "export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never };"; + } } diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts index d058165b47e..4ed7a7f371c 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts @@ -36,6 +36,7 @@ describe('TypeScript Operations Plugin - Enum', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type MeQueryVariables = Exact<{ [key: string]: never; }>; @@ -80,6 +81,7 @@ describe('TypeScript Operations Plugin - Enum', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export enum UserRole { Admin = 0, Customer = 1 @@ -132,6 +134,7 @@ describe('TypeScript Operations Plugin - Enum', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export const UserRole = { ABC: 'A_B_C', XYZ: 'X_Y_Z', @@ -190,6 +193,7 @@ describe('TypeScript Operations Plugin - Enum', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** Multiline comment test */ export const enum UserRole { Admin = 'ADMIN', @@ -241,6 +245,7 @@ describe('TypeScript Operations Plugin - Enum', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export enum UserRole { Admin = 'ADMIN', Customer = 'CUSTOMER' @@ -309,6 +314,7 @@ describe('TypeScript Operations Plugin - Enum', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserRole = | 0 | 'Foo' @@ -378,6 +384,7 @@ describe('TypeScript Operations Plugin - Enum', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export const UserRole = { ABC: 0, XYZ: 'Foo', @@ -445,6 +452,7 @@ describe('TypeScript Operations Plugin - Enum', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export enum UserRole { Admin = 0, Customer = 'test' @@ -507,6 +515,7 @@ describe('TypeScript Operations Plugin - Enum', () => { expect(result).toMatchInlineSnapshot(` "import { MyEnum as UserRole } from './my-file'; type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export { UserRole }; export type MeQueryVariables = Exact<{ @@ -521,6 +530,61 @@ describe('TypeScript Operations Plugin - Enum', () => { validateTs(result, undefined, undefined, undefined, undefined, true); }); + it('does not import or export `enumValues` (as file import) if enum is not used', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + scalar DateTime + `); + + const document = parse(/* GraphQL */ ` + query { + me { + id + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + enumValues: { + UserRole: './my-file#MyEnum', + }, + }, + { outputFile: '' } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + + + export type Unnamed_1_Query = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + it('handles `enumValues` with custom imported enum from namespace with different name', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { @@ -567,6 +631,7 @@ describe('TypeScript Operations Plugin - Enum', () => { "import { NS } from './my-file'; import UserRole = NS.ETest; type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export { UserRole }; export type MeQueryVariables = Exact<{ @@ -627,6 +692,7 @@ describe('TypeScript Operations Plugin - Enum', () => { "import { NS } from './my-file'; import UserRole = NS.UserRole; type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export { UserRole }; export type MeQueryVariables = Exact<{ @@ -691,6 +757,7 @@ describe('TypeScript Operations Plugin - Enum', () => { "import { UserRole } from './my-file'; import { UserStatus } from './my-file'; type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export { UserRole }; export { UserStatus }; @@ -758,6 +825,7 @@ describe('TypeScript Operations Plugin - Enum', () => { "import { UserRole } from './my-file'; import { UserStatus2X as UserStatus } from './my-file'; type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export { UserRole }; export { UserStatus }; @@ -810,6 +878,7 @@ describe('TypeScript Operations Plugin - Enum', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export enum UserRole { ABC = 'A_B_C', XYZ = 'X_Y_Z', @@ -863,6 +932,7 @@ describe('TypeScript Operations Plugin - Enum', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export enum UserRole { _ = '_', __ = '__', @@ -915,6 +985,7 @@ describe('TypeScript Operations Plugin - Enum', () => { ]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type IUserRole = | 'ADMIN' | 'CUSTOMER'; @@ -965,6 +1036,7 @@ describe('TypeScript Operations Plugin - Enum', () => { ]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserRole = | 'ADMIN' | 'CUSTOMER'; @@ -1015,6 +1087,7 @@ describe('TypeScript Operations Plugin - Enum', () => { ]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserRoleZ = | 'ADMIN' | 'CUSTOMER'; @@ -1065,6 +1138,7 @@ describe('TypeScript Operations Plugin - Enum', () => { ]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserRole = | 'ADMIN' | 'CUSTOMER'; @@ -1125,6 +1199,7 @@ describe('TypeScript Operations Plugin - Enum', () => { ]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type userrole = | 'ADMIN' | 'CUSTOMER'; @@ -1186,6 +1261,7 @@ describe('TypeScript Operations Plugin - Enum', () => { ]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export enum UserRole { admin = 'ADMIN', customer = 'CUSTOMER' @@ -1244,6 +1320,7 @@ describe('TypeScript Operations Plugin - Enum', () => { ]); expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type UserRole = | 'ADMIN' | 'CUSTOMER'; @@ -1307,6 +1384,7 @@ describe('TypeScript Operations Plugin - Enum', () => { expect(result).toMatchInlineSnapshot(` "import UserRole from './files'; type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export { UserRole }; export type IMeQueryVariables = Exact<{ @@ -1353,6 +1431,7 @@ describe('TypeScript Operations Plugin - Enum', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export enum UserRole { Axb = 'AXB', '1X2' = '_1X2', @@ -1403,6 +1482,7 @@ describe('TypeScript Operations Plugin - Enum `%future added value`', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserRole = | 'ADMIN' | 'CUSTOMER' diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts index af820bf713a..de0af9bda02 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts @@ -106,6 +106,7 @@ describe('TypeScript Operations Plugin - Import Types', () => { "import type * as TypeImport from './path-to-other-file.generated'; type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ id: string; }>; @@ -240,6 +241,7 @@ describe('TypeScript Operations Plugin - Import Types', () => { "import type * as TypeImport from '@my-company/package/types'; type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ id: string; }>; @@ -353,6 +355,7 @@ describe('TypeScript Operations Plugin - Import Types', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ id?: string | null; name?: string | null; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts index 00ea9a5ca42..e466993c245 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -94,6 +94,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** UserRole Description */ export type UserRole = /** UserRole ADMIN */ @@ -162,6 +163,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ id: string | number | boolean; }>; @@ -289,6 +291,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { expect(result).toMatchInlineSnapshot(` " + /** UserRole Description */ export type UserRole = /** UserRole ADMIN */ @@ -373,6 +376,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { expect(result).toMatchInlineSnapshot(` " + " `); diff --git a/packages/presets/client/src/index.ts b/packages/presets/client/src/index.ts index 41f06df349e..bc986b45e3b 100644 --- a/packages/presets/client/src/index.ts +++ b/packages/presets/client/src/index.ts @@ -7,7 +7,6 @@ import { type Types, } from '@graphql-codegen/plugin-helpers'; import * as typedDocumentNodePlugin from '@graphql-codegen/typed-document-node'; -import * as typescriptPlugin from '@graphql-codegen/typescript'; import * as typescriptOperationPlugin from '@graphql-codegen/typescript-operations'; import { ClientSideBaseVisitor, DocumentMode } from '@graphql-codegen/visitor-plugin-common'; import * as fragmentMaskingPlugin from './fragment-masking-plugin.js'; @@ -140,16 +139,13 @@ export const preset: Types.OutputPreset = { useTypeImports: options.config.useTypeImports, skipTypename: options.config.skipTypename, arrayInputCoercion: options.config.arrayInputCoercion, - enumsAsTypes: options.config.enumsAsTypes, - enumsAsConst: options.config.enumsAsConst, + enumType: options.config.enumType, enumValues: options.config.enumValues, futureProofEnums: options.config.futureProofEnums, nonOptionalTypename: options.config.nonOptionalTypename, avoidOptionals: options.config.avoidOptionals, documentMode: options.config.documentMode, skipTypeNameForRoot: options.config.skipTypeNameForRoot, - onlyOperationTypes: options.config.onlyOperationTypes, - onlyEnums: options.config.onlyEnums, customDirectives: options.config.customDirectives, immutableTypes: options.config.immutableTypes, }; @@ -202,7 +198,6 @@ export const preset: Types.OutputPreset = { const pluginMap = { ...options.pluginMap, [`add`]: addPlugin, - [`typescript`]: typescriptPlugin, [`typescript-operations`]: typescriptOperationPlugin, [`typed-document-node`]: { ...typedDocumentNodePlugin, @@ -236,11 +231,6 @@ export const preset: Types.OutputPreset = { const plugins: Array = [ { [`add`]: { content: `/* eslint-disable */` } }, - { - [`typescript`]: { - inputMaybeValue: 'T | null | undefined', - }, - }, { [`typescript-operations`]: {} }, { [`typed-document-node`]: { diff --git a/packages/presets/client/tests/client-preset.enum.spec.ts b/packages/presets/client/tests/client-preset.enum.spec.ts new file mode 100644 index 00000000000..89267a0f05d --- /dev/null +++ b/packages/presets/client/tests/client-preset.enum.spec.ts @@ -0,0 +1,208 @@ +import { executeCodegen } from '@graphql-codegen/cli'; +import { preset } from '../src/index.js'; + +describe('client-preset - Enum', () => { + it('does not generate enum if not used in operations', async () => { + const { result } = await executeCodegen({ + schema: [ + /* GraphQL */ ` + enum Color { + RED + BLUE + } + `, + ], + + generates: { + 'out1/': { + preset, + }, + }, + }); + + const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); + expect(graphqlFile.content).toMatchInlineSnapshot(` + "/* eslint-disable */ + type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never };" + `); + }); + + it('generates enum if used in operation Variables', async () => { + const { result } = await executeCodegen({ + schema: [ + /* GraphQL */ ` + type Query { + shape(shape: Shape): ShapeObj! + } + + enum Color { + RED + BLUE + } + + enum Shape { + ROUND + SQUARE + } + + type ShapeObj { + id: ID! + shape: Shape! + } + `, + ], + documents: /* GraphQL */ ` + query Shape($shape: Shape) { + shape(shape: $shape) { + id + } + } + `, + + generates: { + 'out1/': { + preset, + }, + }, + }); + + const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); + expect(graphqlFile.content).toMatchInlineSnapshot(` + "/* eslint-disable */ + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type Shape = + | 'ROUND' + | 'SQUARE'; + + export type ShapeQueryVariables = Exact<{ + shape?: Shape | null; + }>; + + + export type ShapeQuery = { __typename?: 'Query', shape: { __typename?: 'ShapeObj', id: string } }; + + + export const ShapeDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Shape"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"shape"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Shape"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"shape"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"shape"},"value":{"kind":"Variable","name":{"kind":"Name","value":"shape"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode;" + `); + }); + + it('generates enum if used in operation Result', async () => { + const { result } = await executeCodegen({ + schema: [ + /* GraphQL */ ` + type Query { + shape(shape: Shape): ShapeObj! + } + + enum Color { + RED + BLUE + } + + enum Shape { + ROUND + SQUARE + } + + type ShapeObj { + id: ID! + shape: Shape! + } + `, + ], + documents: /* GraphQL */ ` + query Shape { + shape { + id + shape + } + } + `, + + generates: { + 'out1/': { + preset, + }, + }, + }); + + const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); + expect(graphqlFile.content).toMatchInlineSnapshot(` + "/* eslint-disable */ + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type ShapeQueryVariables = Exact<{ [key: string]: never; }>; + + + export type ShapeQuery = { __typename?: 'Query', shape: { __typename?: 'ShapeObj', id: string, shape: Shape } }; + + + export const ShapeDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Shape"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"shape"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"shape"}}]}}]}}]} as unknown as DocumentNode;" + `); + }); + + it('supports config.enumType=const', async () => { + const { result } = await executeCodegen({ + schema: [ + /* GraphQL */ ` + type Query { + shape(shape: Shape): ShapeObj! + } + + enum Shape { + ROUND + SQUARE + } + + type ShapeObj { + id: ID! + shape: Shape! + } + `, + ], + documents: /* GraphQL */ ` + query Shape($shape: Shape) { + shape(shape: $shape) { + id + } + } + `, + + generates: { + 'out1/': { + preset, + config: { + enumType: 'const', + }, + }, + }, + }); + + const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); + expect(graphqlFile.content).toMatchInlineSnapshot(` + "/* eslint-disable */ + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export const Shape = { + Round: 'ROUND', + Square: 'SQUARE' + } as const; + + export type Shape = typeof Shape[keyof typeof Shape]; + export type ShapeQueryVariables = Exact<{ + shape?: Shape | null; + }>; + + + export type ShapeQuery = { __typename?: 'Query', shape: { __typename?: 'ShapeObj', id: string } }; + + + export const ShapeDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Shape"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"shape"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Shape"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"shape"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"shape"},"value":{"kind":"Variable","name":{"kind":"Name","value":"shape"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode;" + `); + }); +}); diff --git a/packages/presets/client/tests/client-preset.spec.ts b/packages/presets/client/tests/client-preset.spec.ts index 856848faa9a..eb703be8a06 100644 --- a/packages/presets/client/tests/client-preset.spec.ts +++ b/packages/presets/client/tests/client-preset.spec.ts @@ -363,29 +363,8 @@ export * from "./gql";`); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Query = { - __typename?: 'Query'; - a?: Maybe; - b?: Maybe; - c?: Maybe; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type AQueryVariables = Exact<{ [key: string]: never; }>; @@ -499,29 +478,8 @@ export * from "./gql";`); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Query = { - __typename: 'Query'; - a?: Maybe; - b?: Maybe; - c?: Maybe; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type AQueryVariables = Exact<{ [key: string]: never; }>; @@ -538,8 +496,6 @@ export * from "./gql";`); export const ADocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; export const BDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"B"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"b"}}]}}]} as unknown as DocumentNode;" `); - - expect(graphqlFile.content).toContain("__typename: 'Query';"); }); it('supports Apollo fragment masking', async () => { @@ -588,34 +544,8 @@ export * from "./gql";`); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Query = { - __typename?: 'Query'; - me?: Maybe; - }; - - export type User = { - __typename?: 'User'; - age: Scalars['Int']['output']; - id: Scalars['ID']['output']; - name: Scalars['String']['output']; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type MeQueryVariables = Exact<{ [key: string]: never; }>; @@ -705,27 +635,8 @@ export * from "./gql";`); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Query = { - __typename?: 'Query'; - a?: Maybe; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type AQueryVariables = Exact<{ [key: string]: never; }>; @@ -1562,29 +1473,8 @@ export * from "./gql.cjs";`); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Query = { - __typename?: 'Query'; - a?: Maybe; - b?: Maybe; - c?: Maybe; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type BbbQueryVariables = Exact<{ [key: string]: never; }>; @@ -1642,29 +1532,8 @@ export * from "./gql.cjs";`); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Query = { - __typename?: 'Query'; - a?: Maybe; - b?: Maybe; - c?: Maybe; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type AQueryVariables = Exact<{ [key: string]: never; }>; @@ -1725,29 +1594,8 @@ export * from "./gql.cjs";`); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Query = { - __typename?: 'Query'; - a?: Maybe; - b?: Maybe; - c?: Maybe; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type AQueryVariables = Exact<{ [key: string]: never; }>; @@ -1808,29 +1656,8 @@ export * from "./gql.cjs";`); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Query = { - __typename?: 'Query'; - a?: Maybe; - b?: Maybe; - c?: Maybe; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type AQueryVariables = Exact<{ [key: string]: never; }>; @@ -1891,29 +1718,8 @@ export * from "./gql.cjs";`); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Query = { - __typename?: 'Query'; - a?: Maybe; - b?: Maybe; - c?: Maybe; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type AaaQueryVariables = Exact<{ [key: string]: never; }>; @@ -1972,29 +1778,8 @@ export * from "./gql.cjs";`); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Query = { - __typename?: 'Query'; - a?: Maybe; - b?: Maybe; - c?: Maybe; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type AQueryVariables = Exact<{ [key: string]: never; }>; @@ -2059,29 +1844,8 @@ export * from "./gql.cjs";`); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Query = { - __typename?: 'Query'; - a?: Maybe; - b?: Maybe; - c?: Maybe; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type AQueryVariables = Exact<{ [key: string]: never; }>; @@ -2147,29 +1911,8 @@ export * from "./gql.cjs";`); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Query = { - __typename?: 'Query'; - a?: Maybe; - b?: Maybe; - c?: Maybe; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type AQueryVariables = Exact<{ [key: string]: never; }>; @@ -2235,29 +1978,8 @@ export * from "./gql.cjs";`); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Query = { - __typename?: 'Query'; - a?: Maybe; - b?: Maybe; - c?: Maybe; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type AQueryVariables = Exact<{ [key: string]: never; }>; @@ -2327,33 +2049,8 @@ export * from "./gql.cjs";`); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type A = { - __typename?: 'A'; - a: A; - b: Scalars['String']['output']; - }; - - export type Query = { - __typename?: 'Query'; - a: A; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type AbFragment = ( { __typename?: 'A', b: string } & { ' $fragmentRefs'?: { 'AcFragment': AcFragment;'AaFragment': AaFragment } } @@ -2406,34 +2103,8 @@ export * from "./gql.cjs";`); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Foo = { - __typename?: 'Foo'; - id?: Maybe; - value?: Maybe; - }; - - export type Query = { - __typename?: 'Query'; - foo?: Maybe; - foos?: Maybe>>; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type FooQueryVariables = Exact<{ [key: string]: never; }>; @@ -2497,34 +2168,8 @@ export * from "./gql.cjs";`); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Foo = { - __typename?: 'Foo'; - id?: Maybe; - value?: Maybe; - }; - - export type Query = { - __typename?: 'Query'; - foo?: Maybe; - foos?: Maybe>>; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type FooQueryVariables = Exact<{ [key: string]: never; }>; @@ -2588,34 +2233,8 @@ export * from "./gql.cjs";`); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Foo = { - __typename?: 'Foo'; - id?: Maybe; - value?: Maybe; - }; - - export type Query = { - __typename?: 'Query'; - foo?: Maybe; - foos?: Maybe>>; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type FooQueryVariables = Exact<{ [key: string]: never; }>; @@ -2752,34 +2371,8 @@ export * from "./gql.cjs";`); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Foo = { - __typename?: 'Foo'; - id?: Maybe; - value?: Maybe; - }; - - export type Query = { - __typename?: 'Query'; - foo?: Maybe; - foos?: Maybe>>; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type FooQueryVariables = Exact<{ [key: string]: never; }>; @@ -2914,33 +2507,8 @@ export * from "./gql.cjs";`); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Foo = { - __typename?: 'Foo'; - value?: Maybe; - }; - - export type Query = { - __typename?: 'Query'; - foo?: Maybe; - foos?: Maybe>>; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type FooQueryVariables = Exact<{ [key: string]: never; }>; @@ -3208,51 +2776,11 @@ export * from "./gql.cjs";`); }); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); - expect(graphqlFile.content).toBeSimilarStringTo(` - /* eslint-disable */ + expect(graphqlFile.content).toMatchInlineSnapshot(` + "/* eslint-disable */ import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Mutation = { - __typename?: 'Mutation'; - createRegion?: Maybe; - }; - - - export type MutationCreateRegionArgs = { - regionDescription: Scalars['String']['input']; - }; - - export type Query = { - __typename?: 'Query'; - regions?: Maybe>>; - }; - - export type Region = { - __typename?: 'Region'; - regionDescription: Scalars['String']['output']; - regionId: Scalars['Int']['output']; - }; - - export type Subscription = { - __typename?: 'Subscription'; - onRegionCreated: Region; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type OnRegionCreatedSubscriptionVariables = Exact<{ [key: string]: never; }>; @@ -3285,127 +2813,11 @@ export * from "./gql.cjs";`); regionDescription } } - \`) as unknown as TypedDocumentString; + \`) as unknown as TypedDocumentString;" `); }); }); - it('support enumsAsConst option', async () => { - const { result } = await executeCodegen({ - schema: [ - /* GraphQL */ ` - type Query { - thing: Thing - } - type Thing { - color: Color! - } - enum Color { - RED - BLUE - } - `, - ], - documents: path.join(__dirname, 'fixtures/enum.ts'), - generates: { - 'out1/': { - preset, - config: { - enumsAsConst: true, - }, - }, - }, - }); - const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); - expect(graphqlFile.content).toBeSimilarStringTo(` - /* eslint-disable */ - import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export const Color = { - Blue: 'BLUE', - Red: 'RED' - } as const; - - export type Color = typeof Color[keyof typeof Color]; - export type Query = { - __typename?: 'Query'; - thing?: Maybe; - }; - - export type Thing = { - __typename?: 'Thing'; - color: Color; - }; - - export type FavoriteColorQueryVariables = Exact<{ [key: string]: never; }>; - - - export type FavoriteColorQuery = { __typename?: 'Query', thing?: { __typename?: 'Thing', color: Color } | null }; - - - export const FavoriteColorDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"FavoriteColor"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"thing"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"color"}}]}}]}}]} as unknown as DocumentNode; - `); - }); - - it('support enumValues option', async () => { - const { result } = await executeCodegen({ - schema: [ - /* GraphQL */ ` - enum Color { - RED - BLUE - } - `, - ], - generates: { - 'out1/': { - preset, - config: { - enumValues: { - Color: './fixtures/with-enum-values#MyColor', - }, - }, - }, - }, - }); - - const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); - expect(graphqlFile.content).toBeSimilarStringTo(`/* eslint-disable */ - import { MyColor as Color } from './fixtures/with-enum-values'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export { Color };`); - }); - it('supports immutableTypes', async () => { const { result } = await executeCodegen({ schema: [ @@ -3444,39 +2856,8 @@ export * from "./gql.cjs";`); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; - export type Maybe = T | null; - export type InputMaybe = T | null | undefined; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type Exact = { [K in keyof T]: T[K] }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Query = { - readonly __typename?: 'Query'; - readonly user?: Maybe; - }; - - - export type QueryUserArgs = { - id: Scalars['ID']['input']; - }; - - export type User = { - readonly __typename?: 'User'; - readonly friends: ReadonlyArray; - readonly id: Scalars['ID']['output']; - readonly name: Scalars['String']['output']; - }; - + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type Test_UserQueryVariables = Exact<{ [key: string]: never; }>; From 12a81cae3e173f76f3f5b087c84bddc159f8b345 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Wed, 17 Dec 2025 23:23:40 +1100 Subject: [PATCH 12/69] [typescript-operations] No optional Result fields, unless deferred or conditional (#10548) * Fix types issues and put comments * Handle avoidOptionals * Update integration tests * Add FIXME to pass test for now * Add changeset --- .changeset/breezy-games-enter.md | 11 + dev-test/githunt/typed-document-nodes.ts | 40 +- dev-test/githunt/types.d.ts | 40 +- dev-test/githunt/types.enumsAsTypes.ts | 40 +- .../githunt/types.flatten.preResolveTypes.ts | 30 +- dev-test/githunt/types.immutableTypes.ts | 41 +- ...ypes.preResolveTypes.onlyOperationTypes.ts | 40 +- dev-test/githunt/types.preResolveTypes.ts | 40 +- dev-test/githunt/types.ts | 40 +- .../gql-tag-operations-masking/gql/graphql.ts | 7 +- .../gql-tag-operations-urql/gql/graphql.ts | 10 +- dev-test/gql-tag-operations/gql/graphql.ts | 10 +- .../gql-tag-operations/graphql/graphql.ts | 10 +- .../import-schema-types/_types.generated.ts | 2 +- dev-test/star-wars/types.excludeQueryAlpha.ts | 64 ++- dev-test/star-wars/types.excludeQueryBeta.ts | 64 ++- .../star-wars/types.globallyAvailable.d.ts | 66 ++- dev-test/star-wars/types.immutableTypes.ts | 72 +++- ...ypes.preResolveTypes.onlyOperationTypes.ts | 66 ++- dev-test/star-wars/types.preResolveTypes.ts | 66 ++- dev-test/star-wars/types.skipSchema.ts | 66 ++- dev-test/star-wars/types.ts | 66 ++- dev-test/test-null-value/result.d.ts | 4 + ...ypes.preResolveTypes.onlyOperationTypes.ts | 2 +- dev-test/test-schema/types.preResolveTypes.ts | 2 +- .../react/apollo-client/src/gql/graphql.ts | 14 +- .../react/http-executor/src/gql/graphql.ts | 14 +- .../tanstack-react-query/src/gql/graphql.ts | 14 +- examples/react/urql/src/gql/graphql.ts | 14 +- examples/typescript-esm/src/gql/graphql.ts | 20 +- .../src/gql/graphql.ts | 20 +- .../vite/vite-react-cts/src/gql/graphql.ts | 14 +- .../vite/vite-react-mts/src/gql/graphql.ts | 14 +- .../vite/vite-react-ts/src/gql/graphql.ts | 14 +- .../vue/apollo-composable/src/gql/graphql.ts | 14 +- examples/vue/urql/src/gql/graphql.ts | 14 +- examples/vue/villus/src/gql/graphql.ts | 14 +- .../src/selection-set-processor/base.ts | 10 +- .../pre-resolve-types.ts | 29 +- .../src/selection-set-to-object.ts | 46 +- .../src/ts-selection-set-processor.ts | 11 +- .../typescript/operations/src/visitor.ts | 24 +- .../__snapshots__/ts-documents.spec.ts.snap | 247 ++--------- .../tests/extract-all-types.spec.ts | 62 +-- .../tests/ts-documents.apolloUnmask.spec.ts | 10 +- .../tests/ts-documents.nullability.spec.ts | 34 +- .../operations/tests/ts-documents.spec.ts | 400 ++++++------------ .../ts-documents.standalone.enum.spec.ts | 52 +-- ...-documents.standalone.import-types.spec.ts | 6 +- .../tests/ts-documents.standalone.spec.ts | 6 +- .../tests/client-preset.nullability.spec.ts | 34 +- .../client/tests/client-preset.spec.ts | 114 ++--- 52 files changed, 1078 insertions(+), 1086 deletions(-) create mode 100644 .changeset/breezy-games-enter.md diff --git a/.changeset/breezy-games-enter.md b/.changeset/breezy-games-enter.md new file mode 100644 index 00000000000..9befb0d91ae --- /dev/null +++ b/.changeset/breezy-games-enter.md @@ -0,0 +1,11 @@ +--- +'@graphql-codegen/visitor-plugin-common': major +'@graphql-codegen/typescript-operations': major +'@graphql-codegen/client-preset': major +--- + +Fix nullable field optionality in operations + +Previously, a nullable Result field is generated as optional (marked by `?` TypeScript modifier) by default. This is not correct, because generally at runtime such field can only be `null`, and not `undefined` (both missing from the object OR `undefined`). The only exceptions are when fields are deferred (using `@defer` directive) or marked as conditional (using `@skip` or `@include`). + +Now, a nullable Result field cannot be optional unless the exceptions are met. This also limits `avoidOptionals` to only target Variables input, since some users may want to force explicit `null` when providing operation variables. diff --git a/dev-test/githunt/typed-document-nodes.ts b/dev-test/githunt/typed-document-nodes.ts index e2d4fa0cf7e..ccde4464efc 100644 --- a/dev-test/githunt/typed-document-nodes.ts +++ b/dev-test/githunt/typed-document-nodes.ts @@ -10,7 +10,7 @@ export type OnCommentAddedSubscriptionVariables = Exact<{ export type OnCommentAddedSubscription = { __typename?: 'Subscription'; - commentAdded?: { + commentAdded: { __typename?: 'Comment'; id: number; createdAt: number; @@ -27,8 +27,8 @@ export type CommentQueryVariables = Exact<{ export type CommentQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string; html_url: string } | null; - entry?: { + currentUser: { __typename?: 'User'; login: string; html_url: string } | null; + entry: { __typename?: 'Entry'; id: number; createdAt: number; @@ -43,8 +43,8 @@ export type CommentQuery = { } | null>; repository: { __typename?: 'Repository'; - description?: string | null; - open_issues_count?: number | null; + description: string | null; + open_issues_count: number | null; stargazers_count: number; full_name: string; html_url: string; @@ -64,7 +64,7 @@ export type CurrentUserForProfileQueryVariables = Exact<{ [key: string]: never } export type CurrentUserForProfileQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string; avatar_url: string } | null; + currentUser: { __typename?: 'User'; login: string; avatar_url: string } | null; }; export type FeedEntryFragment = { @@ -77,10 +77,10 @@ export type FeedEntryFragment = { __typename?: 'Repository'; full_name: string; html_url: string; - description?: string | null; + description: string | null; stargazers_count: number; - open_issues_count?: number | null; - owner?: { __typename?: 'User'; avatar_url: string } | null; + open_issues_count: number | null; + owner: { __typename?: 'User'; avatar_url: string } | null; }; vote: { __typename?: 'Vote'; vote_value: number }; postedBy: { __typename?: 'User'; html_url: string; login: string }; @@ -94,8 +94,8 @@ export type FeedQueryVariables = Exact<{ export type FeedQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string } | null; - feed?: Array<{ + currentUser: { __typename?: 'User'; login: string } | null; + feed: Array<{ __typename?: 'Entry'; id: number; commentCount: number; @@ -105,10 +105,10 @@ export type FeedQuery = { __typename?: 'Repository'; full_name: string; html_url: string; - description?: string | null; + description: string | null; stargazers_count: number; - open_issues_count?: number | null; - owner?: { __typename?: 'User'; avatar_url: string } | null; + open_issues_count: number | null; + owner: { __typename?: 'User'; avatar_url: string } | null; }; vote: { __typename?: 'Vote'; vote_value: number }; postedBy: { __typename?: 'User'; html_url: string; login: string }; @@ -121,7 +121,7 @@ export type SubmitRepositoryMutationVariables = Exact<{ export type SubmitRepositoryMutation = { __typename?: 'Mutation'; - submitRepository?: { __typename?: 'Entry'; createdAt: number } | null; + submitRepository: { __typename?: 'Entry'; createdAt: number } | null; }; export type RepoInfoFragment = { @@ -129,9 +129,9 @@ export type RepoInfoFragment = { createdAt: number; repository: { __typename?: 'Repository'; - description?: string | null; + description: string | null; stargazers_count: number; - open_issues_count?: number | null; + open_issues_count: number | null; }; postedBy: { __typename?: 'User'; html_url: string; login: string }; }; @@ -143,7 +143,7 @@ export type SubmitCommentMutationVariables = Exact<{ export type SubmitCommentMutation = { __typename?: 'Mutation'; - submitComment?: { + submitComment: { __typename?: 'Comment'; id: number; createdAt: number; @@ -165,12 +165,16 @@ export type VoteMutationVariables = Exact<{ export type VoteMutation = { __typename?: 'Mutation'; +<<<<<<< HEAD vote?: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number }; } | null; +======= + vote: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number } } | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) }; export const CommentsPageCommentFragmentDoc = { diff --git a/dev-test/githunt/types.d.ts b/dev-test/githunt/types.d.ts index ec2ba3f599b..486d055e08b 100644 --- a/dev-test/githunt/types.d.ts +++ b/dev-test/githunt/types.d.ts @@ -8,7 +8,7 @@ export type OnCommentAddedSubscriptionVariables = Exact<{ export type OnCommentAddedSubscription = { __typename?: 'Subscription'; - commentAdded?: { + commentAdded: { __typename?: 'Comment'; id: number; createdAt: number; @@ -25,8 +25,8 @@ export type CommentQueryVariables = Exact<{ export type CommentQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string; html_url: string } | null; - entry?: { + currentUser: { __typename?: 'User'; login: string; html_url: string } | null; + entry: { __typename?: 'Entry'; id: number; createdAt: number; @@ -41,8 +41,8 @@ export type CommentQuery = { } | null>; repository: { __typename?: 'Repository'; - description?: string | null; - open_issues_count?: number | null; + description: string | null; + open_issues_count: number | null; stargazers_count: number; full_name: string; html_url: string; @@ -62,7 +62,7 @@ export type CurrentUserForProfileQueryVariables = Exact<{ [key: string]: never } export type CurrentUserForProfileQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string; avatar_url: string } | null; + currentUser: { __typename?: 'User'; login: string; avatar_url: string } | null; }; export type FeedEntryFragment = { @@ -75,10 +75,10 @@ export type FeedEntryFragment = { __typename?: 'Repository'; full_name: string; html_url: string; - description?: string | null; + description: string | null; stargazers_count: number; - open_issues_count?: number | null; - owner?: { __typename?: 'User'; avatar_url: string } | null; + open_issues_count: number | null; + owner: { __typename?: 'User'; avatar_url: string } | null; }; vote: { __typename?: 'Vote'; vote_value: number }; postedBy: { __typename?: 'User'; html_url: string; login: string }; @@ -92,8 +92,8 @@ export type FeedQueryVariables = Exact<{ export type FeedQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string } | null; - feed?: Array<{ + currentUser: { __typename?: 'User'; login: string } | null; + feed: Array<{ __typename?: 'Entry'; id: number; commentCount: number; @@ -103,10 +103,10 @@ export type FeedQuery = { __typename?: 'Repository'; full_name: string; html_url: string; - description?: string | null; + description: string | null; stargazers_count: number; - open_issues_count?: number | null; - owner?: { __typename?: 'User'; avatar_url: string } | null; + open_issues_count: number | null; + owner: { __typename?: 'User'; avatar_url: string } | null; }; vote: { __typename?: 'Vote'; vote_value: number }; postedBy: { __typename?: 'User'; html_url: string; login: string }; @@ -119,7 +119,7 @@ export type SubmitRepositoryMutationVariables = Exact<{ export type SubmitRepositoryMutation = { __typename?: 'Mutation'; - submitRepository?: { __typename?: 'Entry'; createdAt: number } | null; + submitRepository: { __typename?: 'Entry'; createdAt: number } | null; }; export type RepoInfoFragment = { @@ -127,9 +127,9 @@ export type RepoInfoFragment = { createdAt: number; repository: { __typename?: 'Repository'; - description?: string | null; + description: string | null; stargazers_count: number; - open_issues_count?: number | null; + open_issues_count: number | null; }; postedBy: { __typename?: 'User'; html_url: string; login: string }; }; @@ -141,7 +141,7 @@ export type SubmitCommentMutationVariables = Exact<{ export type SubmitCommentMutation = { __typename?: 'Mutation'; - submitComment?: { + submitComment: { __typename?: 'Comment'; id: number; createdAt: number; @@ -163,10 +163,14 @@ export type VoteMutationVariables = Exact<{ export type VoteMutation = { __typename?: 'Mutation'; +<<<<<<< HEAD vote?: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number }; } | null; +======= + vote: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number } } | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) }; diff --git a/dev-test/githunt/types.enumsAsTypes.ts b/dev-test/githunt/types.enumsAsTypes.ts index ec2ba3f599b..486d055e08b 100644 --- a/dev-test/githunt/types.enumsAsTypes.ts +++ b/dev-test/githunt/types.enumsAsTypes.ts @@ -8,7 +8,7 @@ export type OnCommentAddedSubscriptionVariables = Exact<{ export type OnCommentAddedSubscription = { __typename?: 'Subscription'; - commentAdded?: { + commentAdded: { __typename?: 'Comment'; id: number; createdAt: number; @@ -25,8 +25,8 @@ export type CommentQueryVariables = Exact<{ export type CommentQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string; html_url: string } | null; - entry?: { + currentUser: { __typename?: 'User'; login: string; html_url: string } | null; + entry: { __typename?: 'Entry'; id: number; createdAt: number; @@ -41,8 +41,8 @@ export type CommentQuery = { } | null>; repository: { __typename?: 'Repository'; - description?: string | null; - open_issues_count?: number | null; + description: string | null; + open_issues_count: number | null; stargazers_count: number; full_name: string; html_url: string; @@ -62,7 +62,7 @@ export type CurrentUserForProfileQueryVariables = Exact<{ [key: string]: never } export type CurrentUserForProfileQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string; avatar_url: string } | null; + currentUser: { __typename?: 'User'; login: string; avatar_url: string } | null; }; export type FeedEntryFragment = { @@ -75,10 +75,10 @@ export type FeedEntryFragment = { __typename?: 'Repository'; full_name: string; html_url: string; - description?: string | null; + description: string | null; stargazers_count: number; - open_issues_count?: number | null; - owner?: { __typename?: 'User'; avatar_url: string } | null; + open_issues_count: number | null; + owner: { __typename?: 'User'; avatar_url: string } | null; }; vote: { __typename?: 'Vote'; vote_value: number }; postedBy: { __typename?: 'User'; html_url: string; login: string }; @@ -92,8 +92,8 @@ export type FeedQueryVariables = Exact<{ export type FeedQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string } | null; - feed?: Array<{ + currentUser: { __typename?: 'User'; login: string } | null; + feed: Array<{ __typename?: 'Entry'; id: number; commentCount: number; @@ -103,10 +103,10 @@ export type FeedQuery = { __typename?: 'Repository'; full_name: string; html_url: string; - description?: string | null; + description: string | null; stargazers_count: number; - open_issues_count?: number | null; - owner?: { __typename?: 'User'; avatar_url: string } | null; + open_issues_count: number | null; + owner: { __typename?: 'User'; avatar_url: string } | null; }; vote: { __typename?: 'Vote'; vote_value: number }; postedBy: { __typename?: 'User'; html_url: string; login: string }; @@ -119,7 +119,7 @@ export type SubmitRepositoryMutationVariables = Exact<{ export type SubmitRepositoryMutation = { __typename?: 'Mutation'; - submitRepository?: { __typename?: 'Entry'; createdAt: number } | null; + submitRepository: { __typename?: 'Entry'; createdAt: number } | null; }; export type RepoInfoFragment = { @@ -127,9 +127,9 @@ export type RepoInfoFragment = { createdAt: number; repository: { __typename?: 'Repository'; - description?: string | null; + description: string | null; stargazers_count: number; - open_issues_count?: number | null; + open_issues_count: number | null; }; postedBy: { __typename?: 'User'; html_url: string; login: string }; }; @@ -141,7 +141,7 @@ export type SubmitCommentMutationVariables = Exact<{ export type SubmitCommentMutation = { __typename?: 'Mutation'; - submitComment?: { + submitComment: { __typename?: 'Comment'; id: number; createdAt: number; @@ -163,10 +163,14 @@ export type VoteMutationVariables = Exact<{ export type VoteMutation = { __typename?: 'Mutation'; +<<<<<<< HEAD vote?: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number }; } | null; +======= + vote: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number } } | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) }; diff --git a/dev-test/githunt/types.flatten.preResolveTypes.ts b/dev-test/githunt/types.flatten.preResolveTypes.ts index feed22b3cf5..a6cb41ad34f 100644 --- a/dev-test/githunt/types.flatten.preResolveTypes.ts +++ b/dev-test/githunt/types.flatten.preResolveTypes.ts @@ -8,7 +8,7 @@ export type OnCommentAddedSubscriptionVariables = Exact<{ export type OnCommentAddedSubscription = { __typename?: 'Subscription'; - commentAdded?: { + commentAdded: { __typename?: 'Comment'; id: number; createdAt: number; @@ -25,8 +25,8 @@ export type CommentQueryVariables = Exact<{ export type CommentQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string; html_url: string } | null; - entry?: { + currentUser: { __typename?: 'User'; login: string; html_url: string } | null; + entry: { __typename?: 'Entry'; id: number; createdAt: number; @@ -43,8 +43,8 @@ export type CommentQuery = { __typename?: 'Repository'; full_name: string; html_url: string; - description?: string | null; - open_issues_count?: number | null; + description: string | null; + open_issues_count: number | null; stargazers_count: number; }; } | null; @@ -54,7 +54,7 @@ export type CurrentUserForProfileQueryVariables = Exact<{ [key: string]: never } export type CurrentUserForProfileQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string; avatar_url: string } | null; + currentUser: { __typename?: 'User'; login: string; avatar_url: string } | null; }; export type FeedQueryVariables = Exact<{ @@ -65,8 +65,8 @@ export type FeedQueryVariables = Exact<{ export type FeedQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string } | null; - feed?: Array<{ + currentUser: { __typename?: 'User'; login: string } | null; + feed: Array<{ __typename?: 'Entry'; id: number; commentCount: number; @@ -76,10 +76,10 @@ export type FeedQuery = { __typename?: 'Repository'; full_name: string; html_url: string; - description?: string | null; + description: string | null; stargazers_count: number; - open_issues_count?: number | null; - owner?: { __typename?: 'User'; avatar_url: string } | null; + open_issues_count: number | null; + owner: { __typename?: 'User'; avatar_url: string } | null; }; vote: { __typename?: 'Vote'; vote_value: number }; postedBy: { __typename?: 'User'; login: string; html_url: string }; @@ -92,7 +92,7 @@ export type SubmitRepositoryMutationVariables = Exact<{ export type SubmitRepositoryMutation = { __typename?: 'Mutation'; - submitRepository?: { __typename?: 'Entry'; createdAt: number } | null; + submitRepository: { __typename?: 'Entry'; createdAt: number } | null; }; export type SubmitCommentMutationVariables = Exact<{ @@ -102,7 +102,7 @@ export type SubmitCommentMutationVariables = Exact<{ export type SubmitCommentMutation = { __typename?: 'Mutation'; - submitComment?: { + submitComment: { __typename?: 'Comment'; id: number; createdAt: number; @@ -118,10 +118,14 @@ export type VoteMutationVariables = Exact<{ export type VoteMutation = { __typename?: 'Mutation'; +<<<<<<< HEAD vote?: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number }; } | null; +======= + vote: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number } } | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) }; diff --git a/dev-test/githunt/types.immutableTypes.ts b/dev-test/githunt/types.immutableTypes.ts index 78425b31023..1edd0d4e96c 100644 --- a/dev-test/githunt/types.immutableTypes.ts +++ b/dev-test/githunt/types.immutableTypes.ts @@ -8,7 +8,7 @@ export type OnCommentAddedSubscriptionVariables = Exact<{ export type OnCommentAddedSubscription = { readonly __typename?: 'Subscription'; - readonly commentAdded?: { + readonly commentAdded: { readonly __typename?: 'Comment'; readonly id: number; readonly createdAt: number; @@ -29,12 +29,17 @@ export type CommentQueryVariables = Exact<{ export type CommentQuery = { readonly __typename?: 'Query'; +<<<<<<< HEAD readonly currentUser?: { readonly __typename?: 'User'; readonly login: string; readonly html_url: string; } | null; readonly entry?: { +======= + readonly currentUser: { readonly __typename?: 'User'; readonly login: string; readonly html_url: string } | null; + readonly entry: { +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) readonly __typename?: 'Entry'; readonly id: number; readonly createdAt: number; @@ -57,8 +62,8 @@ export type CommentQuery = { } | null>; readonly repository: { readonly __typename?: 'Repository'; - readonly description?: string | null; - readonly open_issues_count?: number | null; + readonly description: string | null; + readonly open_issues_count: number | null; readonly stargazers_count: number; readonly full_name: string; readonly html_url: string; @@ -82,11 +87,15 @@ export type CurrentUserForProfileQueryVariables = Exact<{ [key: string]: never } export type CurrentUserForProfileQuery = { readonly __typename?: 'Query'; +<<<<<<< HEAD readonly currentUser?: { readonly __typename?: 'User'; readonly login: string; readonly avatar_url: string; } | null; +======= + readonly currentUser: { readonly __typename?: 'User'; readonly login: string; readonly avatar_url: string } | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) }; export type FeedEntryFragment = { @@ -99,10 +108,10 @@ export type FeedEntryFragment = { readonly __typename?: 'Repository'; readonly full_name: string; readonly html_url: string; - readonly description?: string | null; + readonly description: string | null; readonly stargazers_count: number; - readonly open_issues_count?: number | null; - readonly owner?: { readonly __typename?: 'User'; readonly avatar_url: string } | null; + readonly open_issues_count: number | null; + readonly owner: { readonly __typename?: 'User'; readonly avatar_url: string } | null; }; readonly vote: { readonly __typename?: 'Vote'; readonly vote_value: number }; readonly postedBy: { @@ -120,8 +129,8 @@ export type FeedQueryVariables = Exact<{ export type FeedQuery = { readonly __typename?: 'Query'; - readonly currentUser?: { readonly __typename?: 'User'; readonly login: string } | null; - readonly feed?: ReadonlyArray<{ + readonly currentUser: { readonly __typename?: 'User'; readonly login: string } | null; + readonly feed: ReadonlyArray<{ readonly __typename?: 'Entry'; readonly id: number; readonly commentCount: number; @@ -131,10 +140,10 @@ export type FeedQuery = { readonly __typename?: 'Repository'; readonly full_name: string; readonly html_url: string; - readonly description?: string | null; + readonly description: string | null; readonly stargazers_count: number; - readonly open_issues_count?: number | null; - readonly owner?: { readonly __typename?: 'User'; readonly avatar_url: string } | null; + readonly open_issues_count: number | null; + readonly owner: { readonly __typename?: 'User'; readonly avatar_url: string } | null; }; readonly vote: { readonly __typename?: 'Vote'; readonly vote_value: number }; readonly postedBy: { @@ -151,7 +160,7 @@ export type SubmitRepositoryMutationVariables = Exact<{ export type SubmitRepositoryMutation = { readonly __typename?: 'Mutation'; - readonly submitRepository?: { readonly __typename?: 'Entry'; readonly createdAt: number } | null; + readonly submitRepository: { readonly __typename?: 'Entry'; readonly createdAt: number } | null; }; export type RepoInfoFragment = { @@ -159,9 +168,9 @@ export type RepoInfoFragment = { readonly createdAt: number; readonly repository: { readonly __typename?: 'Repository'; - readonly description?: string | null; + readonly description: string | null; readonly stargazers_count: number; - readonly open_issues_count?: number | null; + readonly open_issues_count: number | null; }; readonly postedBy: { readonly __typename?: 'User'; @@ -177,7 +186,7 @@ export type SubmitCommentMutationVariables = Exact<{ export type SubmitCommentMutation = { readonly __typename?: 'Mutation'; - readonly submitComment?: { + readonly submitComment: { readonly __typename?: 'Comment'; readonly id: number; readonly createdAt: number; @@ -203,7 +212,7 @@ export type VoteMutationVariables = Exact<{ export type VoteMutation = { readonly __typename?: 'Mutation'; - readonly vote?: { + readonly vote: { readonly __typename?: 'Entry'; readonly score: number; readonly id: number; diff --git a/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts index ec2ba3f599b..486d055e08b 100644 --- a/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts @@ -8,7 +8,7 @@ export type OnCommentAddedSubscriptionVariables = Exact<{ export type OnCommentAddedSubscription = { __typename?: 'Subscription'; - commentAdded?: { + commentAdded: { __typename?: 'Comment'; id: number; createdAt: number; @@ -25,8 +25,8 @@ export type CommentQueryVariables = Exact<{ export type CommentQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string; html_url: string } | null; - entry?: { + currentUser: { __typename?: 'User'; login: string; html_url: string } | null; + entry: { __typename?: 'Entry'; id: number; createdAt: number; @@ -41,8 +41,8 @@ export type CommentQuery = { } | null>; repository: { __typename?: 'Repository'; - description?: string | null; - open_issues_count?: number | null; + description: string | null; + open_issues_count: number | null; stargazers_count: number; full_name: string; html_url: string; @@ -62,7 +62,7 @@ export type CurrentUserForProfileQueryVariables = Exact<{ [key: string]: never } export type CurrentUserForProfileQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string; avatar_url: string } | null; + currentUser: { __typename?: 'User'; login: string; avatar_url: string } | null; }; export type FeedEntryFragment = { @@ -75,10 +75,10 @@ export type FeedEntryFragment = { __typename?: 'Repository'; full_name: string; html_url: string; - description?: string | null; + description: string | null; stargazers_count: number; - open_issues_count?: number | null; - owner?: { __typename?: 'User'; avatar_url: string } | null; + open_issues_count: number | null; + owner: { __typename?: 'User'; avatar_url: string } | null; }; vote: { __typename?: 'Vote'; vote_value: number }; postedBy: { __typename?: 'User'; html_url: string; login: string }; @@ -92,8 +92,8 @@ export type FeedQueryVariables = Exact<{ export type FeedQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string } | null; - feed?: Array<{ + currentUser: { __typename?: 'User'; login: string } | null; + feed: Array<{ __typename?: 'Entry'; id: number; commentCount: number; @@ -103,10 +103,10 @@ export type FeedQuery = { __typename?: 'Repository'; full_name: string; html_url: string; - description?: string | null; + description: string | null; stargazers_count: number; - open_issues_count?: number | null; - owner?: { __typename?: 'User'; avatar_url: string } | null; + open_issues_count: number | null; + owner: { __typename?: 'User'; avatar_url: string } | null; }; vote: { __typename?: 'Vote'; vote_value: number }; postedBy: { __typename?: 'User'; html_url: string; login: string }; @@ -119,7 +119,7 @@ export type SubmitRepositoryMutationVariables = Exact<{ export type SubmitRepositoryMutation = { __typename?: 'Mutation'; - submitRepository?: { __typename?: 'Entry'; createdAt: number } | null; + submitRepository: { __typename?: 'Entry'; createdAt: number } | null; }; export type RepoInfoFragment = { @@ -127,9 +127,9 @@ export type RepoInfoFragment = { createdAt: number; repository: { __typename?: 'Repository'; - description?: string | null; + description: string | null; stargazers_count: number; - open_issues_count?: number | null; + open_issues_count: number | null; }; postedBy: { __typename?: 'User'; html_url: string; login: string }; }; @@ -141,7 +141,7 @@ export type SubmitCommentMutationVariables = Exact<{ export type SubmitCommentMutation = { __typename?: 'Mutation'; - submitComment?: { + submitComment: { __typename?: 'Comment'; id: number; createdAt: number; @@ -163,10 +163,14 @@ export type VoteMutationVariables = Exact<{ export type VoteMutation = { __typename?: 'Mutation'; +<<<<<<< HEAD vote?: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number }; } | null; +======= + vote: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number } } | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) }; diff --git a/dev-test/githunt/types.preResolveTypes.ts b/dev-test/githunt/types.preResolveTypes.ts index ec2ba3f599b..486d055e08b 100644 --- a/dev-test/githunt/types.preResolveTypes.ts +++ b/dev-test/githunt/types.preResolveTypes.ts @@ -8,7 +8,7 @@ export type OnCommentAddedSubscriptionVariables = Exact<{ export type OnCommentAddedSubscription = { __typename?: 'Subscription'; - commentAdded?: { + commentAdded: { __typename?: 'Comment'; id: number; createdAt: number; @@ -25,8 +25,8 @@ export type CommentQueryVariables = Exact<{ export type CommentQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string; html_url: string } | null; - entry?: { + currentUser: { __typename?: 'User'; login: string; html_url: string } | null; + entry: { __typename?: 'Entry'; id: number; createdAt: number; @@ -41,8 +41,8 @@ export type CommentQuery = { } | null>; repository: { __typename?: 'Repository'; - description?: string | null; - open_issues_count?: number | null; + description: string | null; + open_issues_count: number | null; stargazers_count: number; full_name: string; html_url: string; @@ -62,7 +62,7 @@ export type CurrentUserForProfileQueryVariables = Exact<{ [key: string]: never } export type CurrentUserForProfileQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string; avatar_url: string } | null; + currentUser: { __typename?: 'User'; login: string; avatar_url: string } | null; }; export type FeedEntryFragment = { @@ -75,10 +75,10 @@ export type FeedEntryFragment = { __typename?: 'Repository'; full_name: string; html_url: string; - description?: string | null; + description: string | null; stargazers_count: number; - open_issues_count?: number | null; - owner?: { __typename?: 'User'; avatar_url: string } | null; + open_issues_count: number | null; + owner: { __typename?: 'User'; avatar_url: string } | null; }; vote: { __typename?: 'Vote'; vote_value: number }; postedBy: { __typename?: 'User'; html_url: string; login: string }; @@ -92,8 +92,8 @@ export type FeedQueryVariables = Exact<{ export type FeedQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string } | null; - feed?: Array<{ + currentUser: { __typename?: 'User'; login: string } | null; + feed: Array<{ __typename?: 'Entry'; id: number; commentCount: number; @@ -103,10 +103,10 @@ export type FeedQuery = { __typename?: 'Repository'; full_name: string; html_url: string; - description?: string | null; + description: string | null; stargazers_count: number; - open_issues_count?: number | null; - owner?: { __typename?: 'User'; avatar_url: string } | null; + open_issues_count: number | null; + owner: { __typename?: 'User'; avatar_url: string } | null; }; vote: { __typename?: 'Vote'; vote_value: number }; postedBy: { __typename?: 'User'; html_url: string; login: string }; @@ -119,7 +119,7 @@ export type SubmitRepositoryMutationVariables = Exact<{ export type SubmitRepositoryMutation = { __typename?: 'Mutation'; - submitRepository?: { __typename?: 'Entry'; createdAt: number } | null; + submitRepository: { __typename?: 'Entry'; createdAt: number } | null; }; export type RepoInfoFragment = { @@ -127,9 +127,9 @@ export type RepoInfoFragment = { createdAt: number; repository: { __typename?: 'Repository'; - description?: string | null; + description: string | null; stargazers_count: number; - open_issues_count?: number | null; + open_issues_count: number | null; }; postedBy: { __typename?: 'User'; html_url: string; login: string }; }; @@ -141,7 +141,7 @@ export type SubmitCommentMutationVariables = Exact<{ export type SubmitCommentMutation = { __typename?: 'Mutation'; - submitComment?: { + submitComment: { __typename?: 'Comment'; id: number; createdAt: number; @@ -163,10 +163,14 @@ export type VoteMutationVariables = Exact<{ export type VoteMutation = { __typename?: 'Mutation'; +<<<<<<< HEAD vote?: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number }; } | null; +======= + vote: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number } } | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) }; diff --git a/dev-test/githunt/types.ts b/dev-test/githunt/types.ts index ec2ba3f599b..486d055e08b 100644 --- a/dev-test/githunt/types.ts +++ b/dev-test/githunt/types.ts @@ -8,7 +8,7 @@ export type OnCommentAddedSubscriptionVariables = Exact<{ export type OnCommentAddedSubscription = { __typename?: 'Subscription'; - commentAdded?: { + commentAdded: { __typename?: 'Comment'; id: number; createdAt: number; @@ -25,8 +25,8 @@ export type CommentQueryVariables = Exact<{ export type CommentQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string; html_url: string } | null; - entry?: { + currentUser: { __typename?: 'User'; login: string; html_url: string } | null; + entry: { __typename?: 'Entry'; id: number; createdAt: number; @@ -41,8 +41,8 @@ export type CommentQuery = { } | null>; repository: { __typename?: 'Repository'; - description?: string | null; - open_issues_count?: number | null; + description: string | null; + open_issues_count: number | null; stargazers_count: number; full_name: string; html_url: string; @@ -62,7 +62,7 @@ export type CurrentUserForProfileQueryVariables = Exact<{ [key: string]: never } export type CurrentUserForProfileQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string; avatar_url: string } | null; + currentUser: { __typename?: 'User'; login: string; avatar_url: string } | null; }; export type FeedEntryFragment = { @@ -75,10 +75,10 @@ export type FeedEntryFragment = { __typename?: 'Repository'; full_name: string; html_url: string; - description?: string | null; + description: string | null; stargazers_count: number; - open_issues_count?: number | null; - owner?: { __typename?: 'User'; avatar_url: string } | null; + open_issues_count: number | null; + owner: { __typename?: 'User'; avatar_url: string } | null; }; vote: { __typename?: 'Vote'; vote_value: number }; postedBy: { __typename?: 'User'; html_url: string; login: string }; @@ -92,8 +92,8 @@ export type FeedQueryVariables = Exact<{ export type FeedQuery = { __typename?: 'Query'; - currentUser?: { __typename?: 'User'; login: string } | null; - feed?: Array<{ + currentUser: { __typename?: 'User'; login: string } | null; + feed: Array<{ __typename?: 'Entry'; id: number; commentCount: number; @@ -103,10 +103,10 @@ export type FeedQuery = { __typename?: 'Repository'; full_name: string; html_url: string; - description?: string | null; + description: string | null; stargazers_count: number; - open_issues_count?: number | null; - owner?: { __typename?: 'User'; avatar_url: string } | null; + open_issues_count: number | null; + owner: { __typename?: 'User'; avatar_url: string } | null; }; vote: { __typename?: 'Vote'; vote_value: number }; postedBy: { __typename?: 'User'; html_url: string; login: string }; @@ -119,7 +119,7 @@ export type SubmitRepositoryMutationVariables = Exact<{ export type SubmitRepositoryMutation = { __typename?: 'Mutation'; - submitRepository?: { __typename?: 'Entry'; createdAt: number } | null; + submitRepository: { __typename?: 'Entry'; createdAt: number } | null; }; export type RepoInfoFragment = { @@ -127,9 +127,9 @@ export type RepoInfoFragment = { createdAt: number; repository: { __typename?: 'Repository'; - description?: string | null; + description: string | null; stargazers_count: number; - open_issues_count?: number | null; + open_issues_count: number | null; }; postedBy: { __typename?: 'User'; html_url: string; login: string }; }; @@ -141,7 +141,7 @@ export type SubmitCommentMutationVariables = Exact<{ export type SubmitCommentMutation = { __typename?: 'Mutation'; - submitComment?: { + submitComment: { __typename?: 'Comment'; id: number; createdAt: number; @@ -163,10 +163,14 @@ export type VoteMutationVariables = Exact<{ export type VoteMutation = { __typename?: 'Mutation'; +<<<<<<< HEAD vote?: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number }; } | null; +======= + vote: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number } } | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) }; diff --git a/dev-test/gql-tag-operations-masking/gql/graphql.ts b/dev-test/gql-tag-operations-masking/gql/graphql.ts index 8f6d59a3d7c..6c49fafb063 100644 --- a/dev-test/gql-tag-operations-masking/gql/graphql.ts +++ b/dev-test/gql-tag-operations-masking/gql/graphql.ts @@ -12,15 +12,20 @@ export type TweetFragmentFragment = ({ __typename?: 'Tweet'; id: string; body: s export type TweetAuthorFragmentFragment = { __typename?: 'Tweet'; id: string; - author: { __typename?: 'User'; id: string; username?: string | null }; + author: { __typename?: 'User'; id: string; username: string | null }; } & { ' $fragmentName'?: 'TweetAuthorFragmentFragment' }; export type TweetsFragmentFragment = { __typename?: 'Query'; +<<<<<<< HEAD Tweets?: Array< { __typename?: 'Tweet'; id: string } & { ' $fragmentRefs'?: { TweetFragmentFragment: TweetFragmentFragment }; } +======= + Tweets: Array< + { __typename?: 'Tweet'; id: string } & { ' $fragmentRefs'?: { TweetFragmentFragment: TweetFragmentFragment } } +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) > | null; } & { ' $fragmentName'?: 'TweetsFragmentFragment' }; diff --git a/dev-test/gql-tag-operations-urql/gql/graphql.ts b/dev-test/gql-tag-operations-urql/gql/graphql.ts index 13ffc0cd740..8e21640fff8 100644 --- a/dev-test/gql-tag-operations-urql/gql/graphql.ts +++ b/dev-test/gql-tag-operations-urql/gql/graphql.ts @@ -7,12 +7,16 @@ export type Incremental = | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type FooQueryVariables = Exact<{ [key: string]: never }>; +<<<<<<< HEAD export type FooQuery = { __typename?: 'Query'; Tweets?: Array<{ __typename?: 'Tweet'; id: string } | null> | null; }; +======= +export type FooQuery = { __typename?: 'Query'; Tweets: Array<{ __typename?: 'Tweet'; id: string } | null> | null }; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) -export type LelFragment = { __typename?: 'Tweet'; id: string; body?: string | null } & { +export type LelFragment = { __typename?: 'Tweet'; id: string; body: string | null } & { ' $fragmentName'?: 'LelFragment'; }; @@ -20,9 +24,13 @@ export type BarQueryVariables = Exact<{ [key: string]: never }>; export type BarQuery = { __typename?: 'Query'; +<<<<<<< HEAD Tweets?: Array< ({ __typename?: 'Tweet' } & { ' $fragmentRefs'?: { LelFragment: LelFragment } }) | null > | null; +======= + Tweets: Array<({ __typename?: 'Tweet' } & { ' $fragmentRefs'?: { LelFragment: LelFragment } }) | null> | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) }; export const LelFragmentDoc = { diff --git a/dev-test/gql-tag-operations/gql/graphql.ts b/dev-test/gql-tag-operations/gql/graphql.ts index 13ffc0cd740..8e21640fff8 100644 --- a/dev-test/gql-tag-operations/gql/graphql.ts +++ b/dev-test/gql-tag-operations/gql/graphql.ts @@ -7,12 +7,16 @@ export type Incremental = | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type FooQueryVariables = Exact<{ [key: string]: never }>; +<<<<<<< HEAD export type FooQuery = { __typename?: 'Query'; Tweets?: Array<{ __typename?: 'Tweet'; id: string } | null> | null; }; +======= +export type FooQuery = { __typename?: 'Query'; Tweets: Array<{ __typename?: 'Tweet'; id: string } | null> | null }; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) -export type LelFragment = { __typename?: 'Tweet'; id: string; body?: string | null } & { +export type LelFragment = { __typename?: 'Tweet'; id: string; body: string | null } & { ' $fragmentName'?: 'LelFragment'; }; @@ -20,9 +24,13 @@ export type BarQueryVariables = Exact<{ [key: string]: never }>; export type BarQuery = { __typename?: 'Query'; +<<<<<<< HEAD Tweets?: Array< ({ __typename?: 'Tweet' } & { ' $fragmentRefs'?: { LelFragment: LelFragment } }) | null > | null; +======= + Tweets: Array<({ __typename?: 'Tweet' } & { ' $fragmentRefs'?: { LelFragment: LelFragment } }) | null> | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) }; export const LelFragmentDoc = { diff --git a/dev-test/gql-tag-operations/graphql/graphql.ts b/dev-test/gql-tag-operations/graphql/graphql.ts index 13ffc0cd740..8e21640fff8 100644 --- a/dev-test/gql-tag-operations/graphql/graphql.ts +++ b/dev-test/gql-tag-operations/graphql/graphql.ts @@ -7,12 +7,16 @@ export type Incremental = | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type FooQueryVariables = Exact<{ [key: string]: never }>; +<<<<<<< HEAD export type FooQuery = { __typename?: 'Query'; Tweets?: Array<{ __typename?: 'Tweet'; id: string } | null> | null; }; +======= +export type FooQuery = { __typename?: 'Query'; Tweets: Array<{ __typename?: 'Tweet'; id: string } | null> | null }; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) -export type LelFragment = { __typename?: 'Tweet'; id: string; body?: string | null } & { +export type LelFragment = { __typename?: 'Tweet'; id: string; body: string | null } & { ' $fragmentName'?: 'LelFragment'; }; @@ -20,9 +24,13 @@ export type BarQueryVariables = Exact<{ [key: string]: never }>; export type BarQuery = { __typename?: 'Query'; +<<<<<<< HEAD Tweets?: Array< ({ __typename?: 'Tweet' } & { ' $fragmentRefs'?: { LelFragment: LelFragment } }) | null > | null; +======= + Tweets: Array<({ __typename?: 'Tweet' } & { ' $fragmentRefs'?: { LelFragment: LelFragment } }) | null> | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) }; export const LelFragmentDoc = { diff --git a/dev-test/standalone-operations/import-schema-types/_types.generated.ts b/dev-test/standalone-operations/import-schema-types/_types.generated.ts index 9c369786a25..7727a8b4ac1 100644 --- a/dev-test/standalone-operations/import-schema-types/_types.generated.ts +++ b/dev-test/standalone-operations/import-schema-types/_types.generated.ts @@ -10,5 +10,5 @@ export type WithVariablesQueryVariables = Exact<{ export type WithVariablesQuery = { __typename?: 'Query'; - user?: { __typename?: 'User'; id: string; name: string } | null; + user: { __typename?: 'User'; id: string; name: string } | null; }; diff --git a/dev-test/star-wars/types.excludeQueryAlpha.ts b/dev-test/star-wars/types.excludeQueryAlpha.ts index 3ebf4d2a82e..732571cc311 100644 --- a/dev-test/star-wars/types.excludeQueryAlpha.ts +++ b/dev-test/star-wars/types.excludeQueryAlpha.ts @@ -9,7 +9,7 @@ export type CreateReviewForEpisodeMutationVariables = Exact<{ export type CreateReviewForEpisodeMutation = { __typename?: 'Mutation'; - createReview?: { __typename?: 'Review'; stars: number; commentary?: string | null } | null; + createReview: { __typename?: 'Review'; stars: number; commentary: string | null } | null; }; export type ExcludeQueryBetaQueryVariables = Exact<{ @@ -18,7 +18,7 @@ export type ExcludeQueryBetaQueryVariables = Exact<{ export type ExcludeQueryBetaQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; export type HeroAndFriendsNamesQueryVariables = Exact<{ @@ -27,20 +27,28 @@ export type HeroAndFriendsNamesQueryVariables = Exact<{ export type HeroAndFriendsNamesQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; +<<<<<<< HEAD friends?: Array< { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null > | null; +======= + friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | { __typename?: 'Human'; name: string; +<<<<<<< HEAD friends?: Array< { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null > | null; +======= + friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | null; }; @@ -49,7 +57,7 @@ export type HeroAppearsInQueryVariables = Exact<{ [key: string]: never }>; export type HeroAppearsInQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; appearsIn: Array } | { __typename?: 'Human'; name: string; appearsIn: Array } | null; @@ -61,19 +69,23 @@ export type HeroDetailsQueryVariables = Exact<{ export type HeroDetailsQuery = { __typename?: 'Query'; - hero?: - | { __typename?: 'Droid'; primaryFunction?: string | null; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } + hero: + | { __typename?: 'Droid'; primaryFunction: string | null; name: string } + | { __typename?: 'Human'; height: number | null; name: string } | null; }; +<<<<<<< HEAD type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction?: string | null; name: string; }; +======= +type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction: string | null; name: string }; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) -type HeroDetails_Human_Fragment = { __typename?: 'Human'; height?: number | null; name: string }; +type HeroDetails_Human_Fragment = { __typename?: 'Human'; height: number | null; name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; @@ -83,9 +95,9 @@ export type HeroDetailsWithFragmentQueryVariables = Exact<{ export type HeroDetailsWithFragmentQuery = { __typename?: 'Query'; - hero?: - | { __typename?: 'Droid'; primaryFunction?: string | null; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } + hero: + | { __typename?: 'Droid'; primaryFunction: string | null; name: string } + | { __typename?: 'Human'; height: number | null; name: string } | null; }; @@ -95,7 +107,7 @@ export type HeroNameQueryVariables = Exact<{ export type HeroNameQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ @@ -105,7 +117,7 @@ export type HeroNameConditionalInclusionQueryVariables = Exact<{ export type HeroNameConditionalInclusionQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ @@ -115,7 +127,7 @@ export type HeroNameConditionalExclusionQueryVariables = Exact<{ export type HeroNameConditionalExclusionQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ @@ -124,23 +136,33 @@ export type HeroParentTypeDependentFieldQueryVariables = Exact<{ export type HeroParentTypeDependentFieldQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; +<<<<<<< HEAD friends?: Array< | { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height?: number | null; name: string } | null +======= + friends: Array< + { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) > | null; } | { __typename?: 'Human'; name: string; +<<<<<<< HEAD friends?: Array< | { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height?: number | null; name: string } | null +======= + friends: Array< + { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) > | null; } | null; @@ -152,25 +174,29 @@ export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ export type HeroTypeDependentAliasedFieldQuery = { __typename?: 'Query'; +<<<<<<< HEAD hero?: | { __typename?: 'Droid'; property?: string | null } | { __typename?: 'Human'; property?: string | null } | null; +======= + hero: { __typename?: 'Droid'; property: string | null } | { __typename?: 'Human'; property: string | null } | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) }; -export type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass?: number | null }; +export type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass: number | null }; export type HumanWithNullHeightQueryVariables = Exact<{ [key: string]: never }>; export type HumanWithNullHeightQuery = { __typename?: 'Query'; - human?: { __typename?: 'Human'; name: string; mass?: number | null } | null; + human: { __typename?: 'Human'; name: string; mass: number | null } | null; }; export type TwoHeroesQueryVariables = Exact<{ [key: string]: never }>; export type TwoHeroesQuery = { __typename?: 'Query'; - r2?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; - luke?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + r2: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + luke: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; diff --git a/dev-test/star-wars/types.excludeQueryBeta.ts b/dev-test/star-wars/types.excludeQueryBeta.ts index 6b0a5109dc2..fd906fe2094 100644 --- a/dev-test/star-wars/types.excludeQueryBeta.ts +++ b/dev-test/star-wars/types.excludeQueryBeta.ts @@ -9,7 +9,7 @@ export type CreateReviewForEpisodeMutationVariables = Exact<{ export type CreateReviewForEpisodeMutation = { __typename?: 'Mutation'; - createReview?: { __typename?: 'Review'; stars: number; commentary?: string | null } | null; + createReview: { __typename?: 'Review'; stars: number; commentary: string | null } | null; }; export type ExcludeQueryAlphaQueryVariables = Exact<{ @@ -18,7 +18,7 @@ export type ExcludeQueryAlphaQueryVariables = Exact<{ export type ExcludeQueryAlphaQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; export type HeroAndFriendsNamesQueryVariables = Exact<{ @@ -27,20 +27,28 @@ export type HeroAndFriendsNamesQueryVariables = Exact<{ export type HeroAndFriendsNamesQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; +<<<<<<< HEAD friends?: Array< { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null > | null; +======= + friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | { __typename?: 'Human'; name: string; +<<<<<<< HEAD friends?: Array< { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null > | null; +======= + friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | null; }; @@ -49,7 +57,7 @@ export type HeroAppearsInQueryVariables = Exact<{ [key: string]: never }>; export type HeroAppearsInQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; appearsIn: Array } | { __typename?: 'Human'; name: string; appearsIn: Array } | null; @@ -61,19 +69,23 @@ export type HeroDetailsQueryVariables = Exact<{ export type HeroDetailsQuery = { __typename?: 'Query'; - hero?: - | { __typename?: 'Droid'; primaryFunction?: string | null; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } + hero: + | { __typename?: 'Droid'; primaryFunction: string | null; name: string } + | { __typename?: 'Human'; height: number | null; name: string } | null; }; +<<<<<<< HEAD type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction?: string | null; name: string; }; +======= +type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction: string | null; name: string }; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) -type HeroDetails_Human_Fragment = { __typename?: 'Human'; height?: number | null; name: string }; +type HeroDetails_Human_Fragment = { __typename?: 'Human'; height: number | null; name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; @@ -83,9 +95,9 @@ export type HeroDetailsWithFragmentQueryVariables = Exact<{ export type HeroDetailsWithFragmentQuery = { __typename?: 'Query'; - hero?: - | { __typename?: 'Droid'; primaryFunction?: string | null; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } + hero: + | { __typename?: 'Droid'; primaryFunction: string | null; name: string } + | { __typename?: 'Human'; height: number | null; name: string } | null; }; @@ -95,7 +107,7 @@ export type HeroNameQueryVariables = Exact<{ export type HeroNameQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ @@ -105,7 +117,7 @@ export type HeroNameConditionalInclusionQueryVariables = Exact<{ export type HeroNameConditionalInclusionQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ @@ -115,7 +127,7 @@ export type HeroNameConditionalExclusionQueryVariables = Exact<{ export type HeroNameConditionalExclusionQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ @@ -124,23 +136,33 @@ export type HeroParentTypeDependentFieldQueryVariables = Exact<{ export type HeroParentTypeDependentFieldQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; +<<<<<<< HEAD friends?: Array< | { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height?: number | null; name: string } | null +======= + friends: Array< + { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) > | null; } | { __typename?: 'Human'; name: string; +<<<<<<< HEAD friends?: Array< | { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height?: number | null; name: string } | null +======= + friends: Array< + { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) > | null; } | null; @@ -152,25 +174,29 @@ export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ export type HeroTypeDependentAliasedFieldQuery = { __typename?: 'Query'; +<<<<<<< HEAD hero?: | { __typename?: 'Droid'; property?: string | null } | { __typename?: 'Human'; property?: string | null } | null; +======= + hero: { __typename?: 'Droid'; property: string | null } | { __typename?: 'Human'; property: string | null } | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) }; -export type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass?: number | null }; +export type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass: number | null }; export type HumanWithNullHeightQueryVariables = Exact<{ [key: string]: never }>; export type HumanWithNullHeightQuery = { __typename?: 'Query'; - human?: { __typename?: 'Human'; name: string; mass?: number | null } | null; + human: { __typename?: 'Human'; name: string; mass: number | null } | null; }; export type TwoHeroesQueryVariables = Exact<{ [key: string]: never }>; export type TwoHeroesQuery = { __typename?: 'Query'; - r2?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; - luke?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + r2: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + luke: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; diff --git a/dev-test/star-wars/types.globallyAvailable.d.ts b/dev-test/star-wars/types.globallyAvailable.d.ts index 4d60ead1878..05ffe126c60 100644 --- a/dev-test/star-wars/types.globallyAvailable.d.ts +++ b/dev-test/star-wars/types.globallyAvailable.d.ts @@ -9,7 +9,7 @@ type CreateReviewForEpisodeMutationVariables = Exact<{ type CreateReviewForEpisodeMutation = { __typename?: 'Mutation'; - createReview?: { __typename?: 'Review'; stars: number; commentary?: string | null } | null; + createReview: { __typename?: 'Review'; stars: number; commentary: string | null } | null; }; type ExcludeQueryAlphaQueryVariables = Exact<{ @@ -18,7 +18,7 @@ type ExcludeQueryAlphaQueryVariables = Exact<{ type ExcludeQueryAlphaQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; type ExcludeQueryBetaQueryVariables = Exact<{ @@ -27,7 +27,7 @@ type ExcludeQueryBetaQueryVariables = Exact<{ type ExcludeQueryBetaQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; type HeroAndFriendsNamesQueryVariables = Exact<{ @@ -36,20 +36,28 @@ type HeroAndFriendsNamesQueryVariables = Exact<{ type HeroAndFriendsNamesQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; +<<<<<<< HEAD friends?: Array< { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null > | null; +======= + friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | { __typename?: 'Human'; name: string; +<<<<<<< HEAD friends?: Array< { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null > | null; +======= + friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | null; }; @@ -58,7 +66,7 @@ type HeroAppearsInQueryVariables = Exact<{ [key: string]: never }>; type HeroAppearsInQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; appearsIn: Array } | { __typename?: 'Human'; name: string; appearsIn: Array } | null; @@ -70,19 +78,23 @@ type HeroDetailsQueryVariables = Exact<{ type HeroDetailsQuery = { __typename?: 'Query'; - hero?: - | { __typename?: 'Droid'; primaryFunction?: string | null; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } + hero: + | { __typename?: 'Droid'; primaryFunction: string | null; name: string } + | { __typename?: 'Human'; height: number | null; name: string } | null; }; +<<<<<<< HEAD type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction?: string | null; name: string; }; +======= +type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction: string | null; name: string }; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) -type HeroDetails_Human_Fragment = { __typename?: 'Human'; height?: number | null; name: string }; +type HeroDetails_Human_Fragment = { __typename?: 'Human'; height: number | null; name: string }; type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; @@ -92,9 +104,9 @@ type HeroDetailsWithFragmentQueryVariables = Exact<{ type HeroDetailsWithFragmentQuery = { __typename?: 'Query'; - hero?: - | { __typename?: 'Droid'; primaryFunction?: string | null; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } + hero: + | { __typename?: 'Droid'; primaryFunction: string | null; name: string } + | { __typename?: 'Human'; height: number | null; name: string } | null; }; @@ -104,7 +116,7 @@ type HeroNameQueryVariables = Exact<{ type HeroNameQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; type HeroNameConditionalInclusionQueryVariables = Exact<{ @@ -114,7 +126,7 @@ type HeroNameConditionalInclusionQueryVariables = Exact<{ type HeroNameConditionalInclusionQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; }; type HeroNameConditionalExclusionQueryVariables = Exact<{ @@ -124,7 +136,7 @@ type HeroNameConditionalExclusionQueryVariables = Exact<{ type HeroNameConditionalExclusionQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; }; type HeroParentTypeDependentFieldQueryVariables = Exact<{ @@ -133,23 +145,33 @@ type HeroParentTypeDependentFieldQueryVariables = Exact<{ type HeroParentTypeDependentFieldQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; +<<<<<<< HEAD friends?: Array< | { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height?: number | null; name: string } | null +======= + friends: Array< + { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) > | null; } | { __typename?: 'Human'; name: string; +<<<<<<< HEAD friends?: Array< | { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height?: number | null; name: string } | null +======= + friends: Array< + { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) > | null; } | null; @@ -161,25 +183,29 @@ type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ type HeroTypeDependentAliasedFieldQuery = { __typename?: 'Query'; +<<<<<<< HEAD hero?: | { __typename?: 'Droid'; property?: string | null } | { __typename?: 'Human'; property?: string | null } | null; +======= + hero: { __typename?: 'Droid'; property: string | null } | { __typename?: 'Human'; property: string | null } | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) }; -type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass?: number | null }; +type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass: number | null }; type HumanWithNullHeightQueryVariables = Exact<{ [key: string]: never }>; type HumanWithNullHeightQuery = { __typename?: 'Query'; - human?: { __typename?: 'Human'; name: string; mass?: number | null } | null; + human: { __typename?: 'Human'; name: string; mass: number | null } | null; }; type TwoHeroesQueryVariables = Exact<{ [key: string]: never }>; type TwoHeroesQuery = { __typename?: 'Query'; - r2?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; - luke?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + r2: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + luke: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; diff --git a/dev-test/star-wars/types.immutableTypes.ts b/dev-test/star-wars/types.immutableTypes.ts index c3b9dd10e2f..48103e12eeb 100644 --- a/dev-test/star-wars/types.immutableTypes.ts +++ b/dev-test/star-wars/types.immutableTypes.ts @@ -9,10 +9,10 @@ export type CreateReviewForEpisodeMutationVariables = Exact<{ export type CreateReviewForEpisodeMutation = { readonly __typename?: 'Mutation'; - readonly createReview?: { + readonly createReview: { readonly __typename?: 'Review'; readonly stars: number; - readonly commentary?: string | null; + readonly commentary: string | null; } | null; }; @@ -22,7 +22,7 @@ export type ExcludeQueryAlphaQueryVariables = Exact<{ export type ExcludeQueryAlphaQuery = { readonly __typename?: 'Query'; - readonly hero?: + readonly hero: | { readonly __typename?: 'Droid'; readonly name: string } | { readonly __typename?: 'Human'; readonly name: string } | null; @@ -34,7 +34,7 @@ export type ExcludeQueryBetaQueryVariables = Exact<{ export type ExcludeQueryBetaQuery = { readonly __typename?: 'Query'; - readonly hero?: + readonly hero: | { readonly __typename?: 'Droid'; readonly name: string } | { readonly __typename?: 'Human'; readonly name: string } | null; @@ -46,11 +46,11 @@ export type HeroAndFriendsNamesQueryVariables = Exact<{ export type HeroAndFriendsNamesQuery = { readonly __typename?: 'Query'; - readonly hero?: + readonly hero: | { readonly __typename?: 'Droid'; readonly name: string; - readonly friends?: ReadonlyArray< + readonly friends: ReadonlyArray< | { readonly __typename?: 'Droid'; readonly name: string } | { readonly __typename?: 'Human'; readonly name: string } | null @@ -59,7 +59,7 @@ export type HeroAndFriendsNamesQuery = { | { readonly __typename?: 'Human'; readonly name: string; - readonly friends?: ReadonlyArray< + readonly friends: ReadonlyArray< | { readonly __typename?: 'Droid'; readonly name: string } | { readonly __typename?: 'Human'; readonly name: string } | null @@ -72,6 +72,7 @@ export type HeroAppearsInQueryVariables = Exact<{ [key: string]: never }>; export type HeroAppearsInQuery = { readonly __typename?: 'Query'; +<<<<<<< HEAD readonly hero?: | { readonly __typename?: 'Droid'; @@ -83,6 +84,11 @@ export type HeroAppearsInQuery = { readonly name: string; readonly appearsIn: ReadonlyArray; } +======= + readonly hero: + | { readonly __typename?: 'Droid'; readonly name: string; readonly appearsIn: ReadonlyArray } + | { readonly __typename?: 'Human'; readonly name: string; readonly appearsIn: ReadonlyArray } +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) | null; }; @@ -92,6 +98,7 @@ export type HeroDetailsQueryVariables = Exact<{ export type HeroDetailsQuery = { readonly __typename?: 'Query'; +<<<<<<< HEAD readonly hero?: | { readonly __typename?: 'Droid'; @@ -99,18 +106,23 @@ export type HeroDetailsQuery = { readonly name: string; } | { readonly __typename?: 'Human'; readonly height?: number | null; readonly name: string } +======= + readonly hero: + | { readonly __typename?: 'Droid'; readonly primaryFunction: string | null; readonly name: string } + | { readonly __typename?: 'Human'; readonly height: number | null; readonly name: string } +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) | null; }; type HeroDetails_Droid_Fragment = { readonly __typename?: 'Droid'; - readonly primaryFunction?: string | null; + readonly primaryFunction: string | null; readonly name: string; }; type HeroDetails_Human_Fragment = { readonly __typename?: 'Human'; - readonly height?: number | null; + readonly height: number | null; readonly name: string; }; @@ -122,6 +134,7 @@ export type HeroDetailsWithFragmentQueryVariables = Exact<{ export type HeroDetailsWithFragmentQuery = { readonly __typename?: 'Query'; +<<<<<<< HEAD readonly hero?: | { readonly __typename?: 'Droid'; @@ -129,6 +142,11 @@ export type HeroDetailsWithFragmentQuery = { readonly name: string; } | { readonly __typename?: 'Human'; readonly height?: number | null; readonly name: string } +======= + readonly hero: + | { readonly __typename?: 'Droid'; readonly primaryFunction: string | null; readonly name: string } + | { readonly __typename?: 'Human'; readonly height: number | null; readonly name: string } +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) | null; }; @@ -138,7 +156,7 @@ export type HeroNameQueryVariables = Exact<{ export type HeroNameQuery = { readonly __typename?: 'Query'; - readonly hero?: + readonly hero: | { readonly __typename?: 'Droid'; readonly name: string } | { readonly __typename?: 'Human'; readonly name: string } | null; @@ -151,7 +169,7 @@ export type HeroNameConditionalInclusionQueryVariables = Exact<{ export type HeroNameConditionalInclusionQuery = { readonly __typename?: 'Query'; - readonly hero?: + readonly hero: | { readonly __typename?: 'Droid'; readonly name?: string } | { readonly __typename?: 'Human'; readonly name?: string } | null; @@ -164,7 +182,7 @@ export type HeroNameConditionalExclusionQueryVariables = Exact<{ export type HeroNameConditionalExclusionQuery = { readonly __typename?: 'Query'; - readonly hero?: + readonly hero: | { readonly __typename?: 'Droid'; readonly name?: string } | { readonly __typename?: 'Human'; readonly name?: string } | null; @@ -176,30 +194,38 @@ export type HeroParentTypeDependentFieldQueryVariables = Exact<{ export type HeroParentTypeDependentFieldQuery = { readonly __typename?: 'Query'; - readonly hero?: + readonly hero: | { readonly __typename?: 'Droid'; readonly name: string; - readonly friends?: ReadonlyArray< + readonly friends: ReadonlyArray< | { readonly __typename?: 'Droid'; readonly name: string } +<<<<<<< HEAD | { readonly __typename?: 'Human'; readonly height?: number | null; readonly name: string; } +======= + | { readonly __typename?: 'Human'; readonly height: number | null; readonly name: string } +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) | null > | null; } | { readonly __typename?: 'Human'; readonly name: string; - readonly friends?: ReadonlyArray< + readonly friends: ReadonlyArray< | { readonly __typename?: 'Droid'; readonly name: string } +<<<<<<< HEAD | { readonly __typename?: 'Human'; readonly height?: number | null; readonly name: string; } +======= + | { readonly __typename?: 'Human'; readonly height: number | null; readonly name: string } +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) | null > | null; } @@ -212,38 +238,42 @@ export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ export type HeroTypeDependentAliasedFieldQuery = { readonly __typename?: 'Query'; - readonly hero?: - | { readonly __typename?: 'Droid'; readonly property?: string | null } - | { readonly __typename?: 'Human'; readonly property?: string | null } + readonly hero: + | { readonly __typename?: 'Droid'; readonly property: string | null } + | { readonly __typename?: 'Human'; readonly property: string | null } | null; }; export type HumanFieldsFragment = { readonly __typename?: 'Human'; readonly name: string; - readonly mass?: number | null; + readonly mass: number | null; }; export type HumanWithNullHeightQueryVariables = Exact<{ [key: string]: never }>; export type HumanWithNullHeightQuery = { readonly __typename?: 'Query'; +<<<<<<< HEAD readonly human?: { readonly __typename?: 'Human'; readonly name: string; readonly mass?: number | null; } | null; +======= + readonly human: { readonly __typename?: 'Human'; readonly name: string; readonly mass: number | null } | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) }; export type TwoHeroesQueryVariables = Exact<{ [key: string]: never }>; export type TwoHeroesQuery = { readonly __typename?: 'Query'; - readonly r2?: + readonly r2: | { readonly __typename?: 'Droid'; readonly name: string } | { readonly __typename?: 'Human'; readonly name: string } | null; - readonly luke?: + readonly luke: | { readonly __typename?: 'Droid'; readonly name: string } | { readonly __typename?: 'Human'; readonly name: string } | null; diff --git a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts index 4e34d8a65e6..d09b49aecd0 100644 --- a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts @@ -9,7 +9,7 @@ export type CreateReviewForEpisodeMutationVariables = Exact<{ export type CreateReviewForEpisodeMutation = { __typename?: 'Mutation'; - createReview?: { __typename?: 'Review'; stars: number; commentary?: string | null } | null; + createReview: { __typename?: 'Review'; stars: number; commentary: string | null } | null; }; export type ExcludeQueryAlphaQueryVariables = Exact<{ @@ -18,7 +18,7 @@ export type ExcludeQueryAlphaQueryVariables = Exact<{ export type ExcludeQueryAlphaQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; export type ExcludeQueryBetaQueryVariables = Exact<{ @@ -27,7 +27,7 @@ export type ExcludeQueryBetaQueryVariables = Exact<{ export type ExcludeQueryBetaQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; export type HeroAndFriendsNamesQueryVariables = Exact<{ @@ -36,20 +36,28 @@ export type HeroAndFriendsNamesQueryVariables = Exact<{ export type HeroAndFriendsNamesQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; +<<<<<<< HEAD friends?: Array< { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null > | null; +======= + friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | { __typename?: 'Human'; name: string; +<<<<<<< HEAD friends?: Array< { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null > | null; +======= + friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | null; }; @@ -58,7 +66,7 @@ export type HeroAppearsInQueryVariables = Exact<{ [key: string]: never }>; export type HeroAppearsInQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; appearsIn: Array } | { __typename?: 'Human'; name: string; appearsIn: Array } | null; @@ -70,19 +78,23 @@ export type HeroDetailsQueryVariables = Exact<{ export type HeroDetailsQuery = { __typename?: 'Query'; - hero?: - | { __typename?: 'Droid'; primaryFunction?: string | null; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } + hero: + | { __typename?: 'Droid'; primaryFunction: string | null; name: string } + | { __typename?: 'Human'; height: number | null; name: string } | null; }; +<<<<<<< HEAD type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction?: string | null; name: string; }; +======= +type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction: string | null; name: string }; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) -type HeroDetails_Human_Fragment = { __typename?: 'Human'; height?: number | null; name: string }; +type HeroDetails_Human_Fragment = { __typename?: 'Human'; height: number | null; name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; @@ -92,9 +104,9 @@ export type HeroDetailsWithFragmentQueryVariables = Exact<{ export type HeroDetailsWithFragmentQuery = { __typename?: 'Query'; - hero?: - | { __typename?: 'Droid'; primaryFunction?: string | null; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } + hero: + | { __typename?: 'Droid'; primaryFunction: string | null; name: string } + | { __typename?: 'Human'; height: number | null; name: string } | null; }; @@ -104,7 +116,7 @@ export type HeroNameQueryVariables = Exact<{ export type HeroNameQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ @@ -114,7 +126,7 @@ export type HeroNameConditionalInclusionQueryVariables = Exact<{ export type HeroNameConditionalInclusionQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ @@ -124,7 +136,7 @@ export type HeroNameConditionalExclusionQueryVariables = Exact<{ export type HeroNameConditionalExclusionQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ @@ -133,23 +145,33 @@ export type HeroParentTypeDependentFieldQueryVariables = Exact<{ export type HeroParentTypeDependentFieldQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; +<<<<<<< HEAD friends?: Array< | { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height?: number | null; name: string } | null +======= + friends: Array< + { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) > | null; } | { __typename?: 'Human'; name: string; +<<<<<<< HEAD friends?: Array< | { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height?: number | null; name: string } | null +======= + friends: Array< + { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) > | null; } | null; @@ -161,25 +183,29 @@ export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ export type HeroTypeDependentAliasedFieldQuery = { __typename?: 'Query'; +<<<<<<< HEAD hero?: | { __typename?: 'Droid'; property?: string | null } | { __typename?: 'Human'; property?: string | null } | null; +======= + hero: { __typename?: 'Droid'; property: string | null } | { __typename?: 'Human'; property: string | null } | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) }; -export type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass?: number | null }; +export type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass: number | null }; export type HumanWithNullHeightQueryVariables = Exact<{ [key: string]: never }>; export type HumanWithNullHeightQuery = { __typename?: 'Query'; - human?: { __typename?: 'Human'; name: string; mass?: number | null } | null; + human: { __typename?: 'Human'; name: string; mass: number | null } | null; }; export type TwoHeroesQueryVariables = Exact<{ [key: string]: never }>; export type TwoHeroesQuery = { __typename?: 'Query'; - r2?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; - luke?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + r2: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + luke: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; diff --git a/dev-test/star-wars/types.preResolveTypes.ts b/dev-test/star-wars/types.preResolveTypes.ts index 4e34d8a65e6..d09b49aecd0 100644 --- a/dev-test/star-wars/types.preResolveTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.ts @@ -9,7 +9,7 @@ export type CreateReviewForEpisodeMutationVariables = Exact<{ export type CreateReviewForEpisodeMutation = { __typename?: 'Mutation'; - createReview?: { __typename?: 'Review'; stars: number; commentary?: string | null } | null; + createReview: { __typename?: 'Review'; stars: number; commentary: string | null } | null; }; export type ExcludeQueryAlphaQueryVariables = Exact<{ @@ -18,7 +18,7 @@ export type ExcludeQueryAlphaQueryVariables = Exact<{ export type ExcludeQueryAlphaQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; export type ExcludeQueryBetaQueryVariables = Exact<{ @@ -27,7 +27,7 @@ export type ExcludeQueryBetaQueryVariables = Exact<{ export type ExcludeQueryBetaQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; export type HeroAndFriendsNamesQueryVariables = Exact<{ @@ -36,20 +36,28 @@ export type HeroAndFriendsNamesQueryVariables = Exact<{ export type HeroAndFriendsNamesQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; +<<<<<<< HEAD friends?: Array< { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null > | null; +======= + friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | { __typename?: 'Human'; name: string; +<<<<<<< HEAD friends?: Array< { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null > | null; +======= + friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | null; }; @@ -58,7 +66,7 @@ export type HeroAppearsInQueryVariables = Exact<{ [key: string]: never }>; export type HeroAppearsInQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; appearsIn: Array } | { __typename?: 'Human'; name: string; appearsIn: Array } | null; @@ -70,19 +78,23 @@ export type HeroDetailsQueryVariables = Exact<{ export type HeroDetailsQuery = { __typename?: 'Query'; - hero?: - | { __typename?: 'Droid'; primaryFunction?: string | null; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } + hero: + | { __typename?: 'Droid'; primaryFunction: string | null; name: string } + | { __typename?: 'Human'; height: number | null; name: string } | null; }; +<<<<<<< HEAD type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction?: string | null; name: string; }; +======= +type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction: string | null; name: string }; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) -type HeroDetails_Human_Fragment = { __typename?: 'Human'; height?: number | null; name: string }; +type HeroDetails_Human_Fragment = { __typename?: 'Human'; height: number | null; name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; @@ -92,9 +104,9 @@ export type HeroDetailsWithFragmentQueryVariables = Exact<{ export type HeroDetailsWithFragmentQuery = { __typename?: 'Query'; - hero?: - | { __typename?: 'Droid'; primaryFunction?: string | null; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } + hero: + | { __typename?: 'Droid'; primaryFunction: string | null; name: string } + | { __typename?: 'Human'; height: number | null; name: string } | null; }; @@ -104,7 +116,7 @@ export type HeroNameQueryVariables = Exact<{ export type HeroNameQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ @@ -114,7 +126,7 @@ export type HeroNameConditionalInclusionQueryVariables = Exact<{ export type HeroNameConditionalInclusionQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ @@ -124,7 +136,7 @@ export type HeroNameConditionalExclusionQueryVariables = Exact<{ export type HeroNameConditionalExclusionQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ @@ -133,23 +145,33 @@ export type HeroParentTypeDependentFieldQueryVariables = Exact<{ export type HeroParentTypeDependentFieldQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; +<<<<<<< HEAD friends?: Array< | { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height?: number | null; name: string } | null +======= + friends: Array< + { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) > | null; } | { __typename?: 'Human'; name: string; +<<<<<<< HEAD friends?: Array< | { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height?: number | null; name: string } | null +======= + friends: Array< + { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) > | null; } | null; @@ -161,25 +183,29 @@ export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ export type HeroTypeDependentAliasedFieldQuery = { __typename?: 'Query'; +<<<<<<< HEAD hero?: | { __typename?: 'Droid'; property?: string | null } | { __typename?: 'Human'; property?: string | null } | null; +======= + hero: { __typename?: 'Droid'; property: string | null } | { __typename?: 'Human'; property: string | null } | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) }; -export type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass?: number | null }; +export type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass: number | null }; export type HumanWithNullHeightQueryVariables = Exact<{ [key: string]: never }>; export type HumanWithNullHeightQuery = { __typename?: 'Query'; - human?: { __typename?: 'Human'; name: string; mass?: number | null } | null; + human: { __typename?: 'Human'; name: string; mass: number | null } | null; }; export type TwoHeroesQueryVariables = Exact<{ [key: string]: never }>; export type TwoHeroesQuery = { __typename?: 'Query'; - r2?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; - luke?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + r2: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + luke: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; diff --git a/dev-test/star-wars/types.skipSchema.ts b/dev-test/star-wars/types.skipSchema.ts index 4e34d8a65e6..d09b49aecd0 100644 --- a/dev-test/star-wars/types.skipSchema.ts +++ b/dev-test/star-wars/types.skipSchema.ts @@ -9,7 +9,7 @@ export type CreateReviewForEpisodeMutationVariables = Exact<{ export type CreateReviewForEpisodeMutation = { __typename?: 'Mutation'; - createReview?: { __typename?: 'Review'; stars: number; commentary?: string | null } | null; + createReview: { __typename?: 'Review'; stars: number; commentary: string | null } | null; }; export type ExcludeQueryAlphaQueryVariables = Exact<{ @@ -18,7 +18,7 @@ export type ExcludeQueryAlphaQueryVariables = Exact<{ export type ExcludeQueryAlphaQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; export type ExcludeQueryBetaQueryVariables = Exact<{ @@ -27,7 +27,7 @@ export type ExcludeQueryBetaQueryVariables = Exact<{ export type ExcludeQueryBetaQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; export type HeroAndFriendsNamesQueryVariables = Exact<{ @@ -36,20 +36,28 @@ export type HeroAndFriendsNamesQueryVariables = Exact<{ export type HeroAndFriendsNamesQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; +<<<<<<< HEAD friends?: Array< { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null > | null; +======= + friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | { __typename?: 'Human'; name: string; +<<<<<<< HEAD friends?: Array< { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null > | null; +======= + friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | null; }; @@ -58,7 +66,7 @@ export type HeroAppearsInQueryVariables = Exact<{ [key: string]: never }>; export type HeroAppearsInQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; appearsIn: Array } | { __typename?: 'Human'; name: string; appearsIn: Array } | null; @@ -70,19 +78,23 @@ export type HeroDetailsQueryVariables = Exact<{ export type HeroDetailsQuery = { __typename?: 'Query'; - hero?: - | { __typename?: 'Droid'; primaryFunction?: string | null; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } + hero: + | { __typename?: 'Droid'; primaryFunction: string | null; name: string } + | { __typename?: 'Human'; height: number | null; name: string } | null; }; +<<<<<<< HEAD type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction?: string | null; name: string; }; +======= +type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction: string | null; name: string }; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) -type HeroDetails_Human_Fragment = { __typename?: 'Human'; height?: number | null; name: string }; +type HeroDetails_Human_Fragment = { __typename?: 'Human'; height: number | null; name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; @@ -92,9 +104,9 @@ export type HeroDetailsWithFragmentQueryVariables = Exact<{ export type HeroDetailsWithFragmentQuery = { __typename?: 'Query'; - hero?: - | { __typename?: 'Droid'; primaryFunction?: string | null; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } + hero: + | { __typename?: 'Droid'; primaryFunction: string | null; name: string } + | { __typename?: 'Human'; height: number | null; name: string } | null; }; @@ -104,7 +116,7 @@ export type HeroNameQueryVariables = Exact<{ export type HeroNameQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ @@ -114,7 +126,7 @@ export type HeroNameConditionalInclusionQueryVariables = Exact<{ export type HeroNameConditionalInclusionQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ @@ -124,7 +136,7 @@ export type HeroNameConditionalExclusionQueryVariables = Exact<{ export type HeroNameConditionalExclusionQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ @@ -133,23 +145,33 @@ export type HeroParentTypeDependentFieldQueryVariables = Exact<{ export type HeroParentTypeDependentFieldQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; +<<<<<<< HEAD friends?: Array< | { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height?: number | null; name: string } | null +======= + friends: Array< + { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) > | null; } | { __typename?: 'Human'; name: string; +<<<<<<< HEAD friends?: Array< | { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height?: number | null; name: string } | null +======= + friends: Array< + { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) > | null; } | null; @@ -161,25 +183,29 @@ export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ export type HeroTypeDependentAliasedFieldQuery = { __typename?: 'Query'; +<<<<<<< HEAD hero?: | { __typename?: 'Droid'; property?: string | null } | { __typename?: 'Human'; property?: string | null } | null; +======= + hero: { __typename?: 'Droid'; property: string | null } | { __typename?: 'Human'; property: string | null } | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) }; -export type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass?: number | null }; +export type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass: number | null }; export type HumanWithNullHeightQueryVariables = Exact<{ [key: string]: never }>; export type HumanWithNullHeightQuery = { __typename?: 'Query'; - human?: { __typename?: 'Human'; name: string; mass?: number | null } | null; + human: { __typename?: 'Human'; name: string; mass: number | null } | null; }; export type TwoHeroesQueryVariables = Exact<{ [key: string]: never }>; export type TwoHeroesQuery = { __typename?: 'Query'; - r2?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; - luke?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + r2: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + luke: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; diff --git a/dev-test/star-wars/types.ts b/dev-test/star-wars/types.ts index 4e34d8a65e6..d09b49aecd0 100644 --- a/dev-test/star-wars/types.ts +++ b/dev-test/star-wars/types.ts @@ -9,7 +9,7 @@ export type CreateReviewForEpisodeMutationVariables = Exact<{ export type CreateReviewForEpisodeMutation = { __typename?: 'Mutation'; - createReview?: { __typename?: 'Review'; stars: number; commentary?: string | null } | null; + createReview: { __typename?: 'Review'; stars: number; commentary: string | null } | null; }; export type ExcludeQueryAlphaQueryVariables = Exact<{ @@ -18,7 +18,7 @@ export type ExcludeQueryAlphaQueryVariables = Exact<{ export type ExcludeQueryAlphaQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; export type ExcludeQueryBetaQueryVariables = Exact<{ @@ -27,7 +27,7 @@ export type ExcludeQueryBetaQueryVariables = Exact<{ export type ExcludeQueryBetaQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; export type HeroAndFriendsNamesQueryVariables = Exact<{ @@ -36,20 +36,28 @@ export type HeroAndFriendsNamesQueryVariables = Exact<{ export type HeroAndFriendsNamesQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; +<<<<<<< HEAD friends?: Array< { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null > | null; +======= + friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | { __typename?: 'Human'; name: string; +<<<<<<< HEAD friends?: Array< { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null > | null; +======= + friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | null; }; @@ -58,7 +66,7 @@ export type HeroAppearsInQueryVariables = Exact<{ [key: string]: never }>; export type HeroAppearsInQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; appearsIn: Array } | { __typename?: 'Human'; name: string; appearsIn: Array } | null; @@ -70,19 +78,23 @@ export type HeroDetailsQueryVariables = Exact<{ export type HeroDetailsQuery = { __typename?: 'Query'; - hero?: - | { __typename?: 'Droid'; primaryFunction?: string | null; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } + hero: + | { __typename?: 'Droid'; primaryFunction: string | null; name: string } + | { __typename?: 'Human'; height: number | null; name: string } | null; }; +<<<<<<< HEAD type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction?: string | null; name: string; }; +======= +type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction: string | null; name: string }; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) -type HeroDetails_Human_Fragment = { __typename?: 'Human'; height?: number | null; name: string }; +type HeroDetails_Human_Fragment = { __typename?: 'Human'; height: number | null; name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; @@ -92,9 +104,9 @@ export type HeroDetailsWithFragmentQueryVariables = Exact<{ export type HeroDetailsWithFragmentQuery = { __typename?: 'Query'; - hero?: - | { __typename?: 'Droid'; primaryFunction?: string | null; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } + hero: + | { __typename?: 'Droid'; primaryFunction: string | null; name: string } + | { __typename?: 'Human'; height: number | null; name: string } | null; }; @@ -104,7 +116,7 @@ export type HeroNameQueryVariables = Exact<{ export type HeroNameQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ @@ -114,7 +126,7 @@ export type HeroNameConditionalInclusionQueryVariables = Exact<{ export type HeroNameConditionalInclusionQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ @@ -124,7 +136,7 @@ export type HeroNameConditionalExclusionQueryVariables = Exact<{ export type HeroNameConditionalExclusionQuery = { __typename?: 'Query'; - hero?: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ @@ -133,23 +145,33 @@ export type HeroParentTypeDependentFieldQueryVariables = Exact<{ export type HeroParentTypeDependentFieldQuery = { __typename?: 'Query'; - hero?: + hero: | { __typename?: 'Droid'; name: string; +<<<<<<< HEAD friends?: Array< | { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height?: number | null; name: string } | null +======= + friends: Array< + { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) > | null; } | { __typename?: 'Human'; name: string; +<<<<<<< HEAD friends?: Array< | { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height?: number | null; name: string } | null +======= + friends: Array< + { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) > | null; } | null; @@ -161,25 +183,29 @@ export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ export type HeroTypeDependentAliasedFieldQuery = { __typename?: 'Query'; +<<<<<<< HEAD hero?: | { __typename?: 'Droid'; property?: string | null } | { __typename?: 'Human'; property?: string | null } | null; +======= + hero: { __typename?: 'Droid'; property: string | null } | { __typename?: 'Human'; property: string | null } | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) }; -export type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass?: number | null }; +export type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass: number | null }; export type HumanWithNullHeightQueryVariables = Exact<{ [key: string]: never }>; export type HumanWithNullHeightQuery = { __typename?: 'Query'; - human?: { __typename?: 'Human'; name: string; mass?: number | null } | null; + human: { __typename?: 'Human'; name: string; mass: number | null } | null; }; export type TwoHeroesQueryVariables = Exact<{ [key: string]: never }>; export type TwoHeroesQuery = { __typename?: 'Query'; - r2?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; - luke?: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + r2: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + luke: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; }; diff --git a/dev-test/test-null-value/result.d.ts b/dev-test/test-null-value/result.d.ts index d5e09b41781..82dfe670c4b 100644 --- a/dev-test/test-null-value/result.d.ts +++ b/dev-test/test-null-value/result.d.ts @@ -6,6 +6,10 @@ export type CartLineFragment = { id: string; quantity: number }; export type TestQueryVariables = Exact<{ [key: string]: never }>; +<<<<<<< HEAD export type TestQuery = { cart?: { lines: { nodes: Array<{ id: string; quantity: number }> } } | null; }; +======= +export type TestQuery = { cart: { lines: { nodes: Array<{ id: string; quantity: number }> } } | null }; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) diff --git a/dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts index 9784511b3c6..462accb7794 100644 --- a/dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts @@ -6,7 +6,7 @@ export type TestQueryVariables = Exact<{ [key: string]: never }>; export type TestQuery = { __typename?: 'Query'; - testArr1?: Array | null; + testArr1: Array | null; testArr2: Array; testArr3: Array; }; diff --git a/dev-test/test-schema/types.preResolveTypes.ts b/dev-test/test-schema/types.preResolveTypes.ts index 9784511b3c6..462accb7794 100644 --- a/dev-test/test-schema/types.preResolveTypes.ts +++ b/dev-test/test-schema/types.preResolveTypes.ts @@ -6,7 +6,7 @@ export type TestQueryVariables = Exact<{ [key: string]: never }>; export type TestQuery = { __typename?: 'Query'; - testArr1?: Array | null; + testArr1: Array | null; testArr2: Array; testArr3: Array; }; diff --git a/examples/react/apollo-client/src/gql/graphql.ts b/examples/react/apollo-client/src/gql/graphql.ts index 0341892a345..b8a36fe5a42 100644 --- a/examples/react/apollo-client/src/gql/graphql.ts +++ b/examples/react/apollo-client/src/gql/graphql.ts @@ -11,13 +11,17 @@ export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ export type AllFilmsWithVariablesQueryQuery = { __typename?: 'Root'; - allFilms?: { + allFilms: { __typename?: 'FilmsConnection'; - edges?: Array<{ + edges: Array<{ __typename?: 'FilmsEdge'; +<<<<<<< HEAD node?: | ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; +======= + node: ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | null> | null; } | null; }; @@ -25,9 +29,9 @@ export type AllFilmsWithVariablesQueryQuery = { export type FilmItemFragment = { __typename?: 'Film'; id: string; - title?: string | null; - releaseDate?: string | null; - producers?: Array | null; + title: string | null; + releaseDate: string | null; + producers: Array | null; } & { ' $fragmentName'?: 'FilmItemFragment' }; export const FilmItemFragmentDoc = { diff --git a/examples/react/http-executor/src/gql/graphql.ts b/examples/react/http-executor/src/gql/graphql.ts index 0341892a345..b8a36fe5a42 100644 --- a/examples/react/http-executor/src/gql/graphql.ts +++ b/examples/react/http-executor/src/gql/graphql.ts @@ -11,13 +11,17 @@ export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ export type AllFilmsWithVariablesQueryQuery = { __typename?: 'Root'; - allFilms?: { + allFilms: { __typename?: 'FilmsConnection'; - edges?: Array<{ + edges: Array<{ __typename?: 'FilmsEdge'; +<<<<<<< HEAD node?: | ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; +======= + node: ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | null> | null; } | null; }; @@ -25,9 +29,9 @@ export type AllFilmsWithVariablesQueryQuery = { export type FilmItemFragment = { __typename?: 'Film'; id: string; - title?: string | null; - releaseDate?: string | null; - producers?: Array | null; + title: string | null; + releaseDate: string | null; + producers: Array | null; } & { ' $fragmentName'?: 'FilmItemFragment' }; export const FilmItemFragmentDoc = { diff --git a/examples/react/tanstack-react-query/src/gql/graphql.ts b/examples/react/tanstack-react-query/src/gql/graphql.ts index c42ceb185cf..835ab1cfe5c 100644 --- a/examples/react/tanstack-react-query/src/gql/graphql.ts +++ b/examples/react/tanstack-react-query/src/gql/graphql.ts @@ -11,13 +11,17 @@ export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ export type AllFilmsWithVariablesQueryQuery = { __typename?: 'Root'; - allFilms?: { + allFilms: { __typename?: 'FilmsConnection'; - edges?: Array<{ + edges: Array<{ __typename?: 'FilmsEdge'; +<<<<<<< HEAD node?: | ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; +======= + node: ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | null> | null; } | null; }; @@ -25,9 +29,9 @@ export type AllFilmsWithVariablesQueryQuery = { export type FilmItemFragment = { __typename?: 'Film'; id: string; - title?: string | null; - releaseDate?: string | null; - producers?: Array | null; + title: string | null; + releaseDate: string | null; + producers: Array | null; } & { ' $fragmentName'?: 'FilmItemFragment' }; export class TypedDocumentString diff --git a/examples/react/urql/src/gql/graphql.ts b/examples/react/urql/src/gql/graphql.ts index da41e38e420..823889e065a 100644 --- a/examples/react/urql/src/gql/graphql.ts +++ b/examples/react/urql/src/gql/graphql.ts @@ -11,13 +11,17 @@ export type AllFilmsWithVariablesQuery199QueryVariables = Exact<{ export type AllFilmsWithVariablesQuery199Query = { __typename?: 'Root'; - allFilms?: { + allFilms: { __typename?: 'FilmsConnection'; - edges?: Array<{ + edges: Array<{ __typename?: 'FilmsEdge'; +<<<<<<< HEAD node?: | ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; +======= + node: ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | null> | null; } | null; }; @@ -25,9 +29,9 @@ export type AllFilmsWithVariablesQuery199Query = { export type FilmItemFragment = { __typename?: 'Film'; id: string; - title?: string | null; - releaseDate?: string | null; - producers?: Array | null; + title: string | null; + releaseDate: string | null; + producers: Array | null; } & { ' $fragmentName'?: 'FilmItemFragment' }; export class TypedDocumentString diff --git a/examples/typescript-esm/src/gql/graphql.ts b/examples/typescript-esm/src/gql/graphql.ts index 12561044a81..f6974dc72b0 100644 --- a/examples/typescript-esm/src/gql/graphql.ts +++ b/examples/typescript-esm/src/gql/graphql.ts @@ -9,14 +9,14 @@ export type AllPeopleQueryQueryVariables = Exact<{ [key: string]: never }>; export type AllPeopleQueryQuery = { __typename?: 'Root'; - allPeople?: { + allPeople: { __typename?: 'PeopleConnection'; - edges?: Array<{ + edges: Array<{ __typename?: 'PeopleEdge'; - node?: { + node: { __typename?: 'Person'; - name?: string | null; - homeworld?: { __typename?: 'Planet'; name?: string | null } | null; + name: string | null; + homeworld: { __typename?: 'Planet'; name: string | null } | null; } | null; } | null> | null; } | null; @@ -28,14 +28,14 @@ export type AllPeopleWithVariablesQueryQueryVariables = Exact<{ export type AllPeopleWithVariablesQueryQuery = { __typename?: 'Root'; - allPeople?: { + allPeople: { __typename?: 'PeopleConnection'; - edges?: Array<{ + edges: Array<{ __typename?: 'PeopleEdge'; - node?: { + node: { __typename?: 'Person'; - name?: string | null; - homeworld?: { __typename?: 'Planet'; name?: string | null } | null; + name: string | null; + homeworld: { __typename?: 'Planet'; name: string | null } | null; } | null; } | null> | null; } | null; diff --git a/examples/typescript-graphql-request/src/gql/graphql.ts b/examples/typescript-graphql-request/src/gql/graphql.ts index d8e0b62d6d9..f41b60648d0 100644 --- a/examples/typescript-graphql-request/src/gql/graphql.ts +++ b/examples/typescript-graphql-request/src/gql/graphql.ts @@ -9,14 +9,14 @@ export type AllPeopleQueryQueryVariables = Exact<{ [key: string]: never }>; export type AllPeopleQueryQuery = { __typename?: 'Root'; - allPeople?: { + allPeople: { __typename?: 'PeopleConnection'; - edges?: Array<{ + edges: Array<{ __typename?: 'PeopleEdge'; - node?: { + node: { __typename?: 'Person'; - name?: string | null; - homeworld?: { __typename?: 'Planet'; name?: string | null } | null; + name: string | null; + homeworld: { __typename?: 'Planet'; name: string | null } | null; } | null; } | null> | null; } | null; @@ -28,14 +28,14 @@ export type AllPeopleWithVariablesQueryQueryVariables = Exact<{ export type AllPeopleWithVariablesQueryQuery = { __typename?: 'Root'; - allPeople?: { + allPeople: { __typename?: 'PeopleConnection'; - edges?: Array<{ + edges: Array<{ __typename?: 'PeopleEdge'; - node?: { + node: { __typename?: 'Person'; - name?: string | null; - homeworld?: { __typename?: 'Planet'; name?: string | null } | null; + name: string | null; + homeworld: { __typename?: 'Planet'; name: string | null } | null; } | null; } | null> | null; } | null; diff --git a/examples/vite/vite-react-cts/src/gql/graphql.ts b/examples/vite/vite-react-cts/src/gql/graphql.ts index 1f179c7d1c3..effe8955b72 100644 --- a/examples/vite/vite-react-cts/src/gql/graphql.ts +++ b/examples/vite/vite-react-cts/src/gql/graphql.ts @@ -8,9 +8,9 @@ export type Incremental = export type FilmItemFragment = { __typename?: 'Film'; id: string; - title?: string | null; - releaseDate?: string | null; - producers?: Array | null; + title: string | null; + releaseDate: string | null; + producers: Array | null; } & { ' $fragmentName'?: 'FilmItemFragment' }; export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ @@ -19,13 +19,17 @@ export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ export type AllFilmsWithVariablesQueryQuery = { __typename?: 'Root'; - allFilms?: { + allFilms: { __typename?: 'FilmsConnection'; - edges?: Array<{ + edges: Array<{ __typename?: 'FilmsEdge'; +<<<<<<< HEAD node?: | ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; +======= + node: ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | null> | null; } | null; }; diff --git a/examples/vite/vite-react-mts/src/gql/graphql.ts b/examples/vite/vite-react-mts/src/gql/graphql.ts index 1f179c7d1c3..effe8955b72 100644 --- a/examples/vite/vite-react-mts/src/gql/graphql.ts +++ b/examples/vite/vite-react-mts/src/gql/graphql.ts @@ -8,9 +8,9 @@ export type Incremental = export type FilmItemFragment = { __typename?: 'Film'; id: string; - title?: string | null; - releaseDate?: string | null; - producers?: Array | null; + title: string | null; + releaseDate: string | null; + producers: Array | null; } & { ' $fragmentName'?: 'FilmItemFragment' }; export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ @@ -19,13 +19,17 @@ export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ export type AllFilmsWithVariablesQueryQuery = { __typename?: 'Root'; - allFilms?: { + allFilms: { __typename?: 'FilmsConnection'; - edges?: Array<{ + edges: Array<{ __typename?: 'FilmsEdge'; +<<<<<<< HEAD node?: | ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; +======= + node: ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | null> | null; } | null; }; diff --git a/examples/vite/vite-react-ts/src/gql/graphql.ts b/examples/vite/vite-react-ts/src/gql/graphql.ts index 1f179c7d1c3..effe8955b72 100644 --- a/examples/vite/vite-react-ts/src/gql/graphql.ts +++ b/examples/vite/vite-react-ts/src/gql/graphql.ts @@ -8,9 +8,9 @@ export type Incremental = export type FilmItemFragment = { __typename?: 'Film'; id: string; - title?: string | null; - releaseDate?: string | null; - producers?: Array | null; + title: string | null; + releaseDate: string | null; + producers: Array | null; } & { ' $fragmentName'?: 'FilmItemFragment' }; export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ @@ -19,13 +19,17 @@ export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ export type AllFilmsWithVariablesQueryQuery = { __typename?: 'Root'; - allFilms?: { + allFilms: { __typename?: 'FilmsConnection'; - edges?: Array<{ + edges: Array<{ __typename?: 'FilmsEdge'; +<<<<<<< HEAD node?: | ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; +======= + node: ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | null> | null; } | null; }; diff --git a/examples/vue/apollo-composable/src/gql/graphql.ts b/examples/vue/apollo-composable/src/gql/graphql.ts index b9b34fd54d4..aba4d5220af 100644 --- a/examples/vue/apollo-composable/src/gql/graphql.ts +++ b/examples/vue/apollo-composable/src/gql/graphql.ts @@ -11,13 +11,17 @@ export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ export type AllFilmsWithVariablesQueryQuery = { __typename?: 'Root'; - allFilms?: { + allFilms: { __typename?: 'FilmsConnection'; - edges?: Array<{ + edges: Array<{ __typename?: 'FilmsEdge'; +<<<<<<< HEAD node?: | ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; +======= + node: ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | null> | null; } | null; }; @@ -25,9 +29,9 @@ export type AllFilmsWithVariablesQueryQuery = { export type FilmItemFragment = { __typename?: 'Film'; id: string; - title?: string | null; - releaseDate?: string | null; - producers?: Array | null; + title: string | null; + releaseDate: string | null; + producers: Array | null; } & { ' $fragmentName'?: 'FilmItemFragment' }; export const FilmItemFragmentDoc = { diff --git a/examples/vue/urql/src/gql/graphql.ts b/examples/vue/urql/src/gql/graphql.ts index b9b34fd54d4..aba4d5220af 100644 --- a/examples/vue/urql/src/gql/graphql.ts +++ b/examples/vue/urql/src/gql/graphql.ts @@ -11,13 +11,17 @@ export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ export type AllFilmsWithVariablesQueryQuery = { __typename?: 'Root'; - allFilms?: { + allFilms: { __typename?: 'FilmsConnection'; - edges?: Array<{ + edges: Array<{ __typename?: 'FilmsEdge'; +<<<<<<< HEAD node?: | ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; +======= + node: ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | null> | null; } | null; }; @@ -25,9 +29,9 @@ export type AllFilmsWithVariablesQueryQuery = { export type FilmItemFragment = { __typename?: 'Film'; id: string; - title?: string | null; - releaseDate?: string | null; - producers?: Array | null; + title: string | null; + releaseDate: string | null; + producers: Array | null; } & { ' $fragmentName'?: 'FilmItemFragment' }; export const FilmItemFragmentDoc = { diff --git a/examples/vue/villus/src/gql/graphql.ts b/examples/vue/villus/src/gql/graphql.ts index b9b34fd54d4..aba4d5220af 100644 --- a/examples/vue/villus/src/gql/graphql.ts +++ b/examples/vue/villus/src/gql/graphql.ts @@ -11,13 +11,17 @@ export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ export type AllFilmsWithVariablesQueryQuery = { __typename?: 'Root'; - allFilms?: { + allFilms: { __typename?: 'FilmsConnection'; - edges?: Array<{ + edges: Array<{ __typename?: 'FilmsEdge'; +<<<<<<< HEAD node?: | ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; +======= + node: ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; +>>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | null> | null; } | null; }; @@ -25,9 +29,9 @@ export type AllFilmsWithVariablesQueryQuery = { export type FilmItemFragment = { __typename?: 'Film'; id: string; - title?: string | null; - releaseDate?: string | null; - producers?: Array | null; + title: string | null; + releaseDate: string | null; + producers: Array | null; } & { ' $fragmentName'?: 'FilmItemFragment' }; export const FilmItemFragmentDoc = { diff --git a/packages/plugins/other/visitor-plugin-common/src/selection-set-processor/base.ts b/packages/plugins/other/visitor-plugin-common/src/selection-set-processor/base.ts index 379665a3b02..8fc8b34a153 100644 --- a/packages/plugins/other/visitor-plugin-common/src/selection-set-processor/base.ts +++ b/packages/plugins/other/visitor-plugin-common/src/selection-set-processor/base.ts @@ -5,7 +5,7 @@ import { GraphQLOutputType, Location, } from 'graphql'; -import { AvoidOptionalsConfig, ConvertNameFn, NormalizedScalarsMap } from '../types.js'; +import { ConvertNameFn, NormalizedScalarsMap } from '../types.js'; export type PrimitiveField = { isConditional: boolean; fieldName: string }; export type PrimitiveAliasedFields = { @@ -28,14 +28,8 @@ export type SelectionSetProcessorConfig = { enumPrefix: boolean | null; enumSuffix: boolean | null; scalars: NormalizedScalarsMap; - formatNamedField( - name: string, - type?: GraphQLOutputType | GraphQLNamedType | null, - isConditional?: boolean, - isOptional?: boolean, - ): string; + formatNamedField(params: { name: string; isOptional?: boolean }): string; wrapTypeWithModifiers(baseType: string, type: GraphQLOutputType | GraphQLNamedType): string; - avoidOptionals?: AvoidOptionalsConfig | boolean; printFieldsOnNewLines?: boolean; }; diff --git a/packages/plugins/other/visitor-plugin-common/src/selection-set-processor/pre-resolve-types.ts b/packages/plugins/other/visitor-plugin-common/src/selection-set-processor/pre-resolve-types.ts index 75410d76f59..aaf720996b2 100644 --- a/packages/plugins/other/visitor-plugin-common/src/selection-set-processor/pre-resolve-types.ts +++ b/packages/plugins/other/visitor-plugin-common/src/selection-set-processor/pre-resolve-types.ts @@ -1,5 +1,5 @@ -import { GraphQLInterfaceType, GraphQLObjectType, isEnumType, isNonNullType } from 'graphql'; -import { getBaseType, removeNonNullWrapper } from '@graphql-codegen/plugin-helpers'; +import { GraphQLInterfaceType, GraphQLObjectType, isEnumType } from 'graphql'; +import { getBaseType } from '@graphql-codegen/plugin-helpers'; import { BaseSelectionSetProcessor, LinkField, @@ -34,15 +34,10 @@ export class PreResolveTypesProcessor extends BaseSelectionSetProcessor { if (aliasedField.fieldName === '__typename') { - const name = this.config.formatNamedField(aliasedField.alias, null); + const name = this.config.formatNamedField({ name: aliasedField.alias }); return { name, type: `'${schemaType.name}'`, @@ -101,12 +96,10 @@ export class PreResolveTypesProcessor extends BaseSelectionSetProcessor> = { __type: TypeMetaFieldDef, }; -export class SelectionSetToObject { +export class SelectionSetToObject< + Config extends ParsedDocumentsConfig = ParsedDocumentsConfig, + SelectionSetProcessorConfig extends BaseSelectionSetProcessorConfig = + BaseSelectionSetProcessorConfig, +> { protected _primitiveFields: PrimitiveField[] = []; protected _primitiveAliasedFields: PrimitiveAliasedFields[] = []; protected _linksFields: LinkField[] = []; protected _queriedForTypename = false; constructor( - protected _processor: BaseSelectionSetProcessor, + protected _processor: BaseSelectionSetProcessor, protected _scalars: NormalizedScalarsMap, protected _schema: GraphQLSchema, protected _convertName: ConvertNameFn, @@ -436,6 +441,7 @@ export class SelectionSetToObject`; }; - const formatNamedField = ( - name: string, - type: GraphQLOutputType | GraphQLNamedType | null, - isConditional = false, - isOptional = false, - ): string => { - const optional = - isOptional || - isConditional || - (!this.config.avoidOptionals.field && !!type && !isNonNullType(type)); - return (this.config.immutableTypes ? `readonly ${name}` : name) + (optional ? '?' : ''); - }; - const allFragments: LoadedFragment[] = [ ...( documentNode.definitions.filter( @@ -144,14 +128,15 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< enumPrefix: this.config.enumPrefix, enumSuffix: this.config.enumSuffix, scalars: this.scalars, - formatNamedField, + formatNamedField: ({ name, isOptional }) => { + return (this.config.immutableTypes ? `readonly ${name}` : name) + (isOptional ? '?' : ''); + }, wrapTypeWithModifiers(baseType, type) { return wrapTypeWithModifiers(baseType, type, { wrapOptional, wrapArray, }); }, - avoidOptionals: this.config.avoidOptionals, printFieldsOnNewLines: this.config.printFieldsOnNewLines, }; const processor = new ( @@ -175,6 +160,9 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< new TypeScriptOperationVariablesToObject( this.scalars, this.convertName.bind(this), + // FIXME: this is the legacy avoidOptionals which was used to make Result fields non-optional. This use case is no longer valid. + // It's also being used for Variables so people could already be using it. + // Maybe it's better to deprecate and remove, to see what users think. this.config.avoidOptionals, this.config.immutableTypes, this.config.namespacedImportName, diff --git a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap index b9d144384f1..0ba7941fc12 100644 --- a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap +++ b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap @@ -18,19 +18,19 @@ exports[`TypeScript Operations Plugin > Issues > #2699 - Issues with multiple in export type GetEntityBrandDataQuery = { __typename?: 'Query', node: - | { __typename: 'Company', active: boolean, id: string, createdAt: any, updatedAt: any, brandData?: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle?: string | null, description: string } | null, createdBy?: { __typename?: 'User', id: string, name: string } | null, updatedBy?: { __typename?: 'User', id: string, name: string } | null } - | { __typename: 'Theater', active: boolean, id: string, createdAt: any, updatedAt: any, brandData?: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle?: string | null, description: string } | null, createdBy?: { __typename?: 'User', id: string, name: string } | null, updatedBy?: { __typename?: 'User', id: string, name: string } | null } - | { __typename: 'Movie', id: string, createdAt: any, updatedAt: any, brandData?: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle?: string | null, description: string } | null, createdBy?: { __typename?: 'User', id: string, name: string } | null, updatedBy?: { __typename?: 'User', id: string, name: string } | null } - | { __typename: 'User', id: string, createdAt: any, updatedAt: any, brandData?: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle?: string | null, description: string } | null, createdBy?: { __typename?: 'User', id: string, name: string } | null, updatedBy?: { __typename?: 'User', id: string, name: string } | null } + | { __typename: 'Company', active: boolean, id: string, createdAt: any, updatedAt: any, brandData: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null, createdBy: { __typename?: 'User', id: string, name: string } | null, updatedBy: { __typename?: 'User', id: string, name: string } | null } + | { __typename: 'Theater', active: boolean, id: string, createdAt: any, updatedAt: any, brandData: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null, createdBy: { __typename?: 'User', id: string, name: string } | null, updatedBy: { __typename?: 'User', id: string, name: string } | null } + | { __typename: 'Movie', id: string, createdAt: any, updatedAt: any, brandData: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null, createdBy: { __typename?: 'User', id: string, name: string } | null, updatedBy: { __typename?: 'User', id: string, name: string } | null } + | { __typename: 'User', id: string, createdAt: any, updatedAt: any, brandData: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null, createdBy: { __typename?: 'User', id: string, name: string } | null, updatedBy: { __typename?: 'User', id: string, name: string } | null } }; -type EntityBrandData_Company_Fragment = { __typename?: 'Company', brandData?: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle?: string | null, description: string } | null }; +type EntityBrandData_Company_Fragment = { __typename?: 'Company', brandData: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null }; -type EntityBrandData_Theater_Fragment = { __typename?: 'Theater', brandData?: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle?: string | null, description: string } | null }; +type EntityBrandData_Theater_Fragment = { __typename?: 'Theater', brandData: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null }; -type EntityBrandData_Movie_Fragment = { __typename?: 'Movie', brandData?: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle?: string | null, description: string } | null }; +type EntityBrandData_Movie_Fragment = { __typename?: 'Movie', brandData: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null }; -type EntityBrandData_User_Fragment = { __typename?: 'User', brandData?: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle?: string | null, description: string } | null }; +type EntityBrandData_User_Fragment = { __typename?: 'User', brandData: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null }; export type EntityBrandDataFragment = | EntityBrandData_Company_Fragment @@ -39,13 +39,13 @@ export type EntityBrandDataFragment = | EntityBrandData_User_Fragment ; -type ElementMetadata_Company_Fragment = { __typename?: 'Company', createdAt: any, updatedAt: any, createdBy?: { __typename?: 'User', id: string, name: string } | null, updatedBy?: { __typename?: 'User', id: string, name: string } | null }; +type ElementMetadata_Company_Fragment = { __typename?: 'Company', createdAt: any, updatedAt: any, createdBy: { __typename?: 'User', id: string, name: string } | null, updatedBy: { __typename?: 'User', id: string, name: string } | null }; -type ElementMetadata_Theater_Fragment = { __typename?: 'Theater', createdAt: any, updatedAt: any, createdBy?: { __typename?: 'User', id: string, name: string } | null, updatedBy?: { __typename?: 'User', id: string, name: string } | null }; +type ElementMetadata_Theater_Fragment = { __typename?: 'Theater', createdAt: any, updatedAt: any, createdBy: { __typename?: 'User', id: string, name: string } | null, updatedBy: { __typename?: 'User', id: string, name: string } | null }; -type ElementMetadata_Movie_Fragment = { __typename?: 'Movie', createdAt: any, updatedAt: any, createdBy?: { __typename?: 'User', id: string, name: string } | null, updatedBy?: { __typename?: 'User', id: string, name: string } | null }; +type ElementMetadata_Movie_Fragment = { __typename?: 'Movie', createdAt: any, updatedAt: any, createdBy: { __typename?: 'User', id: string, name: string } | null, updatedBy: { __typename?: 'User', id: string, name: string } | null }; -type ElementMetadata_User_Fragment = { __typename?: 'User', createdAt: any, updatedAt: any, createdBy?: { __typename?: 'User', id: string, name: string } | null, updatedBy?: { __typename?: 'User', id: string, name: string } | null }; +type ElementMetadata_User_Fragment = { __typename?: 'User', createdAt: any, updatedAt: any, createdBy: { __typename?: 'User', id: string, name: string } | null, updatedBy: { __typename?: 'User', id: string, name: string } | null }; export type ElementMetadataFragment = | ElementMetadata_Company_Fragment @@ -82,56 +82,7 @@ export type QQuery = { __typename?: 'Query', hotel: { __typename?: 'Hotel', id: `; exports[`TypeScript Operations Plugin > Issues > #3064 - fragments over interfaces causes issues with fields 2`] = ` -"export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { [_ in K]?: never }; -export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } -}; - -export type Venue = { - id: Scalars['String']['output']; - name: Scalars['String']['output']; -}; - -export type GpsPosition = { - __typename?: 'GPSPosition'; - lat: Scalars['Float']['output']; - lng: Scalars['Float']['output']; -}; - -export type VenueWithPosition = { - id: Scalars['String']['output']; - gpsPosition: GpsPosition; -}; - -export type Hotel = VenueWithPosition & Venue & { - __typename?: 'Hotel'; - id: Scalars['String']['output']; - gpsPosition: GpsPosition; - name: Scalars['String']['output']; -}; - -export type Transport = Venue & { - __typename?: 'Transport'; - id: Scalars['String']['output']; - name: Scalars['String']['output']; -}; - -export type Query = { - __typename?: 'Query'; - hotel: Hotel; - transport: Transport; -}; -type Venue_Hotel_Fragment = { __typename?: 'Hotel', id: string, gpsPosition: { __typename?: 'GPSPosition', lat: number, lng: number } }; +"type Venue_Hotel_Fragment = { __typename?: 'Hotel', id: string, gpsPosition: { __typename?: 'GPSPosition', lat: number, lng: number } }; type Venue_Transport_Fragment = { __typename?: 'Transport', id: string }; @@ -192,7 +143,7 @@ exports[`TypeScript Operations Plugin > Selection Set > Should generate the corr export type UserQueryQuery = ( { __typename?: 'Query' } - & { user?: Maybe<( + & { user: Maybe<( { __typename?: 'User' } & Pick )> } @@ -211,7 +162,7 @@ exports[`TypeScript Operations Plugin > Selection Set > Should generate the corr export type UserQueryQuery = ( { __typename?: 'Query' } - & { user?: Maybe<( + & { user: Maybe<( { __typename?: 'User' } & Pick )> } @@ -225,7 +176,7 @@ exports[`TypeScript Operations Plugin > Selection Set > Should generate the corr export type UserQueryQuery = ( { __typename?: 'Query' } - & { user?: Maybe<( + & { user: Maybe<( { __typename?: 'User' } & Pick )> } @@ -266,7 +217,7 @@ exports[`TypeScript Operations Plugin > Selection Set > Should generate the corr export type Unnamed_1_Query = ( { __typename?: 'Query' } - & { b?: Maybe< + & { b: Maybe< | ( { __typename?: 'A' } & Pick @@ -420,7 +371,7 @@ export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; export type UserQueryQuery = ( { __typename?: 'Query' } - & { user?: Maybe< + & { user: Maybe< | ( { __typename?: 'Tom' } & Pick @@ -435,48 +386,12 @@ export type UserQueryQuery = ( `; exports[`TypeScript Operations Plugin > Union & Interfaces > #4216 - handle fragments against unions and interfaces with flattenGeneratedTypes 1`] = ` -"export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { [_ in K]?: never }; -export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } -}; - -export type Query = { - __typename?: 'Query'; - search?: Maybe>; -}; - -export type Concept = { - id?: Maybe; -}; - -export type Dimension = Concept & { - __typename?: 'Dimension'; - id?: Maybe; -}; - -export type DimValue = { - __typename?: 'DimValue'; - dimension?: Maybe; - value: Scalars['String']['output']; -}; - -export type Searchable = Dimension | DimValue; -export type SearchPopularQueryVariables = Exact<{ [key: string]: never; }>; +"export type SearchPopularQueryVariables = Exact<{ [key: string]: never; }>; export type SearchPopularQuery = ( { __typename?: 'Query' } - & { search?: Maybe @@ -484,7 +399,7 @@ export type SearchPopularQuery = ( | ( { __typename?: 'DimValue' } & Pick - & { dimension?: Maybe<( + & { dimension: Maybe<( { __typename?: 'Dimension' } & Pick )> } @@ -512,7 +427,7 @@ export type UserQueryQuery = ( | ( { __typename?: 'Error3' } & Pick - & { info?: Maybe<( + & { info: Maybe<( { __typename?: 'AdditionalInfo' } & Pick )> } @@ -534,7 +449,7 @@ type UserResult1_Error2_Fragment = { __typename?: 'Error2' }; type UserResult1_Error3_Fragment = ( { __typename?: 'Error3' } - & { info?: Maybe<( + & { info: Maybe<( { __typename?: 'AdditionalInfo' } & Pick )> } @@ -567,60 +482,7 @@ export type UserResultFragment = `; exports[`TypeScript Operations Plugin > Union & Interfaces > Should handle union selection sets with both FragmentSpreads and InlineFragments with flattenGeneratedTypes 1`] = ` -"export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { [_ in K]?: never }; -export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } -}; - -export type Error = { - message: Scalars['String']['output']; -}; - -export type Error1 = Error & { - __typename?: 'Error1'; - message: Scalars['String']['output']; -}; - -export type Error2 = Error & { - __typename?: 'Error2'; - message: Scalars['String']['output']; -}; - -export type Error3 = Error & { - __typename?: 'Error3'; - message: Scalars['String']['output']; - info?: Maybe; -}; - -export type AdditionalInfo = { - __typename?: 'AdditionalInfo'; - message: Scalars['String']['output']; - message2: Scalars['String']['output']; -}; - -export type User = { - __typename?: 'User'; - id: Scalars['ID']['output']; - login: Scalars['String']['output']; -}; - -export type UserResult = User | Error2 | Error3; - -export type Query = { - __typename?: 'Query'; - user: UserResult; -}; -export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; +"export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; export type UserQueryQuery = ( @@ -637,7 +499,7 @@ export type UserQueryQuery = ( | ( { __typename?: 'Error3' } & Pick - & { info?: Maybe<( + & { info: Maybe<( { __typename?: 'AdditionalInfo' } & Pick )> } @@ -665,62 +527,7 @@ export type UserQueryQuery = ( `; exports[`TypeScript Operations Plugin > Union & Interfaces > Should handle union selection sets with both FragmentSpreads and InlineFragments with flattenGeneratedTypes and directives 1`] = ` -"export type Maybe = T | null; -export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { [_ in K]?: never }; -export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -/** All built-in and custom scalars, mapped to their actual values */ -export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } -}; - -export type Error = { - message: Scalars['String']['output']; -}; - -export type Error1 = Error & { - __typename?: 'Error1'; - message: Scalars['String']['output']; -}; - -export type Error2 = Error & { - __typename?: 'Error2'; - message: Scalars['String']['output']; -}; - -export type Error3 = Error & { - __typename?: 'Error3'; - message: Scalars['String']['output']; - info?: Maybe; -}; - -export type AdditionalInfo = { - __typename?: 'AdditionalInfo'; - message: Scalars['String']['output']; - message2: Scalars['String']['output']; -}; - -export type User = { - __typename?: 'User'; - id: Scalars['ID']['output']; - login: Scalars['String']['output']; - test?: Maybe; - test2?: Maybe; -}; - -export type UserResult = User | Error2 | Error3; - -export type Query = { - __typename?: 'Query'; - user: UserResult; -}; -export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; +"export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; export type UserQueryQuery = ( @@ -743,7 +550,7 @@ export type UserQueryQuery = ( | ( { __typename?: 'Error3' } & Pick - & { info?: Maybe<( + & { info: Maybe<( { __typename?: 'AdditionalInfo' } & Pick )> } diff --git a/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts b/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts index 349f2da0489..a582efd12a4 100644 --- a/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts @@ -157,7 +157,7 @@ describe('extractAllFieldsToTypes: true', () => { export type OverlappingFieldsMergingTestQuery_Query = { __typename: 'Query', - me?: OverlappingFieldsMergingTestQuery_me | null + me: OverlappingFieldsMergingTestQuery_me | null }; @@ -187,7 +187,7 @@ describe('extractAllFieldsToTypes: true', () => { export type NestedOverlappingFieldsMergingTestQuery_Query = { __typename: 'Query', - me?: NestedOverlappingFieldsMergingTestQuery_me | null + me: NestedOverlappingFieldsMergingTestQuery_me | null }; @@ -409,11 +409,11 @@ describe('extractAllFieldsToTypes: true', () => { export type ConversationBotSolutionFragment_BotSolution_originatedFrom_TalkInteraction = { __typename: 'TalkInteraction' }; - export type ConversationBotSolutionFragment_BotSolution_originatedFrom_NativeMessagingInteraction = { __typename: 'NativeMessagingInteraction', conversationId?: string | null }; + export type ConversationBotSolutionFragment_BotSolution_originatedFrom_NativeMessagingInteraction = { __typename: 'NativeMessagingInteraction', conversationId: string | null }; - export type ConversationBotSolutionFragment_BotSolution_originatedFrom_WhatsAppInteraction = { __typename: 'WhatsAppInteraction', conversationId?: string | null }; + export type ConversationBotSolutionFragment_BotSolution_originatedFrom_WhatsAppInteraction = { __typename: 'WhatsAppInteraction', conversationId: string | null }; - export type ConversationBotSolutionFragment_BotSolution_originatedFrom_WeChatInteraction = { __typename: 'WeChatInteraction', conversationId?: string | null }; + export type ConversationBotSolutionFragment_BotSolution_originatedFrom_WeChatInteraction = { __typename: 'WeChatInteraction', conversationId: string | null }; export type ConversationBotSolutionFragment_BotSolution_originatedFrom_NotImplementedOriginatedFrom = { __typename: 'NotImplementedOriginatedFrom' }; @@ -439,11 +439,11 @@ describe('extractAllFieldsToTypes: true', () => { export type ConversationConversationEventFragment_ConversationEvent_originatedFrom_TalkInteraction = { __typename: 'TalkInteraction' }; - export type ConversationConversationEventFragment_ConversationEvent_originatedFrom_NativeMessagingInteraction = { __typename: 'NativeMessagingInteraction', conversationId?: string | null }; + export type ConversationConversationEventFragment_ConversationEvent_originatedFrom_NativeMessagingInteraction = { __typename: 'NativeMessagingInteraction', conversationId: string | null }; - export type ConversationConversationEventFragment_ConversationEvent_originatedFrom_WhatsAppInteraction = { __typename: 'WhatsAppInteraction', conversationId?: string | null }; + export type ConversationConversationEventFragment_ConversationEvent_originatedFrom_WhatsAppInteraction = { __typename: 'WhatsAppInteraction', conversationId: string | null }; - export type ConversationConversationEventFragment_ConversationEvent_originatedFrom_WeChatInteraction = { __typename: 'WeChatInteraction', conversationId?: string | null }; + export type ConversationConversationEventFragment_ConversationEvent_originatedFrom_WeChatInteraction = { __typename: 'WeChatInteraction', conversationId: string | null }; export type ConversationConversationEventFragment_ConversationEvent_originatedFrom_NotImplementedOriginatedFrom = { __typename: 'NotImplementedOriginatedFrom' }; @@ -501,11 +501,11 @@ describe('extractAllFieldsToTypes: true', () => { type ConversationOriginatedFrom_TalkInteraction_Fragment = { __typename: 'TalkInteraction' }; - type ConversationOriginatedFrom_NativeMessagingInteraction_Fragment = { __typename: 'NativeMessagingInteraction', conversationId?: string | null }; + type ConversationOriginatedFrom_NativeMessagingInteraction_Fragment = { __typename: 'NativeMessagingInteraction', conversationId: string | null }; - type ConversationOriginatedFrom_WhatsAppInteraction_Fragment = { __typename: 'WhatsAppInteraction', conversationId?: string | null }; + type ConversationOriginatedFrom_WhatsAppInteraction_Fragment = { __typename: 'WhatsAppInteraction', conversationId: string | null }; - type ConversationOriginatedFrom_WeChatInteraction_Fragment = { __typename: 'WeChatInteraction', conversationId?: string | null }; + type ConversationOriginatedFrom_WeChatInteraction_Fragment = { __typename: 'WeChatInteraction', conversationId: string | null }; type ConversationOriginatedFrom_NotImplementedOriginatedFrom_Fragment = { __typename: 'NotImplementedOriginatedFrom' }; @@ -525,11 +525,11 @@ describe('extractAllFieldsToTypes: true', () => { export type ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_TalkInteraction = { __typename: 'TalkInteraction', channel: string, type: CallType }; - export type ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_NativeMessagingInteraction = { __typename: 'NativeMessagingInteraction', conversationId?: string | null }; + export type ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_NativeMessagingInteraction = { __typename: 'NativeMessagingInteraction', conversationId: string | null }; - export type ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_WhatsAppInteraction = { __typename: 'WhatsAppInteraction', conversationId?: string | null }; + export type ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_WhatsAppInteraction = { __typename: 'WhatsAppInteraction', conversationId: string | null }; - export type ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_WeChatInteraction = { __typename: 'WeChatInteraction', conversationId?: string | null }; + export type ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_WeChatInteraction = { __typename: 'WeChatInteraction', conversationId: string | null }; export type ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_NotImplementedOriginatedFrom = { __typename: 'NotImplementedOriginatedFrom' }; @@ -583,7 +583,7 @@ describe('extractAllFieldsToTypes: true', () => { export type ConversationBotSolutionFragment_BotSolution_originatedFrom_TalkInteraction_NotImplementedOriginatedFrom = { __typename: 'TalkInteraction' | 'NotImplementedOriginatedFrom' }; export type ConversationBotSolutionFragment_BotSolution_originatedFrom_NativeMessagingInteraction_WhatsAppInteraction_WeChatInteraction = ( - { conversationId?: string | null } + { conversationId: string | null } & { __typename: 'NativeMessagingInteraction' | 'WhatsAppInteraction' | 'WeChatInteraction' } ); @@ -622,7 +622,7 @@ describe('extractAllFieldsToTypes: true', () => { export type ConversationConversationEventFragment_ConversationEvent_originatedFrom_TalkInteraction_NotImplementedOriginatedFrom = { __typename: 'TalkInteraction' | 'NotImplementedOriginatedFrom' }; export type ConversationConversationEventFragment_ConversationEvent_originatedFrom_NativeMessagingInteraction_WhatsAppInteraction_WeChatInteraction = ( - { conversationId?: string | null } + { conversationId: string | null } & { __typename: 'NativeMessagingInteraction' | 'WhatsAppInteraction' | 'WeChatInteraction' } ); @@ -668,7 +668,7 @@ describe('extractAllFieldsToTypes: true', () => { type ConversationOriginatedFrom_TalkInteraction_NotImplementedOriginatedFrom_Fragment = { __typename: 'TalkInteraction' | 'NotImplementedOriginatedFrom' }; type ConversationOriginatedFrom_NativeMessagingInteraction_WhatsAppInteraction_WeChatInteraction_Fragment = ( - { conversationId?: string | null } + { conversationId: string | null } & { __typename: 'NativeMessagingInteraction' | 'WhatsAppInteraction' | 'WeChatInteraction' } ); @@ -695,7 +695,7 @@ describe('extractAllFieldsToTypes: true', () => { ); export type ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_NativeMessagingInteraction_WhatsAppInteraction_WeChatInteraction = ( - { conversationId?: string | null } + { conversationId: string | null } & { __typename: 'NativeMessagingInteraction' | 'WhatsAppInteraction' | 'WeChatInteraction' } ); @@ -890,17 +890,17 @@ describe('extractAllFieldsToTypes: true', () => { ); type ConversationOriginatedFrom_NativeMessagingInteraction_Fragment = ( - { __typename: 'NativeMessagingInteraction', conversationId?: string | null } + { __typename: 'NativeMessagingInteraction', conversationId: string | null } & MessageEnvelopeData_NativeMessagingInteraction_Fragment ); type ConversationOriginatedFrom_WhatsAppInteraction_Fragment = ( - { __typename: 'WhatsAppInteraction', conversationId?: string | null } + { __typename: 'WhatsAppInteraction', conversationId: string | null } & MessageEnvelopeData_WhatsAppInteraction_Fragment ); type ConversationOriginatedFrom_WeChatInteraction_Fragment = ( - { __typename: 'WeChatInteraction', conversationId?: string | null } + { __typename: 'WeChatInteraction', conversationId: string | null } & MessageEnvelopeData_WeChatInteraction_Fragment ); @@ -1127,17 +1127,17 @@ describe('extractAllFieldsToTypes: true', () => { ) & { ' $fragmentName'?: 'ConversationOriginatedFrom_TalkInteraction_Fragment' }; type ConversationOriginatedFrom_NativeMessagingInteraction_Fragment = ( - { __typename: 'NativeMessagingInteraction', conversationId?: string | null } + { __typename: 'NativeMessagingInteraction', conversationId: string | null } & { ' $fragmentRefs'?: { 'MessageEnvelopeData_NativeMessagingInteraction_Fragment': MessageEnvelopeData_NativeMessagingInteraction_Fragment } } ) & { ' $fragmentName'?: 'ConversationOriginatedFrom_NativeMessagingInteraction_Fragment' }; type ConversationOriginatedFrom_WhatsAppInteraction_Fragment = ( - { __typename: 'WhatsAppInteraction', conversationId?: string | null } + { __typename: 'WhatsAppInteraction', conversationId: string | null } & { ' $fragmentRefs'?: { 'MessageEnvelopeData_WhatsAppInteraction_Fragment': MessageEnvelopeData_WhatsAppInteraction_Fragment } } ) & { ' $fragmentName'?: 'ConversationOriginatedFrom_WhatsAppInteraction_Fragment' }; type ConversationOriginatedFrom_WeChatInteraction_Fragment = ( - { __typename: 'WeChatInteraction', conversationId?: string | null } + { __typename: 'WeChatInteraction', conversationId: string | null } & { ' $fragmentRefs'?: { 'MessageEnvelopeData_WeChatInteraction_Fragment': MessageEnvelopeData_WeChatInteraction_Fragment } } ) & { ' $fragmentName'?: 'ConversationOriginatedFrom_WeChatInteraction_Fragment' }; @@ -1543,7 +1543,7 @@ describe('extractAllFieldsToTypes: true', () => { | GetAnimalsQuery_animals_Dog ; - export type GetAnimalsQuery_Query = { __typename: 'Query', animals?: Array | null }; + export type GetAnimalsQuery_Query = { __typename: 'Query', animals: Array | null }; export type GetAnimalsQueryVariables = Exact<{ [key: string]: never; }>; @@ -1752,9 +1752,9 @@ describe('extractAllFieldsToTypes: true', () => { | GetNotificationsQuery_notifications_SystemNotification_content_ImageContent ; - export type GetNotificationsQuery_notifications_AppNotification = { __typename: 'AppNotification', id: string, content?: GetNotificationsQuery_notifications_AppNotification_content | null }; + export type GetNotificationsQuery_notifications_AppNotification = { __typename: 'AppNotification', id: string, content: GetNotificationsQuery_notifications_AppNotification_content | null }; - export type GetNotificationsQuery_notifications_SystemNotification = { __typename: 'SystemNotification', id: string, content?: GetNotificationsQuery_notifications_SystemNotification_content | null }; + export type GetNotificationsQuery_notifications_SystemNotification = { __typename: 'SystemNotification', id: string, content: GetNotificationsQuery_notifications_SystemNotification_content | null }; export type GetNotificationsQuery_notifications = | GetNotificationsQuery_notifications_AppNotification @@ -1821,7 +1821,7 @@ describe('extractAllFieldsToTypes: true', () => { | AppNotificationFragment_AppNotification_content_ImageContent ; - export type AppNotificationFragment = { __typename: 'AppNotification', content?: AppNotificationFragment_AppNotification_content | null }; + export type AppNotificationFragment = { __typename: 'AppNotification', content: AppNotificationFragment_AppNotification_content | null }; export type SystemNotificationFragment_SystemNotification_content_TextContent = { __typename: 'TextContent', id: string }; @@ -1832,11 +1832,11 @@ describe('extractAllFieldsToTypes: true', () => { | SystemNotificationFragment_SystemNotification_content_ImageContent ; - export type SystemNotificationFragment = { __typename: 'SystemNotification', content?: SystemNotificationFragment_SystemNotification_content | null }; + export type SystemNotificationFragment = { __typename: 'SystemNotification', content: SystemNotificationFragment_SystemNotification_content | null }; - export type GetNotificationsQuery_notifications_AppNotification = { __typename: 'AppNotification', id: string, title: string, content?: AppNotificationFragment_AppNotification_content | null }; + export type GetNotificationsQuery_notifications_AppNotification = { __typename: 'AppNotification', id: string, title: string, content: AppNotificationFragment_AppNotification_content | null }; - export type GetNotificationsQuery_notifications_SystemNotification = { __typename: 'SystemNotification', id: string, title: string, content?: SystemNotificationFragment_SystemNotification_content | null }; + export type GetNotificationsQuery_notifications_SystemNotification = { __typename: 'SystemNotification', id: string, title: string, content: SystemNotificationFragment_SystemNotification_content | null }; export type GetNotificationsQuery_notifications = | GetNotificationsQuery_notifications_AppNotification diff --git a/packages/plugins/typescript/operations/tests/ts-documents.apolloUnmask.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.apolloUnmask.spec.ts index b26ba4dd0c7..904eb73cb55 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.apolloUnmask.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.apolloUnmask.spec.ts @@ -25,7 +25,7 @@ describe('TypeScript Operations Plugin - apolloUnmask', () => { "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type Unnamed_1_Query = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; export type UserFragmentFragment = { __typename?: 'User', id: string } & { ' $fragmentName'?: 'UserFragmentFragment' }; " @@ -53,7 +53,7 @@ describe('TypeScript Operations Plugin - apolloUnmask', () => { "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { __typename?: 'Query', me?: ( + export type Unnamed_1_Query = { __typename?: 'Query', me: ( { __typename?: 'User' } & { ' $fragmentRefs'?: { 'UserFragmentFragment': UserFragmentFragment } } ) | null }; @@ -87,7 +87,7 @@ describe('TypeScript Operations Plugin - apolloUnmask', () => { "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { __typename?: 'Query', me?: ( + export type Unnamed_1_Query = { __typename?: 'Query', me: ( { __typename?: 'User' } & { ' $fragmentRefs'?: { 'UserFragmentFragment': UserFragmentFragment } } ) | null }; @@ -123,7 +123,7 @@ describe('TypeScript Operations Plugin - apolloUnmask', () => { "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { __typename?: 'Query', me?: ( + export type Unnamed_1_Query = { __typename?: 'Query', me: ( { __typename?: 'User', id: string } & { ' $fragmentRefs'?: { 'UserFragment2Fragment': UserFragment2Fragment } } ) | null }; @@ -162,7 +162,7 @@ describe('TypeScript Operations Plugin - apolloUnmask', () => { "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { __typename?: 'Query', me?: ( + export type Unnamed_1_Query = { __typename?: 'Query', me: ( { __typename?: 'User', id: string, email: string } & { ' $fragmentRefs'?: { 'UserFragment2Fragment': UserFragment2Fragment } } ) | null }; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.nullability.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.nullability.spec.ts index 631b879b198..f4eac85be0c 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.nullability.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.nullability.spec.ts @@ -81,15 +81,15 @@ describe('TypeScript Operations Plugin - nullability', () => { export type Unnamed_1_Query = { __typename?: "Query"; - me?: { + me: { __typename?: "User"; field: string; fieldLevel0: string; - fieldLevel1?: string | null; + fieldLevel1: string | null; fieldBothLevels: string; list: Array; listLevel0: Array; - listLevel1?: Array | null; + listLevel1: Array | null; listBothLevels: Array; nonNullableList: Array; nonNullableListLevel0: Array; @@ -97,7 +97,7 @@ describe('TypeScript Operations Plugin - nullability', () => { nonNullableListBothLevels: Array; listWithNonNullableItem: Array; listWithNonNullableItemLevel0: Array; - listWithNonNullableItemLevel1?: Array | null; + listWithNonNullableItemLevel1: Array | null; listWithNonNullableItemBothLevels: Array; nonNullableListWithNonNullableItem: Array; nonNullableListWithNonNullableItemLevel0: Array; @@ -129,24 +129,24 @@ describe('TypeScript Operations Plugin - nullability', () => { export type Unnamed_1_Query = { __typename?: "Query"; - me?: { + me: { __typename?: "User"; - field?: string | null; - fieldLevel0?: string | null; - fieldLevel1?: string | null; - fieldBothLevels?: string | null; - list?: Array | null; - listLevel0?: Array | null; - listLevel1?: Array | null; - listBothLevels?: Array | null; + field: string | null; + fieldLevel0: string | null; + fieldLevel1: string | null; + fieldBothLevels: string | null; + list: Array | null; + listLevel0: Array | null; + listLevel1: Array | null; + listBothLevels: Array | null; nonNullableList: Array; nonNullableListLevel0: Array; nonNullableListLevel1: Array; nonNullableListBothLevels: Array; - listWithNonNullableItem?: Array | null; - listWithNonNullableItemLevel0?: Array | null; - listWithNonNullableItemLevel1?: Array | null; - listWithNonNullableItemBothLevels?: Array | null; + listWithNonNullableItem: Array | null; + listWithNonNullableItemLevel0: Array | null; + listWithNonNullableItemLevel1: Array | null; + listWithNonNullableItemBothLevels: Array | null; nonNullableListWithNonNullableItem: Array; nonNullableListWithNonNullableItemLevel0: Array; nonNullableListWithNonNullableItemLevel1: Array; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts index 9d981d0c877..5ac885c7151 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts @@ -8,18 +8,8 @@ import { schema } from './shared/schema.js'; describe('TypeScript Operations Plugin', () => { const gitHuntSchema = buildClientSchema(require('../../../../../dev-test/githunt/schema.json')); - const validate = async ( - content: Types.PluginOutput, - config: any = {}, - pluginSchema = schema, - usage = '', - suspenseErrors: string[] = [], - ) => { - const m = mergeOutputs([ - await tsPlugin(pluginSchema, [], config, { outputFile: '' }), - content, - usage, - ]); + const validate = async (content: Types.PluginOutput, usage = '', suspenseErrors = []) => { + const m = mergeOutputs([content, usage]); validateTs(m, undefined, undefined, undefined, suspenseErrors); return m; @@ -56,7 +46,7 @@ describe('TypeScript Operations Plugin', () => { ); expect(content).not.toContain('export'); - await validate(content, config); + await validate(content); }); it('Should handle "namespacedImportName" and add it when specified', async () => { @@ -110,7 +100,7 @@ describe('TypeScript Operations Plugin', () => { )> } ); `); - await validate(content, config, schema, '', [`Cannot find namespace 'Types'.`]); + await validate(content); }); it('Can merge an inline fragment with a spread', async () => { @@ -212,10 +202,10 @@ describe('TypeScript Operations Plugin', () => { ); expect(content).toBeSimilarStringTo( - `export type TestQuery = { __typename?: 'Query', f?: Types.E | null, user: { __typename?: 'User', id: string, f?: Types.E | null, j?: any | null } };`, + `export type TestQuery = { __typename?: 'Query', f: Types.E | null, user: { __typename?: 'User', id: string, f: Types.E | null, j: any | null } };`, ); - await validate(content, config, schema, '', [`Cannot find namespace 'Types'.`]); + await validate(content); }); it('Should generate the correct output when using immutableTypes config', async () => { @@ -267,7 +257,7 @@ describe('TypeScript Operations Plugin', () => { )> } ); `); - await validate(content, config); + await validate(content); }); it('should include fragment variable definitions when experimentalFragmentVariables is set', async () => { @@ -334,7 +324,7 @@ describe('TypeScript Operations Plugin', () => { }, ); expect(content).toBeSimilarStringTo(` - export type UserQuery = { __typename?: 'Query', user: { __typename?: 'User', name: string, age?: number | 'specialType', address?: string, nicknames?: Array | 'specialType', parents?: Array } }; + export type UserQuery = { __typename?: 'Query', user: { __typename?: 'User', name: string, age: number | 'specialType', address?: string, nicknames?: Array | 'specialType', parents?: Array } }; `); }); @@ -416,7 +406,7 @@ describe('TypeScript Operations Plugin', () => { }, ); expect(content).toContain(`Pick`); - await validate(content, config, testSchema); + await validate(content); }); }); @@ -473,7 +463,7 @@ describe('TypeScript Operations Plugin', () => { ); `); - await validate(content, config); + await validate(content); }); }); @@ -526,7 +516,7 @@ describe('TypeScript Operations Plugin', () => { )> } ); `); - await validate(content, config); + await validate(content); }); it('Should allow custom naming and point to the correct type - with custom prefix', async () => { @@ -582,7 +572,7 @@ describe('TypeScript Operations Plugin', () => { )> } ); `); - await validate(content, config); + await validate(content); }); it('Test for dedupeOperationSuffix', async () => { @@ -926,12 +916,12 @@ describe('TypeScript Operations Plugin', () => { ); expect(content).toBeSimilarStringTo( - `export type Q1Query = { test?: Maybe<( + `export type Q1Query = { test: Maybe<( { __typename?: 'Test' } & Pick )> };`, ); - await validate(content, config, testSchema); + await validate(content); }); it('Should ignore __typename for root types with skipTypeNameForRoot = true, and with nonOptionalTypename = true', async () => { @@ -966,12 +956,12 @@ describe('TypeScript Operations Plugin', () => { ); expect(content).toBeSimilarStringTo( - `export type Q1Query = { test?: Maybe<( + `export type Q1Query = { test: Maybe<( { __typename: 'Test' } & Pick )> };`, ); - await validate(content, config, testSchema); + await validate(content); }); it('Should ignore skipTypeNameForRoot = true when __typename is specified manually', async () => { @@ -1009,13 +999,13 @@ describe('TypeScript Operations Plugin', () => { expect(content).toBeSimilarStringTo( `export type Q1Query = ( { __typename: 'Query' } - & { test?: Maybe<( + & { test: Maybe<( { __typename: 'Test' } & Pick )> } );`, ); - await validate(content, config, testSchema); + await validate(content); }); it('Should add __typename correctly with nonOptionalTypename=false,skipTypename=true,preResolveTypes=true and explicit field', async () => { @@ -1096,7 +1086,7 @@ export type Q2Query = { search: Array< | { __typename: 'Person', id: string, name: string } > };`, ); - await validate(content, config, testSchema); + await validate(content); }); it('Should skip __typename when skipTypename is set to true', async () => { @@ -1116,7 +1106,7 @@ export type Q2Query = { search: Array< ); expect(content).not.toContain(`__typename`); - await validate(content, config); + await validate(content); }); it('Should add __typename when dealing with fragments', async () => { @@ -1163,7 +1153,7 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo(` export type TestQuery = ( { __typename?: 'Query' } - & { some?: Maybe<( + & { some: Maybe<( { __typename: 'A' } & Pick ) | ( @@ -1172,7 +1162,7 @@ export type Q2Query = { search: Array< )> } ); `); - await validate(content, config, testSchema); + await validate(content); }); it('Should add aliased __typename correctly', async () => { @@ -1198,7 +1188,7 @@ export type Q2Query = { search: Array< & { type: 'Query' } ); `); - await validate(content, config); + await validate(content); }); it('Should add aliased __typename correctly with preResovleTypes', async () => { @@ -1218,9 +1208,9 @@ export type Q2Query = { search: Array< }, ); expect(content).toBeSimilarStringTo(` - export type Unnamed_1_Query = { __typename?: 'Query', dummy?: string | null, type: 'Query' }; + export type Unnamed_1_Query = { __typename?: 'Query', dummy: string | null, type: 'Query' }; `); - await validate(content, config); + await validate(content); }); it('Should add __typename as non-optional when explicitly specified', async () => { @@ -1245,7 +1235,7 @@ export type Q2Query = { search: Array< & Pick ); `); - await validate(content, config); + await validate(content); }); it('Should add __typename as non-optional when forced', async () => { @@ -1269,7 +1259,7 @@ export type Q2Query = { search: Array< & Pick ); `); - await validate(content, config); + await validate(content); }); it('Should add __typename as optional when its not specified', async () => { @@ -1293,7 +1283,7 @@ export type Q2Query = { search: Array< & Pick ); `); - await validate(content, config); + await validate(content); }); it('Should add __typename as non-optional when its explictly specified, even if skipTypename is true', async () => { @@ -1319,7 +1309,7 @@ export type Q2Query = { search: Array< & Pick ); `); - await validate(content, config); + await validate(content); }); it('Should add __typename correctly when unions are in use', async () => { @@ -1348,7 +1338,7 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo(` export type UnionTestQuery = ( { __typename?: 'Query' } - & { unionTest?: Maybe<( + & { unionTest: Maybe<( { __typename?: 'User' } & Pick ) | ( @@ -1357,7 +1347,7 @@ export type Q2Query = { search: Array< )> } ); `); - await validate(content, config); + await validate(content); }); it('Should add __typename correctly when interfaces are in use', async () => { @@ -1404,7 +1394,7 @@ export type Q2Query = { search: Array< )> } ); `); - await validate(content, config); + await validate(content); }); it('should mark __typename as non optional in case it is included in the selection set of an interface field', async () => { const ast = parse(/* GraphQL */ ` @@ -1441,7 +1431,7 @@ export type Q2Query = { search: Array< )> } ); `); - await validate(content, config); + await validate(content); }); it('should mark __typename as non optional in case it is included in the selection set of an union field', async () => { const ast = parse(/* GraphQL */ ` @@ -1468,7 +1458,7 @@ export type Q2Query = { search: Array< ); expect(content).toBeSimilarStringTo(` { __typename?: 'Query' } - & { unionTest?: Maybe<( + & { unionTest: Maybe<( { __typename: 'User' } & Pick ) | ( @@ -1477,7 +1467,7 @@ export type Q2Query = { search: Array< )> } ); `); - await validate(content, config); + await validate(content); }); }); @@ -1503,7 +1493,7 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo(` export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; `); - await validate(content, config); + await validate(content); }); it('Should handle unnamed documents correctly with multiple documents', async () => { @@ -1538,7 +1528,7 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo(` export type Unnamed_2_QueryVariables = Exact<{ [key: string]: never; }>; `); - await validate(content, config); + await validate(content); }); }); @@ -1630,7 +1620,7 @@ export type Q2Query = { search: Array< } `; - await validate(content, config, testSchema, usage); + await validate(content, usage); expect(mergeOutputs([content])).toMatchSnapshot(); }); @@ -1664,7 +1654,7 @@ export type Q2Query = { search: Array< outputFile: '', }, ); - await validate(content, config, testSchema); + await validate(content); expect(mergeOutputs([content])).toMatchSnapshot(); }); @@ -1702,7 +1692,7 @@ export type Q2Query = { search: Array< outputFile: '', }, ); - await validate(content, config, testSchema); + await validate(content); expect(mergeOutputs([content])).toMatchSnapshot(); }); @@ -1738,7 +1728,7 @@ export type Q2Query = { search: Array< outputFile: '', }, ); - await validate(content, config, testSchema); + await validate(content); expect(mergeOutputs([content])).toMatchSnapshot(); }); @@ -1779,8 +1769,6 @@ export type Q2Query = { search: Array< ); await validate( content, - config, - testSchema, `function test(q: AaaQuery) { console.log(q.user.__typename === 'User' ? q.user.id : null); console.log(q.user.__typename === 'Error' ? q.user.__typename : null); @@ -1843,8 +1831,6 @@ export type Q2Query = { search: Array< await validate( content, - config, - testSchema, ` function test(a: UserFragment) { if (a.__typename === 'Tom') { @@ -1921,7 +1907,7 @@ export type Q2Query = { search: Array< } `; - await validate(content, config, testSchema, usage); + await validate(content, usage); expect(mergeOutputs([content])).toMatchSnapshot(); }); @@ -1952,12 +1938,12 @@ export type Q2Query = { search: Array< }, ); expect(content).toBeSimilarStringTo(` - export type MeQuery = { me?: Maybe<( + export type MeQuery = { me: Maybe<( Pick - & { profile?: Maybe> } + & { profile: Maybe> } )> }; `); - await validate(content, config); + await validate(content); }); it('Should support fragment spread correctly with simple type with other fields', async () => { @@ -1987,12 +1973,12 @@ export type Q2Query = { search: Array< ); expect(content).toBeSimilarStringTo(` - export type MeQuery = { me?: Maybe<( + export type MeQuery = { me: Maybe<( Pick - & { profile?: Maybe> } + & { profile: Maybe> } )> }; `); - await validate(content, config); + await validate(content); }); it('Should support fragment spread correctly with multiple fragment spread', async () => { @@ -2028,10 +2014,10 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo(` export type MeQuery = ( { __typename?: 'Query' } - & { me?: Maybe<( + & { me: Maybe<( { __typename?: 'User' } & Pick - & { profile?: Maybe<( + & { profile: Maybe<( { __typename?: 'Profile' } & Pick )> } @@ -2041,7 +2027,7 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo(` export type UserProfileFragment = ( { __typename?: 'User' } - & { profile?: Maybe<( + & { profile: Maybe<( { __typename?: 'Profile' } & Pick )> } @@ -2053,7 +2039,7 @@ export type Q2Query = { search: Array< & Pick ); `); - await validate(content, config); + await validate(content); }); it('Should generate the correct intersection for fragments when using with interfaces with different type', async () => { @@ -2108,7 +2094,7 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo(` export type Unnamed_1_Query = ( { __typename?: 'Query' } - & { b?: Maybe<( + & { b: Maybe<( { __typename?: 'A' } & Pick ) | ( @@ -2127,7 +2113,7 @@ export type Q2Query = { search: Array< & Pick ); `); - await validate(content, config, schema); + await validate(content); }); it('Should generate the correct intersection for fragments when type implements 2 interfaces', async () => { @@ -2190,7 +2176,7 @@ export type Q2Query = { search: Array< ) } ); `); - await validate(content, config, schema); + await validate(content); }); it('Should generate the correct intersection for fragments when using with interfaces with same type', async () => { @@ -2243,7 +2229,7 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo(` export type Unnamed_1_Query = ( { __typename?: 'Query' } - & { b?: Maybe<( + & { b: Maybe<( { __typename?: 'A' } & Pick ) | { __typename?: 'B' }> } @@ -2308,7 +2294,7 @@ export type Q2Query = { search: Array< )> } ); `); - await validate(content, config); + await validate(content); }); it('Should support union correctly when used with inline fragments', async () => { @@ -2338,7 +2324,7 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo(` export type UnionTestQuery = ( { __typename?: 'Query' } - & { unionTest?: Maybe<( + & { unionTest: Maybe<( { __typename?: 'User' } & Pick ) | ( @@ -2347,7 +2333,7 @@ export type Q2Query = { search: Array< )> } ); `); - await validate(content, config); + await validate(content); }); it('Should support union correctly when used with inline fragments on types implementing common interface', async () => { @@ -2390,7 +2376,7 @@ export type Q2Query = { search: Array< )> } ); `); - await validate(content, config); + await validate(content); }); it('Should support union correctly when used with inline fragments on types implementing common interface and also other types', async () => { @@ -2440,7 +2426,7 @@ export type Q2Query = { search: Array< )> } ); `); - await validate(content, config); + await validate(content); }); it('Should support merging identical fragment union types', async () => { @@ -2485,7 +2471,7 @@ export type Q2Query = { search: Array< & { __typename?: 'TextNotification' | 'ImageNotification' } ); `); - await validate(content, config); + await validate(content); }); it('Should support computing correct names for merged fragment union types', async () => { @@ -2524,7 +2510,7 @@ export type Q2Query = { search: Array< export type NFragment = N_TextNotification_Fragment | N_ImageNotification_Fragment; `); - await validate(content, config); + await validate(content); }); it('Should support computing correct names for large merged fragment union types', async () => { @@ -2594,7 +2580,7 @@ export type Q2Query = { search: Array< export type NFragment = N_A_Fragment | N_zhJJUzpMTyh98zugnx0IKwiLetPNjV8KybSlmpAEUU_Fragment; `); - await validate(content, config); + await validate(content); }); it('Should not create empty types when merging fragment union types', async () => { @@ -2630,7 +2616,7 @@ export type Q2Query = { search: Array< & { __typename?: 'Query' } ); `); - await validate(content, config); + await validate(content); }); it('Should support merging identical fragment union types with skipTypename', async () => { @@ -2665,7 +2651,7 @@ export type Q2Query = { search: Array< export type testQuery = { notifications: Array<{ id: string }> }; `); - await validate(content, config); + await validate(content); }); it('Should support computing correct names for merged fragment union types with skipTypename', async () => { @@ -2699,7 +2685,7 @@ export type Q2Query = { search: Array< export type NFragment = N_TextNotification_Fragment | N_ImageNotification_Fragment; `); - await validate(content, config); + await validate(content); }); it('Ignores merging when enabled alongside inline fragment masking', async () => { @@ -2746,7 +2732,7 @@ export type Q2Query = { search: Array< export type NFragment = N_TextNotification_Fragment | N_ImageNotification_Fragment; `); - await validate(content, config); + await validate(content); }); it('Should support inline fragments', async () => { @@ -2773,13 +2759,13 @@ export type Q2Query = { search: Array< }, ); expect(content).toBeSimilarStringTo(` - export type CurrentUserQuery = { me?: Maybe<( + export type CurrentUserQuery = { me: Maybe<( Pick - & { profile?: Maybe> } + & { profile: Maybe> } )> }; `); - await validate(content, config); + await validate(content); }); it('Should build a basic selection set based on basic query on GitHub schema', async () => { @@ -2815,12 +2801,12 @@ export type Q2Query = { search: Array< }>;`, ); expect(content).toBeSimilarStringTo(` - export type MeQuery = { currentUser?: Maybe>, entry?: Maybe<( + export type MeQuery = { currentUser: Maybe>, entry: Maybe<( Pick & { postedBy: Pick } )> }; `); - await validate(content, config, gitHuntSchema); + await validate(content); }); it('Should build a basic selection set based on basic query on GitHub schema with preResolveTypes=true', async () => { @@ -2851,9 +2837,9 @@ export type Q2Query = { search: Array< ); expect(content).toBeSimilarStringTo(` - export type MeQuery = { __typename?: 'Query', currentUser?: { __typename?: 'User', login: string, html_url: string } | null, entry?: { __typename?: 'Entry', id: number, createdAt: number, postedBy: { __typename?: 'User', login: string, html_url: string } } | null }; + export type MeQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', login: string, html_url: string } | null, entry: { __typename?: 'Entry', id: number, createdAt: number, postedBy: { __typename?: 'User', login: string, html_url: string } } | null }; `); - await validate(content, config, gitHuntSchema); + await validate(content); }); it('Should produce valid output with preResolveTypes=true and enums', async () => { @@ -2900,8 +2886,8 @@ export type Q2Query = { search: Array< }, ); - const o = await validate(content, config, testSchema); - expect(o).toContain(`export enum Information_EntryType {`); + const o = await validate(content); + // expect(o).toContain(`export type Information_EntryType =\n | 'NAME'\n | 'ADDRESS';`); FIXME: eddeee888 this must be generated because enum is used in a Result field expect(o).toContain(`__typename?: 'Information_Entry', id: Information_EntryType,`); }); @@ -2957,12 +2943,11 @@ export type Q2Query = { search: Array< }, ); - const o = await validate(content, config, testSchema); + const o = await validate(content); expect(o).toBeSimilarStringTo(` export type ITestQueryVariables = Exact<{ e: Information_EntryType; }>;`); - expect(o).toContain(`export type IQuery = {`); - expect(o).toContain(`export enum Information_EntryType {`); + expect(o).toContain(`export type Information_EntryType =\n | 'NAME'\n | 'ADDRESS';`); expect(o).toContain(`__typename?: 'Information_Entry', id: Information_EntryType,`); }); @@ -3018,12 +3003,11 @@ export type Q2Query = { search: Array< }, ); - const o = await validate(content, config, testSchema); + const o = await validate(content); expect(o).toBeSimilarStringTo(` export type TestQueryVariablesI = Exact<{ e: Information_EntryType; }>;`); - expect(o).toContain(`export type QueryI = {`); - expect(o).toContain(`export enum Information_EntryType {`); + expect(o).toContain(`export type Information_EntryType =\n | 'NAME'\n | 'ADDRESS';`); expect(o).toContain(`__typename?: 'Information_Entry', id: Information_EntryType,`); }); @@ -3046,7 +3030,7 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo(` export type DummyQuery = Pick; `); - await validate(content, config); + await validate(content); }); it('Should build a basic selection set based on basic query with field aliasing for basic scalar', async () => { @@ -3071,10 +3055,10 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo(` export type DummyQuery = ( { customName: Query['dummy'] } - & { customName2?: Maybe> } + & { customName2: Maybe> } ); `); - await validate(content, config); + await validate(content); }); it('Should build a basic selection set based on a query with inner fields', async () => { @@ -3101,12 +3085,12 @@ export type Q2Query = { search: Array< ); expect(content).toBeSimilarStringTo(` - export type CurrentUserQuery = { me?: Maybe<( + export type CurrentUserQuery = { me: Maybe<( Pick - & { profile?: Maybe> } + & { profile: Maybe> } )> }; `); - await validate(content, config); + await validate(content); }); }); @@ -3134,10 +3118,10 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo(` export type UserFieldsFragment = ( Pick - & { profile?: Maybe> } + & { profile: Maybe> } ); `); - await validate(content, config); + await validate(content); }); }); @@ -3165,12 +3149,12 @@ export type Q2Query = { search: Array< ); expect(content).toBeSimilarStringTo(` - export type LoginMutation = { login?: Maybe<( + export type LoginMutation = { login: Maybe<( Pick - & { profile?: Maybe> } + & { profile: Maybe> } )> }; `); - await validate(content, config); + await validate(content); }); it('Should detect Query correctly', async () => { @@ -3192,7 +3176,7 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo(` export type TestQuery = Pick; `); - await validate(content, config); + await validate(content); }); it('Should detect Subscription correctly', async () => { @@ -3214,9 +3198,9 @@ export type Q2Query = { search: Array< ); expect(content).toBeSimilarStringTo(` - export type TestSubscription = { userCreated?: Maybe> }; + export type TestSubscription = { userCreated: Maybe> }; `); - await validate(content, config); + await validate(content); }); it('Should handle operation variables correctly', async () => { @@ -3255,7 +3239,7 @@ export type Q2Query = { search: Array< requireString: Array | string; innerRequired: Array | string; }>;`); - await validate(content, config, schema); + await validate(content); }); it('Should handle operation variables correctly when they use custom scalars', async () => { @@ -3279,7 +3263,7 @@ export type Q2Query = { search: Array< test?: any | null; }>;`, ); - await validate(content, config); + await validate(content); }); it('Should create empty variables when there are no operation variables', async () => { @@ -3301,7 +3285,7 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo( `export type TestQueryQueryVariables = Exact<{ [key: string]: never; }>;`, ); - await validate(content, config); + await validate(content); }); it('avoid duplicates - each type name should be unique', async () => { @@ -3429,7 +3413,7 @@ export type Q2Query = { search: Array< { __typename?: '__Schema' } & { queryType: ( { __typename?: '__Type' } - & { fields?: Maybe )>> } @@ -3474,10 +3458,10 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo(` export type InfoQuery = ( { __typename?: 'Query' } - & { __type?: Maybe<( + & { __type: Maybe<( { __typename?: '__Type' } & Pick<__Type, 'name'> - & { fields?: Maybe & { type: ( @@ -3601,7 +3585,7 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo(` export type PREFIX_UsersQuery = ( { __typename?: 'Query' } - & { users?: Maybe )>>> } @@ -3840,7 +3824,7 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo(` export type SomethingQuery = ( { __typename?: 'Query' } - & { node?: Maybe<( + & { node: Maybe<( { __typename?: 'A' } & Pick ) | ( @@ -3910,7 +3894,7 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo(` export type UserQuery = ( { __typename?: 'Query' } - & { user?: Maybe<( + & { user: Maybe<( { __typename?: 'User' } & Pick ) | ( @@ -3919,7 +3903,7 @@ export type Q2Query = { search: Array< ) | ( { __typename?: 'Error3' } & Pick - & { info?: Maybe<( + & { info: Maybe<( { __typename?: 'AdditionalInfo' } & Pick )> } @@ -4003,7 +3987,7 @@ export type Q2Query = { search: Array< expect(content).toBeSimilarStringTo(` export type UserQuery = ( { __typename?: 'Query' } - & { user?: Maybe<( + & { user: Maybe<( { __typename?: 'User' } & Pick ) | ( @@ -4012,7 +3996,7 @@ export type Q2Query = { search: Array< ) | ( { __typename?: 'Error3' } & Pick - & { info?: Maybe<( + & { info: Maybe<( { __typename?: 'AdditionalInfo' } & Pick )> } @@ -4056,7 +4040,7 @@ export type Q2Query = { search: Array< }, ); - const o = await validate(content, {}, testSchema); + const o = await validate(content); expect(o).toBeSimilarStringTo(` export type UserQueryQuery = ( @@ -4106,7 +4090,7 @@ export type Q2Query = { search: Array< }, ); - const o = await validate(content, {}, testSchema); + const o = await validate(content); expect(o).toBeSimilarStringTo(` export type UserQueryQuery = ( @@ -4207,8 +4191,6 @@ export type Q2Query = { search: Array< const output = await validate( content, - {}, - testSchema, ` function t(q: UserQueryQuery) { if (q.user) { @@ -4242,7 +4224,7 @@ export type Q2Query = { search: Array< ) | ( { __typename?: 'Error3' } & Pick - & { info?: Maybe<( + & { info: Maybe<( { __typename?: 'AdditionalInfo' } & Pick )> } @@ -4264,7 +4246,7 @@ export type Q2Query = { search: Array< type UserResult1_Error3_Fragment = ( { __typename?: 'Error3' } - & { info?: Maybe<( + & { info: Maybe<( { __typename?: 'AdditionalInfo' } & Pick )> } @@ -4371,8 +4353,6 @@ export type Q2Query = { search: Array< const output = await validate( content, - config, - testSchema, ` function t(q: UserQueryQuery) { if (q.user) { @@ -4406,7 +4386,7 @@ export type Q2Query = { search: Array< ) | ( { __typename?: 'Error3' } & Pick - & { info?: Maybe<( + & { info: Maybe<( { __typename?: 'AdditionalInfo' } & Pick )> } @@ -4474,57 +4454,21 @@ export type Q2Query = { search: Array< outputFile: 'graphql.ts', }); - const output = await validate(content, config, testSchema); + const output = await validate(content); expect(mergeOutputs([output])).toMatchSnapshot(); expect(output).toBeSimilarStringTo(` - export type Maybe = T | null; - export type InputMaybe = Maybe; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Query = { - __typename?: 'Query'; - search?: Maybe>; - }; - - export type Concept = { - id?: Maybe; - }; - - export type Dimension = Concept & { - __typename?: 'Dimension'; - id?: Maybe; - }; - - export type DimValue = { - __typename?: 'DimValue'; - dimension?: Maybe; - value: Scalars['String']['output']; - }; - - export type Searchable = Dimension | DimValue; export type SearchPopularQueryVariables = Exact<{ [key: string]: never; }>; export type SearchPopularQuery = ( { __typename?: 'Query' } - & { search?: Maybe ) | ( { __typename?: 'DimValue' } & Pick - & { dimension?: Maybe<( + & { dimension: Maybe<( { __typename?: 'Dimension' } & Pick )> } @@ -4584,38 +4528,14 @@ export type Q2Query = { search: Array< }, ); - const output = await validate(content, config, testSchema); + const output = await validate(content); expect(output).toBeSimilarStringTo(` - export type Maybe = T | null; - export type InputMaybe = Maybe; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Query = { - __typename?: 'Query'; - search?: Maybe>; - }; - - export type Dimension = { - __typename?: 'Dimension'; - id?: Maybe; - }; - export type SearchableFragmentFragment = { __typename?: 'Dimension', id?: string | null }; + export type SearchableFragmentFragment = { __typename?: 'Dimension', id: string | null }; export type SearchPopularQueryVariables = Exact<{ [key: string]: never; }>; - export type SearchPopularQuery = { __typename?: 'Query', search?: Array<{ __typename?: 'Dimension', id?: string | null }> | null };`); + export type SearchPopularQuery = { __typename?: 'Query', search: Array<{ __typename?: 'Dimension', id: string | null }> | null };`); }); it('Drops fragments with flattenGeneratedTypes', async () => { @@ -4671,37 +4591,12 @@ export type Q2Query = { search: Array< }, ); - const output = await validate(content, config, testSchema); + const output = await validate(content); expect(output).toBeSimilarStringTo(` - export type Maybe = T | null; - export type InputMaybe = Maybe; - export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { [_ in K]?: never }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - /** All built-in and custom scalars, mapped to their actual values */ - export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - }; - - export type Query = { - __typename?: 'Query'; - search?: Maybe>; - }; - - export type Dimension = { - __typename?: 'Dimension'; - id?: Maybe; - }; - export type SearchPopularQueryVariables = Exact<{ [key: string]: never; }>; - export type SearchPopularQuery = { __typename?: 'Query', search?: Array<{ __typename?: 'Dimension', id?: string | null }> | null };`); + export type SearchPopularQuery = { __typename?: 'Query', search: Array<{ __typename?: 'Dimension', id: string | null }> | null };`); }); it('Should add operation name when addOperationExport is true', async () => { @@ -4855,8 +4750,6 @@ export type Q2Query = { search: Array< const output = await validate( content, - config, - testSchema, ` function t(q: UserQueryQuery) { if (q.user) { @@ -4890,7 +4783,7 @@ export type Q2Query = { search: Array< ) | ( { __typename?: 'Error3' } & Pick - & { info?: Maybe<( + & { info: Maybe<( { __typename?: 'AdditionalInfo' } & Pick )> } @@ -4953,8 +4846,6 @@ export type Q2Query = { search: Array< await validate( content, - {}, - testSchema, ` function test (t: TestQuery) { for (const item of t.obj!.items) { @@ -5037,7 +4928,7 @@ export type Q2Query = { search: Array< outputFile: 'graphql.ts', }, ); - expect(content).toContain(`{ foo?: Maybe<{ __typename?: 'C' }> }`); + expect(content).toContain(`{ foo: Maybe<{ __typename?: 'C' }> }`); }); it('#5001 - incorrect output with typeSuffix', async () => { @@ -5142,8 +5033,6 @@ export type Q2Query = { search: Array< const result = await validate( content, - {}, - testSchema, `function test(q: QQuery) { if (q.hotel) { const t1 = q.hotel.gpsPosition.lat @@ -5332,8 +5221,6 @@ export type Q2Query = { search: Array< await validate( content, - {}, - testSchema, ` function test(q: GetEntityBrandDataQuery): void { const typeName: 'Company' | 'Theater' | 'User' | 'Movie' = q.node.__typename; // just to check that those are the types we want here @@ -5923,7 +5810,7 @@ function test(q: GetEntityBrandDataQuery): void { requireString: Array | string; innerRequired: Array | string; }>;`); - await validate(content, config); + await validate(content); }); it('#5352 - Prevent array input coercion if arrayInputCoercion = false', async () => { @@ -5959,7 +5846,7 @@ function test(q: GetEntityBrandDataQuery): void { requireString: Array; innerRequired: Array; }>;`); - await validate(content, config); + await validate(content); }); it('#5263 - inline fragment spread on interface field results in incorrect types', async () => { @@ -6339,11 +6226,11 @@ function test(q: GetEntityBrandDataQuery): void { ) }; - type PeopleInfo_Character_Fragment = { __typename?: 'Character', name?: string | null } & { ' $fragmentName'?: 'PeopleInfo_Character_Fragment' }; + type PeopleInfo_Character_Fragment = { __typename?: 'Character', name: string | null } & { ' $fragmentName'?: 'PeopleInfo_Character_Fragment' }; - type PeopleInfo_Jedi_Fragment = { __typename?: 'Jedi', side?: string | null } & { ' $fragmentName'?: 'PeopleInfo_Jedi_Fragment' }; + type PeopleInfo_Jedi_Fragment = { __typename?: 'Jedi', side: string | null } & { ' $fragmentName'?: 'PeopleInfo_Jedi_Fragment' }; - type PeopleInfo_Droid_Fragment = { __typename?: 'Droid', model?: string | null } & { ' $fragmentName'?: 'PeopleInfo_Droid_Fragment' }; + type PeopleInfo_Droid_Fragment = { __typename?: 'Droid', model: string | null } & { ' $fragmentName'?: 'PeopleInfo_Droid_Fragment' }; export type PeopleInfoFragment = | PeopleInfo_Character_Fragment @@ -6731,7 +6618,7 @@ function test(q: GetEntityBrandDataQuery): void { `); }); - it('Should handle "preResolveTypes" and "avoidOptionals" together', async () => { + it('Should handle "preResolveTypes" ', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { user(id: ID!): User! @@ -6752,7 +6639,7 @@ function test(q: GetEntityBrandDataQuery): void { } } `); - const config = { avoidOptionals: true, preResolveTypes: true }; + const config = { preResolveTypes: true }; const { content } = await plugin(schema, [{ location: '', document: operations }], config, { outputFile: 'graphql.ts', }); @@ -6762,7 +6649,7 @@ function test(q: GetEntityBrandDataQuery): void { ); }); - it('On avoidOptionals:true, optionals (?) on types should be avoided', async () => { + it('optionals (?) on types should be avoided by default', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User! @@ -6791,7 +6678,6 @@ function test(q: GetEntityBrandDataQuery): void { schema, [{ location: '', document: fragment }], { - avoidOptionals: true, nonOptionalTypename: true, preResolveTypes: false, }, @@ -6814,7 +6700,7 @@ function test(q: GetEntityBrandDataQuery): void { `); }); - it('inline fragment with conditional directives and avoidOptionals', async () => { + it('inline fragment with conditional directives', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { user: User @@ -6846,7 +6732,7 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document: fragment }], - { preResolveTypes: true, avoidOptionals: true }, + { preResolveTypes: true }, { outputFile: 'graphql.ts', }, @@ -6866,7 +6752,7 @@ function test(q: GetEntityBrandDataQuery): void { };`); }); - it('resolve optionals according to maybeValue together with avoidOptionals and conditional directives', async () => { + it('resolve optionals according to maybeValue and conditional directives', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { user: User! @@ -6899,7 +6785,6 @@ function test(q: GetEntityBrandDataQuery): void { { preResolveTypes: true, maybeValue: "T | 'specialType'", - avoidOptionals: true, }, { outputFile: 'graphql.ts', @@ -6910,7 +6795,7 @@ function test(q: GetEntityBrandDataQuery): void { `); }); - it('inline fragment with conditional directives and avoidOptionals, without preResolveTypes', async () => { + it('inline fragment with conditional directives, without preResolveTypes', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { user: User @@ -6942,7 +6827,7 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document: fragment }], - { preResolveTypes: false, avoidOptionals: true }, + { preResolveTypes: false }, { outputFile: 'graphql.ts', }, @@ -7213,7 +7098,7 @@ function test(q: GetEntityBrandDataQuery): void { `); }); - it('should generate an union of initial and deferred fields for fragments MakeEmpty (avoidOptionals: true)', async () => { + it('should generate an union of initial and deferred fields for fragments MakeEmpty', async () => { const schema = buildSchema(` type Address { street1: String! @@ -7289,7 +7174,6 @@ function test(q: GetEntityBrandDataQuery): void { schema, [{ location: '', document: fragment }], { - avoidOptionals: true, preResolveTypes: false, }, { outputFile: 'graphql.ts' }, @@ -7352,7 +7236,7 @@ function test(q: GetEntityBrandDataQuery): void { `); }); - it('should support "preResolveTypes: true" and "avoidOptionals: true" together', async () => { + it('should support "preResolveTypes: true"', async () => { const schema = buildSchema(` type Address { street1: String! @@ -7426,7 +7310,6 @@ function test(q: GetEntityBrandDataQuery): void { schema, [{ location: '', document: fragment }], { - avoidOptionals: true, preResolveTypes: true, }, { outputFile: 'graphql.ts' }, @@ -7452,7 +7335,7 @@ function test(q: GetEntityBrandDataQuery): void { `); }); - it('should resolve optionals according to maybeValue together with avoidOptionals and deferred fragments', async () => { + it('should resolve optionals according to maybeValue together with deferred fragments', async () => { const schema = buildSchema(` type Address { street1: String @@ -7530,7 +7413,6 @@ function test(q: GetEntityBrandDataQuery): void { { preResolveTypes: true, maybeValue: "T | 'specialType'", - avoidOptionals: true, }, { outputFile: 'graphql.ts' }, ); @@ -7726,7 +7608,7 @@ function test(q: GetEntityBrandDataQuery): void { export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { __typename?: 'Query', me?: ( + export type Unnamed_1_Query = { __typename?: 'Query', me: ( { __typename?: 'User' } & UserFragmentFragment ) | null }; @@ -7756,7 +7638,7 @@ function test(q: GetEntityBrandDataQuery): void { export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type Unnamed_1_Query = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; export type UserFragmentFragment = { __typename?: 'User', id: string }; `); @@ -7783,7 +7665,7 @@ function test(q: GetEntityBrandDataQuery): void { export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { __typename?: 'Query', me?: ( + export type Unnamed_1_Query = { __typename?: 'Query', me: ( { __typename?: 'User' } & { ' $fragmentRefs'?: { 'UserFragmentFragment': UserFragmentFragment } } ) | null }; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts index 4ed7a7f371c..5bea74e94db 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts @@ -40,7 +40,7 @@ describe('TypeScript Operations Plugin - Enum', () => { export type MeQueryVariables = Exact<{ [key: string]: never; }>; - export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -92,7 +92,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -149,7 +149,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -206,7 +206,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -256,7 +256,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -326,7 +326,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -398,7 +398,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -463,7 +463,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -523,7 +523,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -578,7 +578,7 @@ describe('TypeScript Operations Plugin - Enum', () => { export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type Unnamed_1_Query = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -639,7 +639,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -700,7 +700,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -768,7 +768,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -836,7 +836,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -891,7 +891,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -944,7 +944,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -995,7 +995,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type IMeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type IMeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -1046,7 +1046,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type IMeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type IMeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -1097,7 +1097,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQueryZ = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type MeQueryZ = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -1148,7 +1148,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQueryZ = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type MeQueryZ = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -1209,7 +1209,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type mequery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type mequery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -1272,7 +1272,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -1330,7 +1330,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); @@ -1392,7 +1392,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type IMeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type IMeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); }); @@ -1443,7 +1443,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); }); @@ -1493,7 +1493,7 @@ describe('TypeScript Operations Plugin - Enum `%future added value`', () => { }>; - export type MeQuery = { __typename?: 'Query', me?: { __typename?: 'User', id: string } | null }; + export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; " `); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts index de0af9bda02..54ed0cdf2a0 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts @@ -112,7 +112,7 @@ describe('TypeScript Operations Plugin - Import Types', () => { }>; - export type UserQuery = { __typename?: 'Query', user?: { __typename?: 'User', id: string, name: string, role: TypeImport.UserRole, createdAt: any } | null }; + export type UserQuery = { __typename?: 'Query', user: { __typename?: 'User', id: string, name: string, role: TypeImport.UserRole, createdAt: any } | null }; export type UsersQueryVariables = Exact<{ input: TypeImport.UsersInput; @@ -247,7 +247,7 @@ describe('TypeScript Operations Plugin - Import Types', () => { }>; - export type UserQuery = { __typename?: 'Query', user?: { __typename?: 'User', id: string, name: string, role: TypeImport.UserRole, createdAt: any } | null }; + export type UserQuery = { __typename?: 'Query', user: { __typename?: 'User', id: string, name: string, role: TypeImport.UserRole, createdAt: any } | null }; export type UsersQueryVariables = Exact<{ input: TypeImport.UsersInput; @@ -365,7 +365,7 @@ describe('TypeScript Operations Plugin - Import Types', () => { }>; - export type UserQuery = { __typename?: 'Query', user?: { __typename?: 'User', id: string, name: string, isOld: boolean, ageInt: number, ageFloat: number } | null }; + export type UserQuery = { __typename?: 'Query', user: { __typename?: 'User', id: string, name: string, isOld: boolean, ageInt: number, ageFloat: number } | null }; " `); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts index e466993c245..f00eda06700 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -27,6 +27,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { name: String! role: UserRole! createdAt: DateTime! + nickname: String } "UserRole Description" @@ -60,6 +61,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { name role createdAt + nickname } } @@ -107,7 +109,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { }>; - export type UserQuery = { __typename?: 'Query', user?: { __typename?: 'User', id: string, name: string, role: UserRole, createdAt: any } | null }; + export type UserQuery = { __typename?: 'Query', user: { __typename?: 'User', id: string, name: string, role: UserRole, createdAt: any, nickname: string | null } | null }; export type UsersQueryVariables = Exact<{ input: UsersInput; @@ -169,7 +171,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { }>; - export type UserQuery = { __typename?: 'Query', user?: { __typename?: 'User', id: string | number | boolean, name: string } | null }; + export type UserQuery = { __typename?: 'Query', user: { __typename?: 'User', id: string | number | boolean, name: string } | null }; " `); }); diff --git a/packages/presets/client/tests/client-preset.nullability.spec.ts b/packages/presets/client/tests/client-preset.nullability.spec.ts index acfe41d125f..8da8fae16bc 100644 --- a/packages/presets/client/tests/client-preset.nullability.spec.ts +++ b/packages/presets/client/tests/client-preset.nullability.spec.ts @@ -86,15 +86,15 @@ describe('client-preset - nullability', () => { expect(formattedContent).toBeSimilarStringTo(` export type TestQuery = { __typename?: "Query"; - me?: { + me: { __typename?: "User"; field: string; fieldLevel0: string; - fieldLevel1?: string | null; + fieldLevel1: string | null; fieldBothLevels: string; list: Array; listLevel0: Array; - listLevel1?: Array | null; + listLevel1: Array | null; listBothLevels: Array; nonNullableList: Array; nonNullableListLevel0: Array; @@ -102,7 +102,7 @@ describe('client-preset - nullability', () => { nonNullableListBothLevels: Array; listWithNonNullableItem: Array; listWithNonNullableItemLevel0: Array; - listWithNonNullableItemLevel1?: Array | null; + listWithNonNullableItemLevel1: Array | null; listWithNonNullableItemBothLevels: Array; nonNullableListWithNonNullableItem: Array; nonNullableListWithNonNullableItemLevel0: Array; @@ -137,24 +137,24 @@ describe('client-preset - nullability', () => { expect(formattedContent).toBeSimilarStringTo(` export type TestQuery = { __typename?: "Query"; - me?: { + me: { __typename?: "User"; - field?: string | null; - fieldLevel0?: string | null; - fieldLevel1?: string | null; - fieldBothLevels?: string | null; - list?: Array | null; - listLevel0?: Array | null; - listLevel1?: Array | null; - listBothLevels?: Array | null; + field: string | null; + fieldLevel0: string | null; + fieldLevel1: string | null; + fieldBothLevels: string | null; + list: Array | null; + listLevel0: Array | null; + listLevel1: Array | null; + listBothLevels: Array | null; nonNullableList: Array; nonNullableListLevel0: Array; nonNullableListLevel1: Array; nonNullableListBothLevels: Array; - listWithNonNullableItem?: Array | null; - listWithNonNullableItemLevel0?: Array | null; - listWithNonNullableItemLevel1?: Array | null; - listWithNonNullableItemBothLevels?: Array | null; + listWithNonNullableItem: Array | null; + listWithNonNullableItemLevel0: Array | null; + listWithNonNullableItemLevel1: Array | null; + listWithNonNullableItemBothLevels: Array | null; nonNullableListWithNonNullableItem: Array; nonNullableListWithNonNullableItemLevel0: Array; nonNullableListWithNonNullableItemLevel1: Array; diff --git a/packages/presets/client/tests/client-preset.spec.ts b/packages/presets/client/tests/client-preset.spec.ts index eb703be8a06..129dc8613ec 100644 --- a/packages/presets/client/tests/client-preset.spec.ts +++ b/packages/presets/client/tests/client-preset.spec.ts @@ -368,14 +368,14 @@ export * from "./gql";`); export type AQueryVariables = Exact<{ [key: string]: never; }>; - export type AQuery = { __typename?: 'Query', a?: string | null }; + export type AQuery = { __typename?: 'Query', a: string | null }; export type BQueryVariables = Exact<{ [key: string]: never; }>; - export type BQuery = { __typename?: 'Query', b?: string | null }; + export type BQuery = { __typename?: 'Query', b: string | null }; - export type CFragment = { __typename?: 'Query', c?: string | null } & { ' $fragmentName'?: 'CFragment' }; + export type CFragment = { __typename?: 'Query', c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; export const ADocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; @@ -483,14 +483,14 @@ export * from "./gql";`); export type AQueryVariables = Exact<{ [key: string]: never; }>; - export type AQuery = { __typename: 'Query', a?: string | null }; + export type AQuery = { __typename: 'Query', a: string | null }; export type BQueryVariables = Exact<{ [key: string]: never; }>; - export type BQuery = { __typename: 'Query', b?: string | null }; + export type BQuery = { __typename: 'Query', b: string | null }; - export type CFragment = { __typename: 'Query', c?: string | null } & { ' $fragmentName'?: 'CFragment' }; + export type CFragment = { __typename: 'Query', c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; export const ADocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; @@ -549,7 +549,7 @@ export * from "./gql";`); export type MeQueryVariables = Exact<{ [key: string]: never; }>; - export type MeQuery = { __typename?: 'Query', unmasked?: { __typename?: 'User', id: string, name: string, age: number } | null, masked?: ( + export type MeQuery = { __typename?: 'Query', unmasked: { __typename?: 'User', id: string, name: string, age: number } | null, masked: ( { __typename?: 'User', id: string } & { ' $fragmentRefs'?: { 'User_MeFragment': User_MeFragment } } ) | null }; @@ -640,7 +640,7 @@ export * from "./gql";`); export type AQueryVariables = Exact<{ [key: string]: never; }>; - export type AQuery = { __typename?: 'Query', a?: string | null }; + export type AQuery = { __typename?: 'Query', a: string | null }; export const ADocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"a"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode;" @@ -1478,12 +1478,12 @@ export * from "./gql.cjs";`); export type BbbQueryVariables = Exact<{ [key: string]: never; }>; - export type BbbQuery = { __typename?: 'Query', b?: string | null }; + export type BbbQuery = { __typename?: 'Query', b: string | null }; export type AaaQueryVariables = Exact<{ [key: string]: never; }>; - export type AaaQuery = { __typename?: 'Query', a?: string | null }; + export type AaaQuery = { __typename?: 'Query', a: string | null }; export const BbbDocument = {"__meta__":{"cacheKeys":["bbb"]},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"bbb"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"b"}}]}}]} as unknown as DocumentNode; @@ -1537,14 +1537,14 @@ export * from "./gql.cjs";`); export type AQueryVariables = Exact<{ [key: string]: never; }>; - export type AQuery = { __typename?: 'Query', a?: string | null }; + export type AQuery = { __typename?: 'Query', a: string | null }; export type BQueryVariables = Exact<{ [key: string]: never; }>; - export type BQuery = { __typename?: 'Query', b?: string | null }; + export type BQuery = { __typename?: 'Query', b: string | null }; - export type CFragment = { __typename?: 'Query', c?: string | null } & { ' $fragmentName'?: 'CFragment' }; + export type CFragment = { __typename?: 'Query', c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; export const ADocument = {"__meta__":{"hash":"b61b879c1eb0040bce65d70c8adfb1ae9360f52f"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; @@ -1599,14 +1599,14 @@ export * from "./gql.cjs";`); export type AQueryVariables = Exact<{ [key: string]: never; }>; - export type AQuery = { __typename?: 'Query', a?: string | null }; + export type AQuery = { __typename?: 'Query', a: string | null }; export type BQueryVariables = Exact<{ [key: string]: never; }>; - export type BQuery = { __typename?: 'Query', b?: string | null }; + export type BQuery = { __typename?: 'Query', b: string | null }; - export type CFragment = { __typename?: 'Query', c?: string | null } & { ' $fragmentName'?: 'CFragment' }; + export type CFragment = { __typename?: 'Query', c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; export const ADocument = {"__meta__":{"hash":"b61b879c1eb0040bce65d70c8adfb1ae9360f52f"}} as unknown as DocumentNode; @@ -1661,14 +1661,14 @@ export * from "./gql.cjs";`); export type AQueryVariables = Exact<{ [key: string]: never; }>; - export type AQuery = { __typename?: 'Query', a?: string | null }; + export type AQuery = { __typename?: 'Query', a: string | null }; export type BQueryVariables = Exact<{ [key: string]: never; }>; - export type BQuery = { __typename?: 'Query', b?: string | null }; + export type BQuery = { __typename?: 'Query', b: string | null }; - export type CFragment = { __typename?: 'Query', c?: string | null } & { ' $fragmentName'?: 'CFragment' }; + export type CFragment = { __typename?: 'Query', c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; export const ADocument = {"__meta__":{"custom_property_name":"b61b879c1eb0040bce65d70c8adfb1ae9360f52f"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; @@ -1723,12 +1723,12 @@ export * from "./gql.cjs";`); export type AaaQueryVariables = Exact<{ [key: string]: never; }>; - export type AaaQuery = { __typename?: 'Query', a?: string | null }; + export type AaaQuery = { __typename?: 'Query', a: string | null }; export type BbbQueryVariables = Exact<{ [key: string]: never; }>; - export type BbbQuery = { __typename?: 'Query', b?: string | null }; + export type BbbQuery = { __typename?: 'Query', b: string | null }; export const AaaDocument = {"__meta__":{"cacheKeys":["aaa"],"hash":"682f60dea844320c05fcb4fb6c4118015902c9a8"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"aaa"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; @@ -1783,14 +1783,14 @@ export * from "./gql.cjs";`); export type AQueryVariables = Exact<{ [key: string]: never; }>; - export type AQuery = { __typename?: 'Query', a?: string | null }; + export type AQuery = { __typename?: 'Query', a: string | null }; export type BQueryVariables = Exact<{ [key: string]: never; }>; - export type BQuery = { __typename?: 'Query', b?: string | null }; + export type BQuery = { __typename?: 'Query', b: string | null }; - export type CFragment = { __typename?: 'Query', c?: string | null } & { ' $fragmentName'?: 'CFragment' }; + export type CFragment = { __typename?: 'Query', c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; export const ADocument = {"__meta__":{"hash":"7d0eedabb966107835cf307a0ebaf93b5d2cb8c30228611ffe3d27a53c211a0c"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; @@ -1849,14 +1849,14 @@ export * from "./gql.cjs";`); export type AQueryVariables = Exact<{ [key: string]: never; }>; - export type AQuery = { __typename?: 'Query', a?: string | null }; + export type AQuery = { __typename?: 'Query', a: string | null }; export type BQueryVariables = Exact<{ [key: string]: never; }>; - export type BQuery = { __typename?: 'Query', b?: string | null }; + export type BQuery = { __typename?: 'Query', b: string | null }; - export type CFragment = { __typename?: 'Query', c?: string | null } & { ' $fragmentName'?: 'CFragment' }; + export type CFragment = { __typename?: 'Query', c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; export const ADocument = {"__meta__":{"hash":"queryA{a}"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; @@ -1916,14 +1916,14 @@ export * from "./gql.cjs";`); export type AQueryVariables = Exact<{ [key: string]: never; }>; - export type AQuery = { __typename?: 'Query', a?: string | null }; + export type AQuery = { __typename?: 'Query', a: string | null }; export type BQueryVariables = Exact<{ [key: string]: never; }>; - export type BQuery = { __typename?: 'Query', b?: string | null }; + export type BQuery = { __typename?: 'Query', b: string | null }; - export type CFragment = { __typename?: 'Query', c?: string | null } & { ' $fragmentName'?: 'CFragment' }; + export type CFragment = { __typename?: 'Query', c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; export const ADocument = {"__meta__":{"hash":"7d0eedabb966107835cf307a0ebaf93b5d2cb8c30228611ffe3d27a53c211a0c"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; @@ -1983,14 +1983,14 @@ export * from "./gql.cjs";`); export type AQueryVariables = Exact<{ [key: string]: never; }>; - export type AQuery = { __typename?: 'Query', a?: string | null }; + export type AQuery = { __typename?: 'Query', a: string | null }; export type BQueryVariables = Exact<{ [key: string]: never; }>; - export type BQuery = { __typename?: 'Query', b?: string | null }; + export type BQuery = { __typename?: 'Query', b: string | null }; - export type CFragment = { __typename?: 'Query', c?: string | null } & { ' $fragmentName'?: 'CFragment' }; + export type CFragment = { __typename?: 'Query', c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; export const ADocument = {"__meta__":{"hash":"a82d8b22f2bf805563146dc8ad80b2eb054845441539e3a5a69d1f534bb5bc0bd4f9470053b9f61b6aa1966cfc2f67406258102e5ee3a356a5d171506f3ede50"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; @@ -2108,7 +2108,7 @@ export * from "./gql.cjs";`); export type FooQueryVariables = Exact<{ [key: string]: never; }>; - export type FooQuery = { __typename?: 'Query', foo?: { __typename?: 'Foo' } & ( + export type FooQuery = { __typename?: 'Query', foo: { __typename?: 'Foo' } & ( { __typename?: 'Foo' } & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } ) | null }; @@ -2116,16 +2116,16 @@ export * from "./gql.cjs";`); export type FoosQueryVariables = Exact<{ [key: string]: never; }>; - export type FoosQuery = { __typename?: 'Query', foos?: Array<{ __typename?: 'Foo' } & ( + export type FoosQuery = { __typename?: 'Query', foos: Array<{ __typename?: 'Foo' } & ( { __typename?: 'Foo' } & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } ) | null> | null }; - export type FooFragment = { __typename?: 'Foo', value?: string | null } & { ' $fragmentName'?: 'FooFragment' }; + export type FooFragment = { __typename?: 'Foo', value: string | null } & { ' $fragmentName'?: 'FooFragment' }; - export type FooFragment = { __typename?: 'Foo', id?: string | null } & ({ __typename?: 'Foo', value?: string | null } | { __typename?: 'Foo', value?: never }) & { ' $fragmentName'?: 'FooFragment' }; + export type FooFragment = { __typename?: 'Foo', id: string | null } & ({ __typename?: 'Foo', value: string | null } | { __typename?: 'Foo', value?: never }) & { ' $fragmentName'?: 'FooFragment' }; - export type FooNestedFragment = { __typename?: 'Foo', id?: string | null } & ( + export type FooNestedFragment = { __typename?: 'Foo', id: string | null } & ( { __typename?: 'Foo' } & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } ) & { ' $fragmentName'?: 'FooNestedFragment' }; @@ -2173,7 +2173,7 @@ export * from "./gql.cjs";`); export type FooQueryVariables = Exact<{ [key: string]: never; }>; - export type FooQuery = { __typename?: 'Query', foo?: { __typename?: 'Foo' } & ( + export type FooQuery = { __typename?: 'Query', foo: { __typename?: 'Foo' } & ( { __typename?: 'Foo' } & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } ) | null }; @@ -2181,16 +2181,16 @@ export * from "./gql.cjs";`); export type FoosQueryVariables = Exact<{ [key: string]: never; }>; - export type FoosQuery = { __typename?: 'Query', foos?: Array<{ __typename?: 'Foo' } & ( + export type FoosQuery = { __typename?: 'Query', foos: Array<{ __typename?: 'Foo' } & ( { __typename?: 'Foo' } & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } ) | null> | null }; - export type FooFragment = { __typename?: 'Foo', value?: string | null } & { ' $fragmentName'?: 'FooFragment' }; + export type FooFragment = { __typename?: 'Foo', value: string | null } & { ' $fragmentName'?: 'FooFragment' }; - export type FooFragment = { __typename?: 'Foo', id?: string | null } & ({ __typename?: 'Foo', value?: string | null } | { __typename?: 'Foo', value?: never }) & { ' $fragmentName'?: 'FooFragment' }; + export type FooFragment = { __typename?: 'Foo', id: string | null } & ({ __typename?: 'Foo', value: string | null } | { __typename?: 'Foo', value?: never }) & { ' $fragmentName'?: 'FooFragment' }; - export type FooNestedFragment = { __typename?: 'Foo', id?: string | null } & ( + export type FooNestedFragment = { __typename?: 'Foo', id: string | null } & ( { __typename?: 'Foo' } & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } ) & { ' $fragmentName'?: 'FooNestedFragment' }; @@ -2238,7 +2238,7 @@ export * from "./gql.cjs";`); export type FooQueryVariables = Exact<{ [key: string]: never; }>; - export type FooQuery = { __typename?: 'Query', foo?: { __typename?: 'Foo' } & ( + export type FooQuery = { __typename?: 'Query', foo: { __typename?: 'Foo' } & ( { __typename?: 'Foo' } & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } ) | null }; @@ -2246,16 +2246,16 @@ export * from "./gql.cjs";`); export type FoosQueryVariables = Exact<{ [key: string]: never; }>; - export type FoosQuery = { __typename?: 'Query', foos?: Array<{ __typename?: 'Foo' } & ( + export type FoosQuery = { __typename?: 'Query', foos: Array<{ __typename?: 'Foo' } & ( { __typename?: 'Foo' } & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } ) | null> | null }; - export type FooFragment = { __typename?: 'Foo', value?: string | null } & { ' $fragmentName'?: 'FooFragment' }; + export type FooFragment = { __typename?: 'Foo', value: string | null } & { ' $fragmentName'?: 'FooFragment' }; - export type FooFragment = { __typename?: 'Foo', id?: string | null } & ({ __typename?: 'Foo', value?: string | null } | { __typename?: 'Foo', value?: never }) & { ' $fragmentName'?: 'FooFragment' }; + export type FooFragment = { __typename?: 'Foo', id: string | null } & ({ __typename?: 'Foo', value: string | null } | { __typename?: 'Foo', value?: never }) & { ' $fragmentName'?: 'FooFragment' }; - export type FooNestedFragment = { __typename?: 'Foo', id?: string | null } & ( + export type FooNestedFragment = { __typename?: 'Foo', id: string | null } & ( { __typename?: 'Foo' } & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } ) & { ' $fragmentName'?: 'FooNestedFragment' }; @@ -2376,7 +2376,7 @@ export * from "./gql.cjs";`); export type FooQueryVariables = Exact<{ [key: string]: never; }>; - export type FooQuery = { __typename?: 'Query', foo?: { __typename?: 'Foo' } & ( + export type FooQuery = { __typename?: 'Query', foo: { __typename?: 'Foo' } & ( { __typename?: 'Foo' } & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } ) | null }; @@ -2384,16 +2384,16 @@ export * from "./gql.cjs";`); export type FoosQueryVariables = Exact<{ [key: string]: never; }>; - export type FoosQuery = { __typename?: 'Query', foos?: Array<{ __typename?: 'Foo' } & ( + export type FoosQuery = { __typename?: 'Query', foos: Array<{ __typename?: 'Foo' } & ( { __typename?: 'Foo' } & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } ) | null> | null }; - export type FooFragment = { __typename?: 'Foo', value?: string | null } & { ' $fragmentName'?: 'FooFragment' }; + export type FooFragment = { __typename?: 'Foo', value: string | null } & { ' $fragmentName'?: 'FooFragment' }; - export type FooFragment = { __typename?: 'Foo', id?: string | null } & ({ __typename?: 'Foo', value?: string | null } | { __typename?: 'Foo', value?: never }) & { ' $fragmentName'?: 'FooFragment' }; + export type FooFragment = { __typename?: 'Foo', id: string | null } & ({ __typename?: 'Foo', value: string | null } | { __typename?: 'Foo', value?: never }) & { ' $fragmentName'?: 'FooFragment' }; - export type FooNestedFragment = { __typename?: 'Foo', id?: string | null } & ( + export type FooNestedFragment = { __typename?: 'Foo', id: string | null } & ( { __typename?: 'Foo' } & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } ) & { ' $fragmentName'?: 'FooNestedFragment' }; @@ -2512,7 +2512,7 @@ export * from "./gql.cjs";`); export type FooQueryVariables = Exact<{ [key: string]: never; }>; - export type FooQuery = { __typename?: 'Query', foo?: ( + export type FooQuery = { __typename?: 'Query', foo: ( { __typename?: 'Foo' } & { ' $fragmentRefs'?: { 'FooFragment': FooFragment } } ) | null }; @@ -2520,12 +2520,12 @@ export * from "./gql.cjs";`); export type FoosQueryVariables = Exact<{ [key: string]: never; }>; - export type FoosQuery = { __typename?: 'Query', foos?: Array<( + export type FoosQuery = { __typename?: 'Query', foos: Array<( { __typename?: 'Foo' } & { ' $fragmentRefs'?: { 'FooFragment': FooFragment } } ) | null> | null }; - export type FooFragment = { __typename?: 'Foo', value?: string | null } & { ' $fragmentName'?: 'FooFragment' }; + export type FooFragment = { __typename?: 'Foo', value: string | null } & { ' $fragmentName'?: 'FooFragment' }; export class TypedDocumentString extends String @@ -2861,7 +2861,7 @@ export * from "./gql.cjs";`); export type Test_UserQueryVariables = Exact<{ [key: string]: never; }>; - export type Test_UserQuery = { readonly __typename?: 'Query', readonly user?: { readonly __typename?: 'User', readonly id: string, readonly name: string } | null }; + export type Test_UserQuery = { readonly __typename?: 'Query', readonly user: { readonly __typename?: 'User', readonly id: string, readonly name: string } | null }; export const Test_UserDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Test_User"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"StringValue","value":"user-001","block":false}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]} as unknown as DocumentNode;" From 345850235ccba47c110fb04f45570b832688271d Mon Sep 17 00:00:00 2001 From: Igor Kusakov Date: Wed, 24 Dec 2025 06:02:23 -0500 Subject: [PATCH 13/69] Generate input types and output enums into target file (#10527) * input types, input/output enums are generated to the target files * cleanup * better code * more tests * cleanup * better code * better tests * bugfixing for inner types and outer enums * bugfixing after merge * cleanup * cleanup * fix snapshots * fix type errors in presets/client * updated tests/examples * Add standalone.input.spec.ts and update standalone tests to TDD * Update operations/visitor.ts to satisfy tests * Revert Client Preset changes * Add oneOf directive for GraphQL 15 * Update changeset * Refactor IIFE --------- Co-authored-by: Igor Kusakov Co-authored-by: Eddy Nguyen --- .changeset/every-queens-sin.md | 6 + dev-test/star-wars/types.avoidOptionals.ts | 13 + dev-test/star-wars/types.excludeQueryAlpha.ts | 13 + dev-test/star-wars/types.excludeQueryBeta.ts | 13 + .../star-wars/types.globallyAvailable.d.ts | 13 + dev-test/star-wars/types.immutableTypes.ts | 13 + ...ypes.preResolveTypes.onlyOperationTypes.ts | 13 + dev-test/star-wars/types.preResolveTypes.ts | 13 + dev-test/star-wars/types.skipSchema.ts | 13 + dev-test/star-wars/types.ts | 13 + .../src/ts-operation-variables-to-object.ts | 2 +- .../typescript/operations/src/visitor.ts | 296 +++++++++++++- .../__snapshots__/ts-documents.spec.ts.snap | 6 +- .../tests/extract-all-types.spec.ts | 40 +- ...-documents.standalone.import-types.spec.ts | 18 + .../ts-documents.standalone.input.spec.ts | 370 ++++++++++++++++++ .../tests/ts-documents.standalone.spec.ts | 324 +++++++++++++++ .../client/tests/client-preset.enum.spec.ts | 4 + 18 files changed, 1172 insertions(+), 11 deletions(-) create mode 100644 .changeset/every-queens-sin.md create mode 100644 packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts diff --git a/.changeset/every-queens-sin.md b/.changeset/every-queens-sin.md new file mode 100644 index 00000000000..cda139690b5 --- /dev/null +++ b/.changeset/every-queens-sin.md @@ -0,0 +1,6 @@ +--- +'@graphql-codegen/typescript-operations': major +'@graphql-codegen/client-preset': major +--- + +Conditionally generate input types and output enums into target file diff --git a/dev-test/star-wars/types.avoidOptionals.ts b/dev-test/star-wars/types.avoidOptionals.ts index 1d68e007027..bd588f1b5ef 100644 --- a/dev-test/star-wars/types.avoidOptionals.ts +++ b/dev-test/star-wars/types.avoidOptionals.ts @@ -1,7 +1,20 @@ type Exact = { [K in keyof T]: T[K] }; +<<<<<<< HEAD export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +======= +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** The episodes in the Star Wars trilogy */ +export type Episode = + /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ + | 'EMPIRE' + /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ + | 'JEDI' + /** Star Wars Episode IV: A New Hope, released in 1977. */ + | 'NEWHOPE'; + +>>>>>>> c7b5477b6 (Generate input types and output enums into target file (#10527)) export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.excludeQueryAlpha.ts b/dev-test/star-wars/types.excludeQueryAlpha.ts index 732571cc311..d294745831d 100644 --- a/dev-test/star-wars/types.excludeQueryAlpha.ts +++ b/dev-test/star-wars/types.excludeQueryAlpha.ts @@ -1,7 +1,20 @@ type Exact = { [K in keyof T]: T[K] }; +<<<<<<< HEAD export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +======= +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** The episodes in the Star Wars trilogy */ +export type Episode = + /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ + | 'EMPIRE' + /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ + | 'JEDI' + /** Star Wars Episode IV: A New Hope, released in 1977. */ + | 'NEWHOPE'; + +>>>>>>> c7b5477b6 (Generate input types and output enums into target file (#10527)) export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.excludeQueryBeta.ts b/dev-test/star-wars/types.excludeQueryBeta.ts index fd906fe2094..172be46a898 100644 --- a/dev-test/star-wars/types.excludeQueryBeta.ts +++ b/dev-test/star-wars/types.excludeQueryBeta.ts @@ -1,7 +1,20 @@ type Exact = { [K in keyof T]: T[K] }; +<<<<<<< HEAD export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +======= +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** The episodes in the Star Wars trilogy */ +export type Episode = + /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ + | 'EMPIRE' + /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ + | 'JEDI' + /** Star Wars Episode IV: A New Hope, released in 1977. */ + | 'NEWHOPE'; + +>>>>>>> c7b5477b6 (Generate input types and output enums into target file (#10527)) export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.globallyAvailable.d.ts b/dev-test/star-wars/types.globallyAvailable.d.ts index 05ffe126c60..9409ec381b3 100644 --- a/dev-test/star-wars/types.globallyAvailable.d.ts +++ b/dev-test/star-wars/types.globallyAvailable.d.ts @@ -1,7 +1,20 @@ type Exact = { [K in keyof T]: T[K] }; +<<<<<<< HEAD export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +======= +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** The episodes in the Star Wars trilogy */ +type Episode = + /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ + | 'EMPIRE' + /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ + | 'JEDI' + /** Star Wars Episode IV: A New Hope, released in 1977. */ + | 'NEWHOPE'; + +>>>>>>> c7b5477b6 (Generate input types and output enums into target file (#10527)) type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.immutableTypes.ts b/dev-test/star-wars/types.immutableTypes.ts index 48103e12eeb..79acc648d06 100644 --- a/dev-test/star-wars/types.immutableTypes.ts +++ b/dev-test/star-wars/types.immutableTypes.ts @@ -1,7 +1,20 @@ type Exact = { [K in keyof T]: T[K] }; +<<<<<<< HEAD export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +======= +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** The episodes in the Star Wars trilogy */ +export type Episode = + /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ + | 'EMPIRE' + /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ + | 'JEDI' + /** Star Wars Episode IV: A New Hope, released in 1977. */ + | 'NEWHOPE'; + +>>>>>>> c7b5477b6 (Generate input types and output enums into target file (#10527)) export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts index d09b49aecd0..3eeecddb585 100644 --- a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts @@ -1,7 +1,20 @@ type Exact = { [K in keyof T]: T[K] }; +<<<<<<< HEAD export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +======= +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** The episodes in the Star Wars trilogy */ +export type Episode = + /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ + | 'EMPIRE' + /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ + | 'JEDI' + /** Star Wars Episode IV: A New Hope, released in 1977. */ + | 'NEWHOPE'; + +>>>>>>> c7b5477b6 (Generate input types and output enums into target file (#10527)) export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.preResolveTypes.ts b/dev-test/star-wars/types.preResolveTypes.ts index d09b49aecd0..3eeecddb585 100644 --- a/dev-test/star-wars/types.preResolveTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.ts @@ -1,7 +1,20 @@ type Exact = { [K in keyof T]: T[K] }; +<<<<<<< HEAD export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +======= +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** The episodes in the Star Wars trilogy */ +export type Episode = + /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ + | 'EMPIRE' + /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ + | 'JEDI' + /** Star Wars Episode IV: A New Hope, released in 1977. */ + | 'NEWHOPE'; + +>>>>>>> c7b5477b6 (Generate input types and output enums into target file (#10527)) export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.skipSchema.ts b/dev-test/star-wars/types.skipSchema.ts index d09b49aecd0..3eeecddb585 100644 --- a/dev-test/star-wars/types.skipSchema.ts +++ b/dev-test/star-wars/types.skipSchema.ts @@ -1,7 +1,20 @@ type Exact = { [K in keyof T]: T[K] }; +<<<<<<< HEAD export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +======= +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** The episodes in the Star Wars trilogy */ +export type Episode = + /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ + | 'EMPIRE' + /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ + | 'JEDI' + /** Star Wars Episode IV: A New Hope, released in 1977. */ + | 'NEWHOPE'; + +>>>>>>> c7b5477b6 (Generate input types and output enums into target file (#10527)) export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.ts b/dev-test/star-wars/types.ts index d09b49aecd0..3eeecddb585 100644 --- a/dev-test/star-wars/types.ts +++ b/dev-test/star-wars/types.ts @@ -1,7 +1,20 @@ type Exact = { [K in keyof T]: T[K] }; +<<<<<<< HEAD export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +======= +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** The episodes in the Star Wars trilogy */ +export type Episode = + /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ + | 'EMPIRE' + /** Star Wars Episode VI: Return of the Jedi, released in 1983. */ + | 'JEDI' + /** Star Wars Episode IV: A New Hope, released in 1977. */ + | 'NEWHOPE'; + +>>>>>>> c7b5477b6 (Generate input types and output enums into target file (#10527)) export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts index 55941798944..d052bbd8c97 100644 --- a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts +++ b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts @@ -1,6 +1,6 @@ import { TypeScriptOperationVariablesToObject as TSOperationVariablesToObject } from '@graphql-codegen/typescript'; -const SCALARS = { +export const SCALARS = { ID: 'string | number', String: 'string', Int: 'number', diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 661b8f47059..6835cbbd73e 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -1,27 +1,38 @@ import autoBind from 'auto-bind'; import { EnumTypeDefinitionNode, + getNamedType, GraphQLEnumType, GraphQLInputObjectType, GraphQLScalarType, + InputObjectTypeDefinitionNode, + InputValueDefinitionNode, isEnumType, Kind, + TypeInfo, visit, + visitWithTypeInfo, type DocumentNode, type FragmentDefinitionNode, type GraphQLNamedInputType, type GraphQLSchema, + type TypeDefinitionNode, + type TypeNode, } from 'graphql'; import { normalizeImportExtension } from '@graphql-codegen/plugin-helpers'; import { BaseDocumentsVisitor, convertSchemaEnumToDeclarationBlockString, + DeclarationBlock, DeclarationKind, generateFragmentImportStatement, generateImportStatement, getConfigValue, getEnumsImports, + getNodeComment, + indent, isNativeNamedType, + isOneOfInputObjectType, LoadedFragment, normalizeAvoidOptionals, NormalizedAvoidOptionalsConfig, @@ -35,7 +46,10 @@ import { type ParsedEnumValuesMap, } from '@graphql-codegen/visitor-plugin-common'; import { TypeScriptDocumentsPluginConfig } from './config.js'; -import { TypeScriptOperationVariablesToObject } from './ts-operation-variables-to-object.js'; +import { + SCALARS, + TypeScriptOperationVariablesToObject, +} from './ts-operation-variables-to-object.js'; import { TypeScriptSelectionSetProcessor } from './ts-selection-set-processor.js'; export interface TypeScriptDocumentsParsedConfig extends ParsedDocumentsConfig { @@ -50,7 +64,12 @@ export interface TypeScriptDocumentsParsedConfig extends ParsedDocumentsConfig { enumValues: ParsedEnumValuesMap; } -type UsedNamedInputTypes = Record; +type UsedNamedInputTypes = Record< + string, + | { type: 'GraphQLScalarType'; node: GraphQLScalarType; tsType: string } + | { type: 'GraphQLEnumType'; node: GraphQLEnumType; tsType: string } + | { type: 'GraphQLInputObjectType'; node: GraphQLInputObjectType; tsType: string } +>; export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< TypeScriptDocumentsPluginConfig, @@ -172,7 +191,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< this.config.enumValues, this.config.arrayInputCoercion, undefined, - 'InputMaybe', + undefined, ), ); this._declarationBlockConfig = { @@ -206,6 +225,142 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< }); } + InputObjectTypeDefinition(node: InputObjectTypeDefinitionNode): string | null { + const inputTypeName = node.name.value; + if (!this._usedNamedInputTypes[inputTypeName]) { + return null; + } + + if (isOneOfInputObjectType(this._schema.getType(inputTypeName))) { + return new DeclarationBlock(this._declarationBlockConfig) + .asKind('type') + .withName(this.convertName(node)) + .withComment(node.description?.value) + .withContent(`\n` + (node.fields || []).join('\n |')).string; + } + + return new DeclarationBlock(this._declarationBlockConfig) + .asKind('type') + .withName(this.convertName(node)) + .withComment(node.description?.value) + .withBlock((node.fields || []).join('\n')).string; + } + + InputValueDefinition( + node: InputValueDefinitionNode, + _key?: number | string, + _parent?: any, + _path?: Array, + ancestors?: Array, + ): string { + const oneOfDetails = parseOneOfInputValue({ + node, + schema: this._schema, + ancestors, + }); + + // 1. Flatten GraphQL type nodes to make it easier to turn into string + // GraphQL type nodes may have `NonNullType` type before each `ListType` or `NamedType` + // This make it a bit harder to know whether a `ListType` or `Namedtype` is nullable without looking at the node before it. + // Flattening it into an array where the nullability is in `ListType` and `NamedType` makes it easier to code, + // + // So, we recursively call `collectAndFlattenTypeNodes` to handle the following scenarios: + // - [Thing] + // - [Thing!] + // - [Thing]! + // - [Thing!]! + const typeNodes: Parameters[0]['typeNodes'] = []; + collectAndFlattenTypeNodes({ + currentTypeNode: node.type, + isPreviousNodeNonNullable: oneOfDetails.isOneOfInputValue, // If the InputValue is part of @oneOf input, we treat it as non-null (even if it must be null in the schema) + typeNodes, + }); + + // 2. Generate the type of a TypeScript field declaration + // e.g. `field?: string`, then the `string` is the `typePart` + let typePart: string = ''; + // We call `.reverse()` here to get the base type node first + for (const typeNode of typeNodes.reverse()) { + if (typeNode.type === 'NamedType') { + const usedInputType = this._usedNamedInputTypes[typeNode.name]; + if (!usedInputType) { + continue; + } + + typePart = usedInputType.tsType; // If the schema is correct, when reversing typeNodes, the first node would be `NamedType`, which means we can safely set it as the base for typePart + if (usedInputType.tsType !== 'any' && !typeNode.isNonNullable) { + typePart += ' | null | undefined'; + } + continue; + } + + if (typeNode.type === 'ListType') { + typePart = `Array<${typePart}>`; + if (!typeNode.isNonNullable) { + typePart += ' | null | undefined'; + } + } + } + + // TODO: eddeee888 check if we want to support `directiveArgumentAndInputFieldMappings` for operations + // if (node.directives && this.config.directiveArgumentAndInputFieldMappings) { + // typePart = + // getDirectiveOverrideType({ + // directives: node.directives, + // directiveArgumentAndInputFieldMappings: this.config.directiveArgumentAndInputFieldMappings, + // }) || typePart; + // } + + const addOptionalSign = + !oneOfDetails.isOneOfInputValue && + !this.config.avoidOptionals.inputValue && + (node.type.kind !== Kind.NON_NULL_TYPE || + (!this.config.avoidOptionals.defaultValue && node.defaultValue !== undefined)); + + // 3. Generate the keyPart of the TypeScript field declaration + // e.g. `field?: string`, then the `field?` is the `keyPart` + const keyPart = `${node.name.value}${addOptionalSign ? '?' : ''}`; + + // 4. other parts of TypeScript field declaration + const commentPart = getNodeComment(node); + const readonlyPart = this.config.immutableTypes ? 'readonly ' : ''; + + const currentInputValue = commentPart + indent(`${readonlyPart}${keyPart}: ${typePart};`); + + // 5. Check if field is part of `@oneOf` input type + // If yes, we must generate a union member where the current inputValue must be provieded, and the others are not + // e.g. + // ```graphql + // input UserInput { + // byId: ID + // byEmail: String + // byLegacyId: ID + // } + // ``` + // + // Then, the generated type is: + // ```ts + // type UserInput = + // | { byId: string | number; byEmail?: never; byLegacyId?: never } + // | { byId?: never; byEmail: string; byLegacyId?: never } + // | { byId?: never; byEmail?: never; byLegacyId: string | number } + // ``` + if (oneOfDetails.isOneOfInputValue) { + const fieldParts: Array = []; + for (const fieldName of Object.keys(oneOfDetails.parentType.getFields())) { + if (fieldName === node.name.value) { + fieldParts.push(currentInputValue); + continue; + } + fieldParts.push(`${readonlyPart}${fieldName}?: never;`); + } + return indent(`{ ${fieldParts.join(' ')} }`); + } + + // If field is not part of @oneOf input type, then it's a input value, just return as-is + return currentInputValue; + } + public getImports(): Array { return !this.config.globalNamespace && (this.config.inlineFragmentTypes === 'combine' || this.config.inlineFragmentTypes === 'mask') @@ -257,6 +412,46 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< return `Exact<${variablesBlock === '{}' ? `{ [key: string]: never; }` : variablesBlock}>${extraType}`; } + private collectInnerTypesRecursively( + node: GraphQLNamedInputType, + usedInputTypes: UsedNamedInputTypes, + ): void { + if (usedInputTypes[node.name]) { + return; + } + + if (node instanceof GraphQLEnumType) { + usedInputTypes[node.name] = { + type: 'GraphQLEnumType', + node, + tsType: this.convertName(node.name), + }; + return; + } + + if (node instanceof GraphQLScalarType) { + usedInputTypes[node.name] = { + type: 'GraphQLScalarType', + node, + tsType: (SCALARS[node.name] || this.config.scalars?.[node.name]?.input.type) ?? 'any', + }; + return; + } + + // GraphQLInputObjectType + usedInputTypes[node.name] = { + type: 'GraphQLInputObjectType', + node, + tsType: this.convertName(node.name), + }; + + const fields = node.getFields(); + for (const field of Object.values(fields)) { + const fieldType = getNamedType(field.type); + this.collectInnerTypesRecursively(fieldType, usedInputTypes); + } + } + private collectUsedInputTypes({ schema, documentNode, @@ -268,6 +463,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< const usedInputTypes: UsedNamedInputTypes = {}; + // Collect input enums and input types visit(documentNode, { VariableDefinition: variableDefinitionNode => { visit(variableDefinitionNode, { @@ -280,13 +476,38 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< foundInputType instanceof GraphQLEnumType) && !isNativeNamedType(foundInputType) ) { - usedInputTypes[namedTypeNode.name.value] = foundInputType; + this.collectInnerTypesRecursively(foundInputType, usedInputTypes); } }, }); }, }); + // Collect output enums + const typeInfo = new TypeInfo(schema); + visit( + documentNode, + // AST doesn’t include field types (they are defined in schema) - only names. + // TypeInfo is a stateful helper that tracks typing context while walking the AST + // visitWithTypeInfo wires that context into a visitor. + visitWithTypeInfo(typeInfo, { + Field: () => { + const fieldType = typeInfo.getType(); + if (fieldType) { + const namedType = getNamedType(fieldType); + + if (namedType instanceof GraphQLEnumType) { + usedInputTypes[namedType.name] = { + type: 'GraphQLEnumType', + node: namedType, + tsType: this.convertName(namedType.name), + }; + } + } + }, + }), + ); + return usedInputTypes; } @@ -323,3 +544,70 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< return "export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never };"; } } + +function parseOneOfInputValue({ + node, + schema, + ancestors, +}: { + node: InputValueDefinitionNode; + schema: GraphQLSchema; + ancestors?: Array; +}): + | { + isOneOfInputValue: true; + realParentDef: TypeDefinitionNode; + parentType: GraphQLInputObjectType; + } + | { isOneOfInputValue: false } { + const realParentDef = ancestors?.[ancestors.length - 1]; + if (realParentDef) { + const parentType = schema.getType(realParentDef.name.value); + if (isOneOfInputObjectType(parentType)) { + if (node.type.kind === Kind.NON_NULL_TYPE) { + throw new Error( + 'Fields on an input object type can not be non-nullable. It seems like the schema was not validated.', + ); + } + return { isOneOfInputValue: true, realParentDef, parentType }; + } + } + return { isOneOfInputValue: false }; +} + +function collectAndFlattenTypeNodes({ + currentTypeNode, + isPreviousNodeNonNullable, + typeNodes, +}: { + currentTypeNode: TypeNode; + isPreviousNodeNonNullable: boolean; + typeNodes: Array< + | { type: 'ListType'; isNonNullable: boolean } + | { type: 'NamedType'; isNonNullable: boolean; name: string } + >; +}): void { + if (currentTypeNode.kind === Kind.NON_NULL_TYPE) { + const nextTypeNode = currentTypeNode.type; + collectAndFlattenTypeNodes({ + currentTypeNode: nextTypeNode, + isPreviousNodeNonNullable: true, + typeNodes, + }); + } else if (currentTypeNode.kind === Kind.LIST_TYPE) { + typeNodes.push({ type: 'ListType', isNonNullable: isPreviousNodeNonNullable }); + + const nextTypeNode = currentTypeNode.type; + collectAndFlattenTypeNodes({ + currentTypeNode: nextTypeNode, + isPreviousNodeNonNullable: false, + typeNodes, + }); + } else if (currentTypeNode.kind === Kind.NAMED_TYPE) { + typeNodes.push({ + type: 'NamedType', + isNonNullable: isPreviousNodeNonNullable, + name: currentTypeNode.name.value, + }); + } +} diff --git a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap index 0ba7941fc12..07c552f2903 100644 --- a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap +++ b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap @@ -57,7 +57,11 @@ export type ElementMetadataFragment = `; exports[`TypeScript Operations Plugin > Issues > #2916 - Missing import prefix with preResolveTypes: true and near-operation-file preset 1`] = ` -"export type UserQueryVariables = Exact<{ [key: string]: never; }>; +"export type Department = + | 'Direction' + | 'Development'; + +export type UserQueryVariables = Exact<{ [key: string]: never; }>; export type UserQuery = { user: { id: string, username: string, email: string, dep: Types.Department } }; diff --git a/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts b/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts index a582efd12a4..d8cdf32c0ec 100644 --- a/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts @@ -401,7 +401,13 @@ describe('extractAllFieldsToTypes: true', () => { { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` - "export type ConversationBotSolutionFragment_BotSolution_article_ArchivedArticle = { __typename: 'ArchivedArticle', id: string, htmlUrl: string, title: string, url: string }; + "export type CallType = + | 'OUTGOING' + | 'INCOMING' + | 'VOICEMAIL' + | 'UNKNOWN'; + + export type ConversationBotSolutionFragment_BotSolution_article_ArchivedArticle = { __typename: 'ArchivedArticle', id: string, htmlUrl: string, title: string, url: string }; export type ConversationBotSolutionFragment_BotSolution_originatedFrom_EmailInteraction = { __typename: 'EmailInteraction', originalEmailURLPath: string }; @@ -565,7 +571,13 @@ describe('extractAllFieldsToTypes: true', () => { { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` - "export type ConversationBotSolutionFragment_BotSolution_article_ArchivedArticle = ( + "export type CallType = + | 'OUTGOING' + | 'INCOMING' + | 'VOICEMAIL' + | 'UNKNOWN'; + + export type ConversationBotSolutionFragment_BotSolution_article_ArchivedArticle = ( { id: string, htmlUrl: string, title: string, url: string } & { __typename: 'ArchivedArticle' } ); @@ -734,7 +746,13 @@ describe('extractAllFieldsToTypes: true', () => { { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` - "export type ConversationBotSolutionFragment_BotSolution_article_ArchivedArticle = { __typename: 'ArchivedArticle', id: string, htmlUrl: string, title: string, url: string }; + "export type CallType = + | 'OUTGOING' + | 'INCOMING' + | 'VOICEMAIL' + | 'UNKNOWN'; + + export type ConversationBotSolutionFragment_BotSolution_article_ArchivedArticle = { __typename: 'ArchivedArticle', id: string, htmlUrl: string, title: string, url: string }; export type ConversationBotSolutionFragment_BotSolution_originatedFrom_EmailInteraction = ( { __typename: 'EmailInteraction' } @@ -972,7 +990,13 @@ describe('extractAllFieldsToTypes: true', () => { { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` - "export type ConversationBotSolutionFragment_BotSolution_article_ArchivedArticle = { __typename: 'ArchivedArticle', id: string, htmlUrl: string, title: string, url: string }; + "export type CallType = + | 'OUTGOING' + | 'INCOMING' + | 'VOICEMAIL' + | 'UNKNOWN'; + + export type ConversationBotSolutionFragment_BotSolution_article_ArchivedArticle = { __typename: 'ArchivedArticle', id: string, htmlUrl: string, title: string, url: string }; export type ConversationBotSolutionFragment_BotSolution_originatedFrom_EmailInteraction = ( { __typename: 'EmailInteraction' } @@ -1207,7 +1231,13 @@ describe('extractAllFieldsToTypes: true', () => { { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` - "export type ConversationBotSolutionFragment_BotSolution_article_ArchivedArticle = ( + "export type CallType = + | 'OUTGOING' + | 'INCOMING' + | 'VOICEMAIL' + | 'UNKNOWN'; + + export type ConversationBotSolutionFragment_BotSolution_article_ArchivedArticle = ( { __typename: 'ArchivedArticle' } & Pick< ArchivedArticle, diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts index 54ed0cdf2a0..7063e9d09ff 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts @@ -107,6 +107,15 @@ describe('TypeScript Operations Plugin - Import Types', () => { type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + /** UsersInput Description */ + type UsersInput = { + /** UsersInput from */ + from?: any; + /** UsersInput to */ + to?: any; + role?: UserRole | null | undefined; + }; + export type UserQueryVariables = Exact<{ id: string; }>; @@ -242,6 +251,15 @@ describe('TypeScript Operations Plugin - Import Types', () => { type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + /** UsersInput Description */ + type UsersInput = { + /** UsersInput from */ + from?: any; + /** UsersInput to */ + to?: any; + role?: UserRole | null | undefined; + }; + export type UserQueryVariables = Exact<{ id: string; }>; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts new file mode 100644 index 00000000000..2071c3adf0e --- /dev/null +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts @@ -0,0 +1,370 @@ +import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; +import { validateTs } from '@graphql-codegen/testing'; +import { buildSchema, parse } from 'graphql'; +import { plugin } from '../src/index.js'; + +describe('TypeScript Operations Plugin - Input', () => { + it('generates nested input correctly', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + users(input: UsersInput!): [User!]! + } + + type ResponseError { + error: ResponseErrorType! + } + + enum ResponseErrorType { + NOT_FOUND + INPUT_VALIDATION_ERROR + FORBIDDEN_ERROR + UNEXPECTED_ERROR + } + + type User { + id: ID! + ageRange1: [Int] + ageRange2: [Int]! + ageRange3: [Int!] + ageRange4: [Int!]! + } + + "UserRole Description" + enum UserRole { + "UserRole ADMIN" + ADMIN + "UserRole CUSTOMER" + CUSTOMER + } + + "UsersInput Description" + input UsersInput { + "UsersInput from" + from: DateTime + "UsersInput to" + to: DateTime + timezone: TimeZone + role: UserRole + ageRange1: [Int] + ageRange2: [Int]! + ageRange3: [Int!] + ageRange4: [Int!]! + bestFriend: UsersBestFriendInput + nestedInput: UsersInput + } + + input UsersBestFriendInput { + name: String + } + + scalar DateTime + scalar TimeZone + `); + const document = parse(/* GraphQL */ ` + query UsersWithScalarInput($inputNonNullable: UsersInput!, $inputNullable: UsersInput) { + users(input: $inputNonNullable) { + ageRange1 + ageRange2 + ageRange3 + ageRange4 + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + scalars: { + DateTime: 'Date', + }, + }, + { outputFile: '' } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + /** UserRole Description */ + export type UserRole = + /** UserRole ADMIN */ + | 'ADMIN' + /** UserRole CUSTOMER */ + | 'CUSTOMER'; + + /** UsersInput Description */ + type UsersInput = { + /** UsersInput from */ + from?: Date | null | undefined; + /** UsersInput to */ + to?: Date | null | undefined; + timezone?: any; + role?: UserRole | null | undefined; + ageRange1?: Array | null | undefined; + ageRange2: Array; + ageRange3?: Array | null | undefined; + ageRange4: Array; + bestFriend?: UsersBestFriendInput | null | undefined; + nestedInput?: UsersInput | null | undefined; + }; + + type UsersBestFriendInput = { + name?: string | null | undefined; + }; + + export type UsersWithScalarInputQueryVariables = Exact<{ + inputNonNullable: UsersInput; + inputNullable?: UsersInput | null; + }>; + + + export type UsersWithScalarInputQuery = { __typename?: 'Query', users: Array<{ __typename?: 'User', ageRange1: Array | null, ageRange2: Array, ageRange3: Array | null, ageRange4: Array }> }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('generates readonly input when immutableTypes:true', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + users(input: UsersInput!): [User!]! + } + + type ResponseError { + error: ResponseErrorType! + } + + enum ResponseErrorType { + NOT_FOUND + INPUT_VALIDATION_ERROR + FORBIDDEN_ERROR + UNEXPECTED_ERROR + } + + type User { + id: ID! + ageRange1: [Int] + ageRange2: [Int]! + ageRange3: [Int!] + ageRange4: [Int!]! + } + + "UserRole Description" + enum UserRole { + "UserRole ADMIN" + ADMIN + "UserRole CUSTOMER" + CUSTOMER + } + + "UsersInput Description" + input UsersInput { + "UsersInput from" + from: DateTime + "UsersInput to" + to: DateTime + timezone: TimeZone + role: UserRole + ageRange1: [Int] + ageRange2: [Int]! + ageRange3: [Int!] + ageRange4: [Int!]! + bestFriend: UsersBestFriendInput + nestedInput: UsersInput + } + + input UsersBestFriendInput { + name: String + } + + scalar DateTime + scalar TimeZone + `); + const document = parse(/* GraphQL */ ` + query UsersWithScalarInput($inputNonNullable: UsersInput!, $inputNullable: UsersInput) { + users(input: $inputNonNullable) { + ageRange1 + ageRange2 + ageRange3 + ageRange4 + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + scalars: { + DateTime: 'Date', + }, + immutableTypes: true, + }, + { outputFile: '' } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + /** UserRole Description */ + export type UserRole = + /** UserRole ADMIN */ + | 'ADMIN' + /** UserRole CUSTOMER */ + | 'CUSTOMER'; + + /** UsersInput Description */ + type UsersInput = { + /** UsersInput from */ + readonly from?: Date | null | undefined; + /** UsersInput to */ + readonly to?: Date | null | undefined; + readonly timezone?: any; + readonly role?: UserRole | null | undefined; + readonly ageRange1?: Array | null | undefined; + readonly ageRange2: Array; + readonly ageRange3?: Array | null | undefined; + readonly ageRange4: Array; + readonly bestFriend?: UsersBestFriendInput | null | undefined; + readonly nestedInput?: UsersInput | null | undefined; + }; + + type UsersBestFriendInput = { + readonly name?: string | null | undefined; + }; + + export type UsersWithScalarInputQueryVariables = Exact<{ + inputNonNullable: UsersInput; + inputNullable?: UsersInput | null; + }>; + + + export type UsersWithScalarInputQuery = { readonly __typename?: 'Query', readonly users: ReadonlyArray<{ readonly __typename?: 'User', readonly ageRange1: ReadonlyArray | null, readonly ageRange2: ReadonlyArray, readonly ageRange3: ReadonlyArray | null, readonly ageRange4: ReadonlyArray }> }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('generates @oneOf input correctly', async () => { + const schema = buildSchema(/* GraphQL */ ` + directive @oneOf on INPUT_OBJECT + + type Query { + users(input: UsersInput!): [User!]! + } + + type ResponseError { + error: ResponseErrorType! + } + + enum ResponseErrorType { + NOT_FOUND + INPUT_VALIDATION_ERROR + FORBIDDEN_ERROR + UNEXPECTED_ERROR + } + + type User { + id: ID! + ageRange1: [Int] + ageRange2: [Int]! + ageRange3: [Int!] + ageRange4: [Int!]! + } + + "UserRole Description" + enum UserRole { + "UserRole ADMIN" + ADMIN + "UserRole CUSTOMER" + CUSTOMER + } + + "UsersInput Description" + input UsersInput @oneOf { + "UsersInput from" + from: DateTime + "UsersInput to" + to: DateTime + timezone: TimeZone + role: UserRole + ageRange1: [Int] + ageRange3: [Int!] + bestFriend: UsersBestFriendInput + nestedInput: UsersInput + } + + input UsersBestFriendInput { + name: String + } + + scalar DateTime + scalar TimeZone + `); + const document = parse(/* GraphQL */ ` + query Users($inputNonNullable: UsersInput!, $inputNullable: UsersInput) { + users(input: $inputNonNullable) { + __typename + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + scalars: { + DateTime: 'Date', + }, + }, + { outputFile: '' } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + /** UserRole Description */ + export type UserRole = + /** UserRole ADMIN */ + | 'ADMIN' + /** UserRole CUSTOMER */ + | 'CUSTOMER'; + + /** UsersInput Description */ + type UsersInput = + { /** UsersInput from */ + from: Date; to?: never; timezone?: never; role?: never; ageRange1?: never; ageRange3?: never; bestFriend?: never; nestedInput?: never; } + | { from?: never; /** UsersInput to */ + to: Date; timezone?: never; role?: never; ageRange1?: never; ageRange3?: never; bestFriend?: never; nestedInput?: never; } + | { from?: never; to?: never; timezone: any; role?: never; ageRange1?: never; ageRange3?: never; bestFriend?: never; nestedInput?: never; } + | { from?: never; to?: never; timezone?: never; role: UserRole; ageRange1?: never; ageRange3?: never; bestFriend?: never; nestedInput?: never; } + | { from?: never; to?: never; timezone?: never; role?: never; ageRange1: Array; ageRange3?: never; bestFriend?: never; nestedInput?: never; } + | { from?: never; to?: never; timezone?: never; role?: never; ageRange1?: never; ageRange3: Array; bestFriend?: never; nestedInput?: never; } + | { from?: never; to?: never; timezone?: never; role?: never; ageRange1?: never; ageRange3?: never; bestFriend: UsersBestFriendInput; nestedInput?: never; } + | { from?: never; to?: never; timezone?: never; role?: never; ageRange1?: never; ageRange3?: never; bestFriend?: never; nestedInput: UsersInput; }; + + type UsersBestFriendInput = { + name?: string | null | undefined; + }; + + export type UsersQueryVariables = Exact<{ + inputNonNullable: UsersInput; + inputNullable?: UsersInput | null; + }>; + + + export type UsersQuery = { __typename?: 'Query', users: Array<{ __typename: 'User' }> }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); +}); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts index f00eda06700..c2d4c58e33c 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -97,6 +97,12 @@ describe('TypeScript Operations Plugin - Standalone', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type ResponseErrorType = + | 'NOT_FOUND' + | 'INPUT_VALIDATION_ERROR' + | 'FORBIDDEN_ERROR' + | 'UNEXPECTED_ERROR'; + /** UserRole Description */ export type UserRole = /** UserRole ADMIN */ @@ -104,6 +110,15 @@ describe('TypeScript Operations Plugin - Standalone', () => { /** UserRole CUSTOMER */ | 'CUSTOMER'; + /** UsersInput Description */ + type UsersInput = { + /** UsersInput from */ + from?: any; + /** UsersInput to */ + to?: any; + role?: UserRole | null | undefined; + }; + export type UserQueryVariables = Exact<{ id: string; }>; @@ -139,6 +154,186 @@ describe('TypeScript Operations Plugin - Standalone', () => { // validateTs(content, undefined, undefined, undefined, undefined, true); }); + it('test generating input types enums in lists and inner field', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + users(input: UsersInput!): [User!]! + } + + type User { + id: ID! + } + + enum EnumRoot { + ENUM_A + ENUM_B + } + + enum EnumRootArray { + ENUM_C + ENUM_D + } + + enum EnumInnerArray { + ENUM_E + ENUM_F + } + + input EnumsInner { + enumsDeep: [EnumInnerArray!]! + } + + input UsersInput { + enum: EnumRoot! + enums: [EnumRootArray!]! + innerEnums: EnumsInner! + } + `); + const document = parse(/* GraphQL */ ` + query Users($input: UsersInput!) { + users(input: $input) { + id + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], {}, { outputFile: '' })]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type EnumRoot = + | 'ENUM_A' + | 'ENUM_B'; + + export type EnumRootArray = + | 'ENUM_C' + | 'ENUM_D'; + + export type EnumInnerArray = + | 'ENUM_E' + | 'ENUM_F'; + + type EnumsInner = { + enumsDeep: Array; + }; + + type UsersInput = { + enum: EnumRoot; + enums: Array; + innerEnums: EnumsInner; + }; + + export type UsersQueryVariables = Exact<{ + input: UsersInput; + }>; + + + export type UsersQuery = { __typename?: 'Query', users: Array<{ __typename?: 'User', id: string }> }; + " + `); + }); + + it('test generating output enums in lists and inner field', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User! + } + + enum EnumRoot { + ENUM_A + ENUM_B + } + + enum EnumRootArray { + ENUM_C + ENUM_D + } + + enum EnumInnerArray { + ENUM_E + ENUM_F + } + + type EnumsInner { + enumsDeep: [EnumInnerArray!]! + } + + type User { + enum: EnumRoot! + enums: [EnumRootArray!]! + innerEnums: EnumsInner! + } + `); + const document = parse(/* GraphQL */ ` + query User($id: ID!) { + user(id: $id) { + enum + enums + innerEnums { + enumsDeep + } + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + extractAllFieldsToTypes: true, // Extracts all fields to separate types (similar to apollo-codegen behavior) + printFieldsOnNewLines: true, // Prints each field on a new line (similar to apollo-codegen behavior) + }, + { + outputFile: '', + } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type EnumRoot = + | 'ENUM_A' + | 'ENUM_B'; + + export type EnumRootArray = + | 'ENUM_C' + | 'ENUM_D'; + + export type EnumInnerArray = + | 'ENUM_E' + | 'ENUM_F'; + + export type UserQuery_user_User_innerEnums_EnumsInner = { + __typename?: 'EnumsInner', + enumsDeep: Array + }; + + export type UserQuery_user_User = { + __typename?: 'User', + enum: EnumRoot, + enums: Array, + innerEnums: UserQuery_user_User_innerEnums_EnumsInner + }; + + export type UserQuery_Query = { + __typename?: 'Query', + user: UserQuery_user_User + }; + + + export type UserQueryVariables = Exact<{ + id: string; + }>; + + + export type UserQuery = UserQuery_Query; + " + `); + }); + it('test overrdiding config.scalars', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { @@ -176,6 +371,121 @@ describe('TypeScript Operations Plugin - Standalone', () => { `); }); + it('test render output enum from fragment in the same document', async () => { + const schema = buildSchema(/* GraphQL */ ` + enum RoleType { + ROLE_A + ROLE_B + } + + type User { + id: ID! + name: String! + role: RoleType + pictureUrl: String + } + + type Query { + users: [User!]! + viewer: User! + } + `); + const document = parse(/* GraphQL */ ` + fragment UserBasic on User { + id + name + role + } + + query GetUsersAndViewer { + users { + ...UserBasic + } + viewer { + ...UserBasic + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], {}, { outputFile: '' })]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type RoleType = + | 'ROLE_A' + | 'ROLE_B'; + + export type UserBasicFragment = { __typename?: 'User', id: string, name: string, role: RoleType | null }; + + export type GetUsersAndViewerQueryVariables = Exact<{ [key: string]: never; }>; + + + export type GetUsersAndViewerQuery = { __typename?: 'Query', users: Array<{ __typename?: 'User', id: string, name: string, role: RoleType | null }>, viewer: { __typename?: 'User', id: string, name: string, role: RoleType | null } }; + " + `); + }); + + it('test render output enum from fragment in a separate document', async () => { + const schema = buildSchema(/* GraphQL */ ` + enum RoleType { + ROLE_A + ROLE_B + } + + type User { + id: ID! + name: String! + role: RoleType + pictureUrl: String + } + + type Query { + users: [User!]! + viewer: User! + } + `); + + const documentWithFragment = parse(/* GraphQL */ ` + fragment UserBasic on User { + id + name + role + } + `); + + const documentMain = parse(/* GraphQL */ ` + query GetUsersAndViewer { + users { + ...UserBasic + } + viewer { + ...UserBasic + } + } + `); + + const result = mergeOutputs([ + await plugin(schema, [{ document: documentMain }, { document: documentWithFragment }], {}, { outputFile: '' }), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type RoleType = + | 'ROLE_A' + | 'ROLE_B'; + + export type GetUsersAndViewerQueryVariables = Exact<{ [key: string]: never; }>; + + + export type GetUsersAndViewerQuery = { __typename?: 'Query', users: Array<{ __typename?: 'User', id: string, name: string, role: RoleType | null }>, viewer: { __typename?: 'User', id: string, name: string, role: RoleType | null } }; + + export type UserBasicFragment = { __typename?: 'User', id: string, name: string, role: RoleType | null }; + " + `); + }); + it('does not generate Variables, Result or Fragments when generatesOperationTypes is false', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { @@ -294,6 +604,12 @@ describe('TypeScript Operations Plugin - Standalone', () => { expect(result).toMatchInlineSnapshot(` " + export type ResponseErrorType = + | 'NOT_FOUND' + | 'INPUT_VALIDATION_ERROR' + | 'FORBIDDEN_ERROR' + | 'UNEXPECTED_ERROR'; + /** UserRole Description */ export type UserRole = /** UserRole ADMIN */ @@ -301,6 +617,14 @@ describe('TypeScript Operations Plugin - Standalone', () => { /** UserRole CUSTOMER */ | 'CUSTOMER'; + /** UsersInput Description */ + type UsersInput = { + /** UsersInput from */ + from?: any; + /** UsersInput to */ + to?: any; + role?: UserRole | null | undefined; + }; " `); diff --git a/packages/presets/client/tests/client-preset.enum.spec.ts b/packages/presets/client/tests/client-preset.enum.spec.ts index 89267a0f05d..58ac2f6f67f 100644 --- a/packages/presets/client/tests/client-preset.enum.spec.ts +++ b/packages/presets/client/tests/client-preset.enum.spec.ts @@ -135,6 +135,10 @@ describe('client-preset - Enum', () => { import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type Shape = + | 'ROUND' + | 'SQUARE'; + export type ShapeQueryVariables = Exact<{ [key: string]: never; }>; From 2787f411cb3d573b7c005a228a66cf1c55c2e3d0 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Wed, 24 Dec 2025 22:39:50 +1100 Subject: [PATCH 14/69] =?UTF-8?q?Remove=20placeholder=20and=20test=20relea?= =?UTF-8?q?se=20=F0=9F=A4=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index f5ab64e989a..c74441baef3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ -FIXME:eddeee888 -
GraphQL Code Generator logo From daab272b928d99769576fe09f33db603deaf6bb2 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Wed, 24 Dec 2025 22:48:58 +1100 Subject: [PATCH 15/69] Test snapshot release --- .github/workflows/pr.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 4d05c7f9de2..102e5f252b2 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -3,6 +3,7 @@ on: pull_request: branches: - master + - master-next # FIXME:eddeee888 Remove once done concurrency: group: ${{ github.workflow }}-${{ github.ref }} From ed7c2fc0a16848652ff6df4130852076a867b251 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Tue, 30 Dec 2025 23:44:46 +1100 Subject: [PATCH 16/69] [typescript-operations] Fix __typename optionality and nullability (#10552) * Fix typename optionality and existence at Result root and types * Update tests * Update tests * Stop allowing skipTypename into Client Preset and typescript-operations, and update tests * Remove dependency on typescript plugin * Add changeset --- .changeset/real-numbers-fall.md | 14 + .../external-documents/app/types.generated.ts | 7 +- dev-test/githunt/typed-document-nodes.ts | 70 +- dev-test/githunt/types.avoidOptionals.ts | 66 +- dev-test/githunt/types.d.ts | 70 +- dev-test/githunt/types.enumsAsTypes.ts | 70 +- .../githunt/types.flatten.preResolveTypes.ts | 49 +- dev-test/githunt/types.immutableTypes.ts | 106 +- ...ypes.preResolveTypes.onlyOperationTypes.ts | 70 +- dev-test/githunt/types.preResolveTypes.ts | 70 +- dev-test/githunt/types.ts | 70 +- .../gql-tag-operations-masking/gql/graphql.ts | 17 +- .../gql-tag-operations-urql/gql/graphql.ts | 20 +- dev-test/gql-tag-operations/gql/graphql.ts | 20 +- .../gql-tag-operations/graphql/graphql.ts | 20 +- .../import-schema-types/_types.generated.ts | 5 +- dev-test/star-wars/types.avoidOptionals.ts | 101 +- dev-test/star-wars/types.excludeQueryAlpha.ts | 122 +- dev-test/star-wars/types.excludeQueryBeta.ts | 122 +- .../star-wars/types.globallyAvailable.d.ts | 131 +- dev-test/star-wars/types.immutableTypes.ts | 169 +- ...ypes.preResolveTypes.onlyOperationTypes.ts | 127 +- dev-test/star-wars/types.preResolveTypes.ts | 127 +- dev-test/star-wars/types.skipSchema.ts | 127 +- dev-test/star-wars/types.ts | 127 +- dev-test/test-null-value/result.d.ts | 6 +- ...ypes.preResolveTypes.onlyOperationTypes.ts | 1 - dev-test/test-schema/types.preResolveTypes.ts | 1 - .../src/gql/graphql.ts | 2 +- .../persisted-documents/src/gql/graphql.ts | 2 +- examples/react/apollo-client-defer/codegen.ts | 4 + .../apollo-client-defer/src/gql/graphql.ts | 13 +- examples/react/apollo-client/codegen.ts | 4 + .../react/apollo-client/src/gql/graphql.ts | 15 +- .../react/http-executor/src/gql/graphql.ts | 12 +- .../tanstack-react-query/src/gql/graphql.ts | 12 +- examples/react/urql/src/gql/graphql.ts | 12 +- examples/typescript-esm/src/gql/graphql.ts | 18 +- .../src/gql/graphql.ts | 18 +- .../vite/vite-react-cts/src/gql/graphql.ts | 12 +- .../vite/vite-react-mts/src/gql/graphql.ts | 12 +- .../vite/vite-react-ts/src/gql/graphql.ts | 12 +- .../vue/apollo-composable/src/gql/graphql.ts | 12 +- examples/vue/urql/src/gql/graphql.ts | 12 +- examples/vue/villus/src/gql/graphql.ts | 12 +- examples/yoga-tests/src/gql/graphql.ts | 4 +- .../src/base-documents-visitor.ts | 6 - .../src/selection-set-to-object.ts | 36 +- .../__snapshots__/ts-documents.spec.ts.snap | 316 +- .../tests/ts-documents.apolloUnmask.spec.ts | 34 +- .../tests/ts-documents.nullability.spec.ts | 4 - .../operations/tests/ts-documents.spec.ts | 2854 +++++++++-------- .../ts-documents.standalone.enum.spec.ts | 52 +- ...-documents.standalone.import-types.spec.ts | 26 +- .../ts-documents.standalone.input.spec.ts | 6 +- .../tests/ts-documents.standalone.spec.ts | 104 +- packages/presets/client/src/index.ts | 1 - .../client/tests/client-preset.enum.spec.ts | 6 +- .../tests/client-preset.nullability.spec.ts | 4 - .../client/tests/client-preset.spec.ts | 272 +- 60 files changed, 2296 insertions(+), 3518 deletions(-) create mode 100644 .changeset/real-numbers-fall.md diff --git a/.changeset/real-numbers-fall.md b/.changeset/real-numbers-fall.md new file mode 100644 index 00000000000..12c0cedbf52 --- /dev/null +++ b/.changeset/real-numbers-fall.md @@ -0,0 +1,14 @@ +--- +'@graphql-codegen/visitor-plugin-common': major +'@graphql-codegen/typescript-operations': major +'@graphql-codegen/client-preset': major +--- + +BREAKING CHANGE: Operation plugin and Client Preset no longer generates optional `__typename` for result type + +`__typenam` should not be in the request unless: + +- explicitly requested by the user +- automatically injected into the request by clients, such as Apollo Clients. + +Note: Apollo Client users can still use `nonOptionalTypename: true` and `skipTypeNameForRoot: true` to ensure generated types match the runtime behaviour. diff --git a/dev-test/external-documents/app/types.generated.ts b/dev-test/external-documents/app/types.generated.ts index 40b98b77936..2c99a5e5866 100644 --- a/dev-test/external-documents/app/types.generated.ts +++ b/dev-test/external-documents/app/types.generated.ts @@ -2,11 +2,10 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +export type UserRole = 'ADMIN' | 'CUSTOMER'; + export type UserQueryVariables = Exact<{ id: string; }>; -export type UserQuery = { - __typename?: 'Query'; - user?: { __typename?: 'User'; id: string; name: string; role: UserRole } | null; -}; +export type UserQuery = { user: { id: string; name: string; role: UserRole } | null }; diff --git a/dev-test/githunt/typed-document-nodes.ts b/dev-test/githunt/typed-document-nodes.ts index ccde4464efc..1bae63e7263 100644 --- a/dev-test/githunt/typed-document-nodes.ts +++ b/dev-test/githunt/typed-document-nodes.ts @@ -9,13 +9,11 @@ export type OnCommentAddedSubscriptionVariables = Exact<{ }>; export type OnCommentAddedSubscription = { - __typename?: 'Subscription'; commentAdded: { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null; }; @@ -26,23 +24,19 @@ export type CommentQueryVariables = Exact<{ }>; export type CommentQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string; html_url: string } | null; + currentUser: { login: string; html_url: string } | null; entry: { - __typename?: 'Entry'; id: number; createdAt: number; commentCount: number; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; comments: Array<{ - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null>; repository: { - __typename?: 'Repository'; description: string | null; open_issues_count: number | null; stargazers_count: number; @@ -53,37 +47,33 @@ export type CommentQuery = { }; export type CommentsPageCommentFragment = { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; }; export type CurrentUserForProfileQueryVariables = Exact<{ [key: string]: never }>; export type CurrentUserForProfileQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string; avatar_url: string } | null; + currentUser: { login: string; avatar_url: string } | null; }; export type FeedEntryFragment = { - __typename?: 'Entry'; id: number; commentCount: number; score: number; createdAt: number; repository: { - __typename?: 'Repository'; full_name: string; html_url: string; description: string | null; stargazers_count: number; open_issues_count: number | null; - owner: { __typename?: 'User'; avatar_url: string } | null; + owner: { avatar_url: string } | null; }; - vote: { __typename?: 'Vote'; vote_value: number }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + vote: { vote_value: number }; + postedBy: { html_url: string; login: string }; }; export type FeedQueryVariables = Exact<{ @@ -93,25 +83,22 @@ export type FeedQueryVariables = Exact<{ }>; export type FeedQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string } | null; + currentUser: { login: string } | null; feed: Array<{ - __typename?: 'Entry'; id: number; commentCount: number; score: number; createdAt: number; repository: { - __typename?: 'Repository'; full_name: string; html_url: string; description: string | null; stargazers_count: number; open_issues_count: number | null; - owner: { __typename?: 'User'; avatar_url: string } | null; + owner: { avatar_url: string } | null; }; - vote: { __typename?: 'Vote'; vote_value: number }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + vote: { vote_value: number }; + postedBy: { html_url: string; login: string }; } | null> | null; }; @@ -119,21 +106,16 @@ export type SubmitRepositoryMutationVariables = Exact<{ repoFullName: string; }>; -export type SubmitRepositoryMutation = { - __typename?: 'Mutation'; - submitRepository: { __typename?: 'Entry'; createdAt: number } | null; -}; +export type SubmitRepositoryMutation = { submitRepository: { createdAt: number } | null }; export type RepoInfoFragment = { - __typename?: 'Entry'; createdAt: number; repository: { - __typename?: 'Repository'; description: string | null; stargazers_count: number; open_issues_count: number | null; }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + postedBy: { html_url: string; login: string }; }; export type SubmitCommentMutationVariables = Exact<{ @@ -142,21 +124,15 @@ export type SubmitCommentMutationVariables = Exact<{ }>; export type SubmitCommentMutation = { - __typename?: 'Mutation'; submitComment: { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null; }; -export type VoteButtonsFragment = { - __typename?: 'Entry'; - score: number; - vote: { __typename?: 'Vote'; vote_value: number }; -}; +export type VoteButtonsFragment = { score: number; vote: { vote_value: number } }; export type VoteMutationVariables = Exact<{ repoFullName: string; @@ -164,17 +140,7 @@ export type VoteMutationVariables = Exact<{ }>; export type VoteMutation = { - __typename?: 'Mutation'; -<<<<<<< HEAD - vote?: { - __typename?: 'Entry'; - score: number; - id: number; - vote: { __typename?: 'Vote'; vote_value: number }; - } | null; -======= - vote: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number } } | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + vote: { score: number; id: number; vote: { vote_value: number } } | null; }; export const CommentsPageCommentFragmentDoc = { diff --git a/dev-test/githunt/types.avoidOptionals.ts b/dev-test/githunt/types.avoidOptionals.ts index 0a1908ad3af..36f1197dde8 100644 --- a/dev-test/githunt/types.avoidOptionals.ts +++ b/dev-test/githunt/types.avoidOptionals.ts @@ -7,13 +7,11 @@ export type OnCommentAddedSubscriptionVariables = Exact<{ }>; export type OnCommentAddedSubscription = { - __typename?: 'Subscription'; commentAdded: { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null; }; @@ -24,23 +22,19 @@ export type CommentQueryVariables = Exact<{ }>; export type CommentQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string; html_url: string } | null; + currentUser: { login: string; html_url: string } | null; entry: { - __typename?: 'Entry'; id: number; createdAt: number; commentCount: number; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; comments: Array<{ - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null>; repository: { - __typename?: 'Repository'; description: string | null; open_issues_count: number | null; stargazers_count: number; @@ -51,37 +45,33 @@ export type CommentQuery = { }; export type CommentsPageCommentFragment = { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; }; export type CurrentUserForProfileQueryVariables = Exact<{ [key: string]: never }>; export type CurrentUserForProfileQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string; avatar_url: string } | null; + currentUser: { login: string; avatar_url: string } | null; }; export type FeedEntryFragment = { - __typename?: 'Entry'; id: number; commentCount: number; score: number; createdAt: number; repository: { - __typename?: 'Repository'; full_name: string; html_url: string; description: string | null; stargazers_count: number; open_issues_count: number | null; - owner: { __typename?: 'User'; avatar_url: string } | null; + owner: { avatar_url: string } | null; }; - vote: { __typename?: 'Vote'; vote_value: number }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + vote: { vote_value: number }; + postedBy: { html_url: string; login: string }; }; export type FeedQueryVariables = Exact<{ @@ -91,25 +81,22 @@ export type FeedQueryVariables = Exact<{ }>; export type FeedQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string } | null; + currentUser: { login: string } | null; feed: Array<{ - __typename?: 'Entry'; id: number; commentCount: number; score: number; createdAt: number; repository: { - __typename?: 'Repository'; full_name: string; html_url: string; description: string | null; stargazers_count: number; open_issues_count: number | null; - owner: { __typename?: 'User'; avatar_url: string } | null; + owner: { avatar_url: string } | null; }; - vote: { __typename?: 'Vote'; vote_value: number }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + vote: { vote_value: number }; + postedBy: { html_url: string; login: string }; } | null> | null; }; @@ -117,21 +104,16 @@ export type SubmitRepositoryMutationVariables = Exact<{ repoFullName: string; }>; -export type SubmitRepositoryMutation = { - __typename?: 'Mutation'; - submitRepository: { __typename?: 'Entry'; createdAt: number } | null; -}; +export type SubmitRepositoryMutation = { submitRepository: { createdAt: number } | null }; export type RepoInfoFragment = { - __typename?: 'Entry'; createdAt: number; repository: { - __typename?: 'Repository'; description: string | null; stargazers_count: number; open_issues_count: number | null; }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + postedBy: { html_url: string; login: string }; }; export type SubmitCommentMutationVariables = Exact<{ @@ -140,21 +122,15 @@ export type SubmitCommentMutationVariables = Exact<{ }>; export type SubmitCommentMutation = { - __typename?: 'Mutation'; submitComment: { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null; }; -export type VoteButtonsFragment = { - __typename?: 'Entry'; - score: number; - vote: { __typename?: 'Vote'; vote_value: number }; -}; +export type VoteButtonsFragment = { score: number; vote: { vote_value: number } }; export type VoteMutationVariables = Exact<{ repoFullName: string; @@ -162,11 +138,5 @@ export type VoteMutationVariables = Exact<{ }>; export type VoteMutation = { - __typename?: 'Mutation'; - vote: { - __typename?: 'Entry'; - score: number; - id: number; - vote: { __typename?: 'Vote'; vote_value: number }; - } | null; + vote: { score: number; id: number; vote: { vote_value: number } } | null; }; diff --git a/dev-test/githunt/types.d.ts b/dev-test/githunt/types.d.ts index 486d055e08b..1f81c577172 100644 --- a/dev-test/githunt/types.d.ts +++ b/dev-test/githunt/types.d.ts @@ -7,13 +7,11 @@ export type OnCommentAddedSubscriptionVariables = Exact<{ }>; export type OnCommentAddedSubscription = { - __typename?: 'Subscription'; commentAdded: { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null; }; @@ -24,23 +22,19 @@ export type CommentQueryVariables = Exact<{ }>; export type CommentQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string; html_url: string } | null; + currentUser: { login: string; html_url: string } | null; entry: { - __typename?: 'Entry'; id: number; createdAt: number; commentCount: number; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; comments: Array<{ - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null>; repository: { - __typename?: 'Repository'; description: string | null; open_issues_count: number | null; stargazers_count: number; @@ -51,37 +45,33 @@ export type CommentQuery = { }; export type CommentsPageCommentFragment = { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; }; export type CurrentUserForProfileQueryVariables = Exact<{ [key: string]: never }>; export type CurrentUserForProfileQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string; avatar_url: string } | null; + currentUser: { login: string; avatar_url: string } | null; }; export type FeedEntryFragment = { - __typename?: 'Entry'; id: number; commentCount: number; score: number; createdAt: number; repository: { - __typename?: 'Repository'; full_name: string; html_url: string; description: string | null; stargazers_count: number; open_issues_count: number | null; - owner: { __typename?: 'User'; avatar_url: string } | null; + owner: { avatar_url: string } | null; }; - vote: { __typename?: 'Vote'; vote_value: number }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + vote: { vote_value: number }; + postedBy: { html_url: string; login: string }; }; export type FeedQueryVariables = Exact<{ @@ -91,25 +81,22 @@ export type FeedQueryVariables = Exact<{ }>; export type FeedQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string } | null; + currentUser: { login: string } | null; feed: Array<{ - __typename?: 'Entry'; id: number; commentCount: number; score: number; createdAt: number; repository: { - __typename?: 'Repository'; full_name: string; html_url: string; description: string | null; stargazers_count: number; open_issues_count: number | null; - owner: { __typename?: 'User'; avatar_url: string } | null; + owner: { avatar_url: string } | null; }; - vote: { __typename?: 'Vote'; vote_value: number }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + vote: { vote_value: number }; + postedBy: { html_url: string; login: string }; } | null> | null; }; @@ -117,21 +104,16 @@ export type SubmitRepositoryMutationVariables = Exact<{ repoFullName: string; }>; -export type SubmitRepositoryMutation = { - __typename?: 'Mutation'; - submitRepository: { __typename?: 'Entry'; createdAt: number } | null; -}; +export type SubmitRepositoryMutation = { submitRepository: { createdAt: number } | null }; export type RepoInfoFragment = { - __typename?: 'Entry'; createdAt: number; repository: { - __typename?: 'Repository'; description: string | null; stargazers_count: number; open_issues_count: number | null; }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + postedBy: { html_url: string; login: string }; }; export type SubmitCommentMutationVariables = Exact<{ @@ -140,21 +122,15 @@ export type SubmitCommentMutationVariables = Exact<{ }>; export type SubmitCommentMutation = { - __typename?: 'Mutation'; submitComment: { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null; }; -export type VoteButtonsFragment = { - __typename?: 'Entry'; - score: number; - vote: { __typename?: 'Vote'; vote_value: number }; -}; +export type VoteButtonsFragment = { score: number; vote: { vote_value: number } }; export type VoteMutationVariables = Exact<{ repoFullName: string; @@ -162,15 +138,5 @@ export type VoteMutationVariables = Exact<{ }>; export type VoteMutation = { - __typename?: 'Mutation'; -<<<<<<< HEAD - vote?: { - __typename?: 'Entry'; - score: number; - id: number; - vote: { __typename?: 'Vote'; vote_value: number }; - } | null; -======= - vote: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number } } | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + vote: { score: number; id: number; vote: { vote_value: number } } | null; }; diff --git a/dev-test/githunt/types.enumsAsTypes.ts b/dev-test/githunt/types.enumsAsTypes.ts index 486d055e08b..1f81c577172 100644 --- a/dev-test/githunt/types.enumsAsTypes.ts +++ b/dev-test/githunt/types.enumsAsTypes.ts @@ -7,13 +7,11 @@ export type OnCommentAddedSubscriptionVariables = Exact<{ }>; export type OnCommentAddedSubscription = { - __typename?: 'Subscription'; commentAdded: { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null; }; @@ -24,23 +22,19 @@ export type CommentQueryVariables = Exact<{ }>; export type CommentQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string; html_url: string } | null; + currentUser: { login: string; html_url: string } | null; entry: { - __typename?: 'Entry'; id: number; createdAt: number; commentCount: number; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; comments: Array<{ - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null>; repository: { - __typename?: 'Repository'; description: string | null; open_issues_count: number | null; stargazers_count: number; @@ -51,37 +45,33 @@ export type CommentQuery = { }; export type CommentsPageCommentFragment = { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; }; export type CurrentUserForProfileQueryVariables = Exact<{ [key: string]: never }>; export type CurrentUserForProfileQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string; avatar_url: string } | null; + currentUser: { login: string; avatar_url: string } | null; }; export type FeedEntryFragment = { - __typename?: 'Entry'; id: number; commentCount: number; score: number; createdAt: number; repository: { - __typename?: 'Repository'; full_name: string; html_url: string; description: string | null; stargazers_count: number; open_issues_count: number | null; - owner: { __typename?: 'User'; avatar_url: string } | null; + owner: { avatar_url: string } | null; }; - vote: { __typename?: 'Vote'; vote_value: number }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + vote: { vote_value: number }; + postedBy: { html_url: string; login: string }; }; export type FeedQueryVariables = Exact<{ @@ -91,25 +81,22 @@ export type FeedQueryVariables = Exact<{ }>; export type FeedQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string } | null; + currentUser: { login: string } | null; feed: Array<{ - __typename?: 'Entry'; id: number; commentCount: number; score: number; createdAt: number; repository: { - __typename?: 'Repository'; full_name: string; html_url: string; description: string | null; stargazers_count: number; open_issues_count: number | null; - owner: { __typename?: 'User'; avatar_url: string } | null; + owner: { avatar_url: string } | null; }; - vote: { __typename?: 'Vote'; vote_value: number }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + vote: { vote_value: number }; + postedBy: { html_url: string; login: string }; } | null> | null; }; @@ -117,21 +104,16 @@ export type SubmitRepositoryMutationVariables = Exact<{ repoFullName: string; }>; -export type SubmitRepositoryMutation = { - __typename?: 'Mutation'; - submitRepository: { __typename?: 'Entry'; createdAt: number } | null; -}; +export type SubmitRepositoryMutation = { submitRepository: { createdAt: number } | null }; export type RepoInfoFragment = { - __typename?: 'Entry'; createdAt: number; repository: { - __typename?: 'Repository'; description: string | null; stargazers_count: number; open_issues_count: number | null; }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + postedBy: { html_url: string; login: string }; }; export type SubmitCommentMutationVariables = Exact<{ @@ -140,21 +122,15 @@ export type SubmitCommentMutationVariables = Exact<{ }>; export type SubmitCommentMutation = { - __typename?: 'Mutation'; submitComment: { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null; }; -export type VoteButtonsFragment = { - __typename?: 'Entry'; - score: number; - vote: { __typename?: 'Vote'; vote_value: number }; -}; +export type VoteButtonsFragment = { score: number; vote: { vote_value: number } }; export type VoteMutationVariables = Exact<{ repoFullName: string; @@ -162,15 +138,5 @@ export type VoteMutationVariables = Exact<{ }>; export type VoteMutation = { - __typename?: 'Mutation'; -<<<<<<< HEAD - vote?: { - __typename?: 'Entry'; - score: number; - id: number; - vote: { __typename?: 'Vote'; vote_value: number }; - } | null; -======= - vote: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number } } | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + vote: { score: number; id: number; vote: { vote_value: number } } | null; }; diff --git a/dev-test/githunt/types.flatten.preResolveTypes.ts b/dev-test/githunt/types.flatten.preResolveTypes.ts index a6cb41ad34f..94e9f8bb1c4 100644 --- a/dev-test/githunt/types.flatten.preResolveTypes.ts +++ b/dev-test/githunt/types.flatten.preResolveTypes.ts @@ -7,13 +7,11 @@ export type OnCommentAddedSubscriptionVariables = Exact<{ }>; export type OnCommentAddedSubscription = { - __typename?: 'Subscription'; commentAdded: { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null; }; @@ -24,23 +22,19 @@ export type CommentQueryVariables = Exact<{ }>; export type CommentQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string; html_url: string } | null; + currentUser: { login: string; html_url: string } | null; entry: { - __typename?: 'Entry'; id: number; createdAt: number; commentCount: number; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; comments: Array<{ - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null>; repository: { - __typename?: 'Repository'; full_name: string; html_url: string; description: string | null; @@ -53,8 +47,7 @@ export type CommentQuery = { export type CurrentUserForProfileQueryVariables = Exact<{ [key: string]: never }>; export type CurrentUserForProfileQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string; avatar_url: string } | null; + currentUser: { login: string; avatar_url: string } | null; }; export type FeedQueryVariables = Exact<{ @@ -64,25 +57,22 @@ export type FeedQueryVariables = Exact<{ }>; export type FeedQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string } | null; + currentUser: { login: string } | null; feed: Array<{ - __typename?: 'Entry'; id: number; commentCount: number; score: number; createdAt: number; repository: { - __typename?: 'Repository'; full_name: string; html_url: string; description: string | null; stargazers_count: number; open_issues_count: number | null; - owner: { __typename?: 'User'; avatar_url: string } | null; + owner: { avatar_url: string } | null; }; - vote: { __typename?: 'Vote'; vote_value: number }; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + vote: { vote_value: number }; + postedBy: { login: string; html_url: string }; } | null> | null; }; @@ -90,10 +80,7 @@ export type SubmitRepositoryMutationVariables = Exact<{ repoFullName: string; }>; -export type SubmitRepositoryMutation = { - __typename?: 'Mutation'; - submitRepository: { __typename?: 'Entry'; createdAt: number } | null; -}; +export type SubmitRepositoryMutation = { submitRepository: { createdAt: number } | null }; export type SubmitCommentMutationVariables = Exact<{ repoFullName: string; @@ -101,13 +88,11 @@ export type SubmitCommentMutationVariables = Exact<{ }>; export type SubmitCommentMutation = { - __typename?: 'Mutation'; submitComment: { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null; }; @@ -117,15 +102,5 @@ export type VoteMutationVariables = Exact<{ }>; export type VoteMutation = { - __typename?: 'Mutation'; -<<<<<<< HEAD - vote?: { - __typename?: 'Entry'; - score: number; - id: number; - vote: { __typename?: 'Vote'; vote_value: number }; - } | null; -======= - vote: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number } } | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + vote: { score: number; id: number; vote: { vote_value: number } } | null; }; diff --git a/dev-test/githunt/types.immutableTypes.ts b/dev-test/githunt/types.immutableTypes.ts index 1edd0d4e96c..d98b6ab7b81 100644 --- a/dev-test/githunt/types.immutableTypes.ts +++ b/dev-test/githunt/types.immutableTypes.ts @@ -7,17 +7,11 @@ export type OnCommentAddedSubscriptionVariables = Exact<{ }>; export type OnCommentAddedSubscription = { - readonly __typename?: 'Subscription'; readonly commentAdded: { - readonly __typename?: 'Comment'; readonly id: number; readonly createdAt: number; readonly content: string; - readonly postedBy: { - readonly __typename?: 'User'; - readonly login: string; - readonly html_url: string; - }; + readonly postedBy: { readonly login: string; readonly html_url: string }; } | null; }; @@ -28,40 +22,19 @@ export type CommentQueryVariables = Exact<{ }>; export type CommentQuery = { - readonly __typename?: 'Query'; -<<<<<<< HEAD - readonly currentUser?: { - readonly __typename?: 'User'; - readonly login: string; - readonly html_url: string; - } | null; - readonly entry?: { -======= - readonly currentUser: { readonly __typename?: 'User'; readonly login: string; readonly html_url: string } | null; + readonly currentUser: { readonly login: string; readonly html_url: string } | null; readonly entry: { ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - readonly __typename?: 'Entry'; readonly id: number; readonly createdAt: number; readonly commentCount: number; - readonly postedBy: { - readonly __typename?: 'User'; - readonly login: string; - readonly html_url: string; - }; + readonly postedBy: { readonly login: string; readonly html_url: string }; readonly comments: ReadonlyArray<{ - readonly __typename?: 'Comment'; readonly id: number; readonly createdAt: number; readonly content: string; - readonly postedBy: { - readonly __typename?: 'User'; - readonly login: string; - readonly html_url: string; - }; + readonly postedBy: { readonly login: string; readonly html_url: string }; } | null>; readonly repository: { - readonly __typename?: 'Repository'; readonly description: string | null; readonly open_issues_count: number | null; readonly stargazers_count: number; @@ -72,53 +45,33 @@ export type CommentQuery = { }; export type CommentsPageCommentFragment = { - readonly __typename?: 'Comment'; readonly id: number; readonly createdAt: number; readonly content: string; - readonly postedBy: { - readonly __typename?: 'User'; - readonly login: string; - readonly html_url: string; - }; + readonly postedBy: { readonly login: string; readonly html_url: string }; }; export type CurrentUserForProfileQueryVariables = Exact<{ [key: string]: never }>; export type CurrentUserForProfileQuery = { - readonly __typename?: 'Query'; -<<<<<<< HEAD - readonly currentUser?: { - readonly __typename?: 'User'; - readonly login: string; - readonly avatar_url: string; - } | null; -======= - readonly currentUser: { readonly __typename?: 'User'; readonly login: string; readonly avatar_url: string } | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + readonly currentUser: { readonly login: string; readonly avatar_url: string } | null; }; export type FeedEntryFragment = { - readonly __typename?: 'Entry'; readonly id: number; readonly commentCount: number; readonly score: number; readonly createdAt: number; readonly repository: { - readonly __typename?: 'Repository'; readonly full_name: string; readonly html_url: string; readonly description: string | null; readonly stargazers_count: number; readonly open_issues_count: number | null; - readonly owner: { readonly __typename?: 'User'; readonly avatar_url: string } | null; - }; - readonly vote: { readonly __typename?: 'Vote'; readonly vote_value: number }; - readonly postedBy: { - readonly __typename?: 'User'; - readonly html_url: string; - readonly login: string; + readonly owner: { readonly avatar_url: string } | null; }; + readonly vote: { readonly vote_value: number }; + readonly postedBy: { readonly html_url: string; readonly login: string }; }; export type FeedQueryVariables = Exact<{ @@ -128,29 +81,22 @@ export type FeedQueryVariables = Exact<{ }>; export type FeedQuery = { - readonly __typename?: 'Query'; - readonly currentUser: { readonly __typename?: 'User'; readonly login: string } | null; + readonly currentUser: { readonly login: string } | null; readonly feed: ReadonlyArray<{ - readonly __typename?: 'Entry'; readonly id: number; readonly commentCount: number; readonly score: number; readonly createdAt: number; readonly repository: { - readonly __typename?: 'Repository'; readonly full_name: string; readonly html_url: string; readonly description: string | null; readonly stargazers_count: number; readonly open_issues_count: number | null; - readonly owner: { readonly __typename?: 'User'; readonly avatar_url: string } | null; - }; - readonly vote: { readonly __typename?: 'Vote'; readonly vote_value: number }; - readonly postedBy: { - readonly __typename?: 'User'; - readonly html_url: string; - readonly login: string; + readonly owner: { readonly avatar_url: string } | null; }; + readonly vote: { readonly vote_value: number }; + readonly postedBy: { readonly html_url: string; readonly login: string }; } | null> | null; }; @@ -159,24 +105,17 @@ export type SubmitRepositoryMutationVariables = Exact<{ }>; export type SubmitRepositoryMutation = { - readonly __typename?: 'Mutation'; - readonly submitRepository: { readonly __typename?: 'Entry'; readonly createdAt: number } | null; + readonly submitRepository: { readonly createdAt: number } | null; }; export type RepoInfoFragment = { - readonly __typename?: 'Entry'; readonly createdAt: number; readonly repository: { - readonly __typename?: 'Repository'; readonly description: string | null; readonly stargazers_count: number; readonly open_issues_count: number | null; }; - readonly postedBy: { - readonly __typename?: 'User'; - readonly html_url: string; - readonly login: string; - }; + readonly postedBy: { readonly html_url: string; readonly login: string }; }; export type SubmitCommentMutationVariables = Exact<{ @@ -185,24 +124,17 @@ export type SubmitCommentMutationVariables = Exact<{ }>; export type SubmitCommentMutation = { - readonly __typename?: 'Mutation'; readonly submitComment: { - readonly __typename?: 'Comment'; readonly id: number; readonly createdAt: number; readonly content: string; - readonly postedBy: { - readonly __typename?: 'User'; - readonly login: string; - readonly html_url: string; - }; + readonly postedBy: { readonly login: string; readonly html_url: string }; } | null; }; export type VoteButtonsFragment = { - readonly __typename?: 'Entry'; readonly score: number; - readonly vote: { readonly __typename?: 'Vote'; readonly vote_value: number }; + readonly vote: { readonly vote_value: number }; }; export type VoteMutationVariables = Exact<{ @@ -211,11 +143,9 @@ export type VoteMutationVariables = Exact<{ }>; export type VoteMutation = { - readonly __typename?: 'Mutation'; readonly vote: { - readonly __typename?: 'Entry'; readonly score: number; readonly id: number; - readonly vote: { readonly __typename?: 'Vote'; readonly vote_value: number }; + readonly vote: { readonly vote_value: number }; } | null; }; diff --git a/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts index 486d055e08b..1f81c577172 100644 --- a/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts @@ -7,13 +7,11 @@ export type OnCommentAddedSubscriptionVariables = Exact<{ }>; export type OnCommentAddedSubscription = { - __typename?: 'Subscription'; commentAdded: { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null; }; @@ -24,23 +22,19 @@ export type CommentQueryVariables = Exact<{ }>; export type CommentQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string; html_url: string } | null; + currentUser: { login: string; html_url: string } | null; entry: { - __typename?: 'Entry'; id: number; createdAt: number; commentCount: number; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; comments: Array<{ - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null>; repository: { - __typename?: 'Repository'; description: string | null; open_issues_count: number | null; stargazers_count: number; @@ -51,37 +45,33 @@ export type CommentQuery = { }; export type CommentsPageCommentFragment = { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; }; export type CurrentUserForProfileQueryVariables = Exact<{ [key: string]: never }>; export type CurrentUserForProfileQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string; avatar_url: string } | null; + currentUser: { login: string; avatar_url: string } | null; }; export type FeedEntryFragment = { - __typename?: 'Entry'; id: number; commentCount: number; score: number; createdAt: number; repository: { - __typename?: 'Repository'; full_name: string; html_url: string; description: string | null; stargazers_count: number; open_issues_count: number | null; - owner: { __typename?: 'User'; avatar_url: string } | null; + owner: { avatar_url: string } | null; }; - vote: { __typename?: 'Vote'; vote_value: number }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + vote: { vote_value: number }; + postedBy: { html_url: string; login: string }; }; export type FeedQueryVariables = Exact<{ @@ -91,25 +81,22 @@ export type FeedQueryVariables = Exact<{ }>; export type FeedQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string } | null; + currentUser: { login: string } | null; feed: Array<{ - __typename?: 'Entry'; id: number; commentCount: number; score: number; createdAt: number; repository: { - __typename?: 'Repository'; full_name: string; html_url: string; description: string | null; stargazers_count: number; open_issues_count: number | null; - owner: { __typename?: 'User'; avatar_url: string } | null; + owner: { avatar_url: string } | null; }; - vote: { __typename?: 'Vote'; vote_value: number }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + vote: { vote_value: number }; + postedBy: { html_url: string; login: string }; } | null> | null; }; @@ -117,21 +104,16 @@ export type SubmitRepositoryMutationVariables = Exact<{ repoFullName: string; }>; -export type SubmitRepositoryMutation = { - __typename?: 'Mutation'; - submitRepository: { __typename?: 'Entry'; createdAt: number } | null; -}; +export type SubmitRepositoryMutation = { submitRepository: { createdAt: number } | null }; export type RepoInfoFragment = { - __typename?: 'Entry'; createdAt: number; repository: { - __typename?: 'Repository'; description: string | null; stargazers_count: number; open_issues_count: number | null; }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + postedBy: { html_url: string; login: string }; }; export type SubmitCommentMutationVariables = Exact<{ @@ -140,21 +122,15 @@ export type SubmitCommentMutationVariables = Exact<{ }>; export type SubmitCommentMutation = { - __typename?: 'Mutation'; submitComment: { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null; }; -export type VoteButtonsFragment = { - __typename?: 'Entry'; - score: number; - vote: { __typename?: 'Vote'; vote_value: number }; -}; +export type VoteButtonsFragment = { score: number; vote: { vote_value: number } }; export type VoteMutationVariables = Exact<{ repoFullName: string; @@ -162,15 +138,5 @@ export type VoteMutationVariables = Exact<{ }>; export type VoteMutation = { - __typename?: 'Mutation'; -<<<<<<< HEAD - vote?: { - __typename?: 'Entry'; - score: number; - id: number; - vote: { __typename?: 'Vote'; vote_value: number }; - } | null; -======= - vote: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number } } | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + vote: { score: number; id: number; vote: { vote_value: number } } | null; }; diff --git a/dev-test/githunt/types.preResolveTypes.ts b/dev-test/githunt/types.preResolveTypes.ts index 486d055e08b..1f81c577172 100644 --- a/dev-test/githunt/types.preResolveTypes.ts +++ b/dev-test/githunt/types.preResolveTypes.ts @@ -7,13 +7,11 @@ export type OnCommentAddedSubscriptionVariables = Exact<{ }>; export type OnCommentAddedSubscription = { - __typename?: 'Subscription'; commentAdded: { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null; }; @@ -24,23 +22,19 @@ export type CommentQueryVariables = Exact<{ }>; export type CommentQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string; html_url: string } | null; + currentUser: { login: string; html_url: string } | null; entry: { - __typename?: 'Entry'; id: number; createdAt: number; commentCount: number; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; comments: Array<{ - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null>; repository: { - __typename?: 'Repository'; description: string | null; open_issues_count: number | null; stargazers_count: number; @@ -51,37 +45,33 @@ export type CommentQuery = { }; export type CommentsPageCommentFragment = { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; }; export type CurrentUserForProfileQueryVariables = Exact<{ [key: string]: never }>; export type CurrentUserForProfileQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string; avatar_url: string } | null; + currentUser: { login: string; avatar_url: string } | null; }; export type FeedEntryFragment = { - __typename?: 'Entry'; id: number; commentCount: number; score: number; createdAt: number; repository: { - __typename?: 'Repository'; full_name: string; html_url: string; description: string | null; stargazers_count: number; open_issues_count: number | null; - owner: { __typename?: 'User'; avatar_url: string } | null; + owner: { avatar_url: string } | null; }; - vote: { __typename?: 'Vote'; vote_value: number }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + vote: { vote_value: number }; + postedBy: { html_url: string; login: string }; }; export type FeedQueryVariables = Exact<{ @@ -91,25 +81,22 @@ export type FeedQueryVariables = Exact<{ }>; export type FeedQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string } | null; + currentUser: { login: string } | null; feed: Array<{ - __typename?: 'Entry'; id: number; commentCount: number; score: number; createdAt: number; repository: { - __typename?: 'Repository'; full_name: string; html_url: string; description: string | null; stargazers_count: number; open_issues_count: number | null; - owner: { __typename?: 'User'; avatar_url: string } | null; + owner: { avatar_url: string } | null; }; - vote: { __typename?: 'Vote'; vote_value: number }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + vote: { vote_value: number }; + postedBy: { html_url: string; login: string }; } | null> | null; }; @@ -117,21 +104,16 @@ export type SubmitRepositoryMutationVariables = Exact<{ repoFullName: string; }>; -export type SubmitRepositoryMutation = { - __typename?: 'Mutation'; - submitRepository: { __typename?: 'Entry'; createdAt: number } | null; -}; +export type SubmitRepositoryMutation = { submitRepository: { createdAt: number } | null }; export type RepoInfoFragment = { - __typename?: 'Entry'; createdAt: number; repository: { - __typename?: 'Repository'; description: string | null; stargazers_count: number; open_issues_count: number | null; }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + postedBy: { html_url: string; login: string }; }; export type SubmitCommentMutationVariables = Exact<{ @@ -140,21 +122,15 @@ export type SubmitCommentMutationVariables = Exact<{ }>; export type SubmitCommentMutation = { - __typename?: 'Mutation'; submitComment: { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null; }; -export type VoteButtonsFragment = { - __typename?: 'Entry'; - score: number; - vote: { __typename?: 'Vote'; vote_value: number }; -}; +export type VoteButtonsFragment = { score: number; vote: { vote_value: number } }; export type VoteMutationVariables = Exact<{ repoFullName: string; @@ -162,15 +138,5 @@ export type VoteMutationVariables = Exact<{ }>; export type VoteMutation = { - __typename?: 'Mutation'; -<<<<<<< HEAD - vote?: { - __typename?: 'Entry'; - score: number; - id: number; - vote: { __typename?: 'Vote'; vote_value: number }; - } | null; -======= - vote: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number } } | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + vote: { score: number; id: number; vote: { vote_value: number } } | null; }; diff --git a/dev-test/githunt/types.ts b/dev-test/githunt/types.ts index 486d055e08b..1f81c577172 100644 --- a/dev-test/githunt/types.ts +++ b/dev-test/githunt/types.ts @@ -7,13 +7,11 @@ export type OnCommentAddedSubscriptionVariables = Exact<{ }>; export type OnCommentAddedSubscription = { - __typename?: 'Subscription'; commentAdded: { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null; }; @@ -24,23 +22,19 @@ export type CommentQueryVariables = Exact<{ }>; export type CommentQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string; html_url: string } | null; + currentUser: { login: string; html_url: string } | null; entry: { - __typename?: 'Entry'; id: number; createdAt: number; commentCount: number; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; comments: Array<{ - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null>; repository: { - __typename?: 'Repository'; description: string | null; open_issues_count: number | null; stargazers_count: number; @@ -51,37 +45,33 @@ export type CommentQuery = { }; export type CommentsPageCommentFragment = { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; }; export type CurrentUserForProfileQueryVariables = Exact<{ [key: string]: never }>; export type CurrentUserForProfileQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string; avatar_url: string } | null; + currentUser: { login: string; avatar_url: string } | null; }; export type FeedEntryFragment = { - __typename?: 'Entry'; id: number; commentCount: number; score: number; createdAt: number; repository: { - __typename?: 'Repository'; full_name: string; html_url: string; description: string | null; stargazers_count: number; open_issues_count: number | null; - owner: { __typename?: 'User'; avatar_url: string } | null; + owner: { avatar_url: string } | null; }; - vote: { __typename?: 'Vote'; vote_value: number }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + vote: { vote_value: number }; + postedBy: { html_url: string; login: string }; }; export type FeedQueryVariables = Exact<{ @@ -91,25 +81,22 @@ export type FeedQueryVariables = Exact<{ }>; export type FeedQuery = { - __typename?: 'Query'; - currentUser: { __typename?: 'User'; login: string } | null; + currentUser: { login: string } | null; feed: Array<{ - __typename?: 'Entry'; id: number; commentCount: number; score: number; createdAt: number; repository: { - __typename?: 'Repository'; full_name: string; html_url: string; description: string | null; stargazers_count: number; open_issues_count: number | null; - owner: { __typename?: 'User'; avatar_url: string } | null; + owner: { avatar_url: string } | null; }; - vote: { __typename?: 'Vote'; vote_value: number }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + vote: { vote_value: number }; + postedBy: { html_url: string; login: string }; } | null> | null; }; @@ -117,21 +104,16 @@ export type SubmitRepositoryMutationVariables = Exact<{ repoFullName: string; }>; -export type SubmitRepositoryMutation = { - __typename?: 'Mutation'; - submitRepository: { __typename?: 'Entry'; createdAt: number } | null; -}; +export type SubmitRepositoryMutation = { submitRepository: { createdAt: number } | null }; export type RepoInfoFragment = { - __typename?: 'Entry'; createdAt: number; repository: { - __typename?: 'Repository'; description: string | null; stargazers_count: number; open_issues_count: number | null; }; - postedBy: { __typename?: 'User'; html_url: string; login: string }; + postedBy: { html_url: string; login: string }; }; export type SubmitCommentMutationVariables = Exact<{ @@ -140,21 +122,15 @@ export type SubmitCommentMutationVariables = Exact<{ }>; export type SubmitCommentMutation = { - __typename?: 'Mutation'; submitComment: { - __typename?: 'Comment'; id: number; createdAt: number; content: string; - postedBy: { __typename?: 'User'; login: string; html_url: string }; + postedBy: { login: string; html_url: string }; } | null; }; -export type VoteButtonsFragment = { - __typename?: 'Entry'; - score: number; - vote: { __typename?: 'Vote'; vote_value: number }; -}; +export type VoteButtonsFragment = { score: number; vote: { vote_value: number } }; export type VoteMutationVariables = Exact<{ repoFullName: string; @@ -162,15 +138,5 @@ export type VoteMutationVariables = Exact<{ }>; export type VoteMutation = { - __typename?: 'Mutation'; -<<<<<<< HEAD - vote?: { - __typename?: 'Entry'; - score: number; - id: number; - vote: { __typename?: 'Vote'; vote_value: number }; - } | null; -======= - vote: { __typename?: 'Entry'; score: number; id: number; vote: { __typename?: 'Vote'; vote_value: number } } | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + vote: { score: number; id: number; vote: { vote_value: number } } | null; }; diff --git a/dev-test/gql-tag-operations-masking/gql/graphql.ts b/dev-test/gql-tag-operations-masking/gql/graphql.ts index 6c49fafb063..9dda1735a5d 100644 --- a/dev-test/gql-tag-operations-masking/gql/graphql.ts +++ b/dev-test/gql-tag-operations-masking/gql/graphql.ts @@ -5,33 +5,24 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -export type TweetFragmentFragment = ({ __typename?: 'Tweet'; id: string; body: string } & { +export type TweetFragmentFragment = ({ id: string; body: string } & { ' $fragmentRefs'?: { TweetAuthorFragmentFragment: TweetAuthorFragmentFragment }; }) & { ' $fragmentName'?: 'TweetFragmentFragment' }; export type TweetAuthorFragmentFragment = { - __typename?: 'Tweet'; id: string; - author: { __typename?: 'User'; id: string; username: string | null }; + author: { id: string; username: string | null }; } & { ' $fragmentName'?: 'TweetAuthorFragmentFragment' }; export type TweetsFragmentFragment = { - __typename?: 'Query'; -<<<<<<< HEAD - Tweets?: Array< - { __typename?: 'Tweet'; id: string } & { - ' $fragmentRefs'?: { TweetFragmentFragment: TweetFragmentFragment }; - } -======= Tweets: Array< - { __typename?: 'Tweet'; id: string } & { ' $fragmentRefs'?: { TweetFragmentFragment: TweetFragmentFragment } } ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + { id: string } & { ' $fragmentRefs'?: { TweetFragmentFragment: TweetFragmentFragment } } > | null; } & { ' $fragmentName'?: 'TweetsFragmentFragment' }; export type TweetAppQueryQueryVariables = Exact<{ [key: string]: never }>; -export type TweetAppQueryQuery = { __typename?: 'Query' } & { +export type TweetAppQueryQuery = { ' $fragmentRefs'?: { TweetsFragmentFragment: TweetsFragmentFragment }; }; diff --git a/dev-test/gql-tag-operations-urql/gql/graphql.ts b/dev-test/gql-tag-operations-urql/gql/graphql.ts index 8e21640fff8..aa5c16c9b1c 100644 --- a/dev-test/gql-tag-operations-urql/gql/graphql.ts +++ b/dev-test/gql-tag-operations-urql/gql/graphql.ts @@ -7,30 +7,16 @@ export type Incremental = | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type FooQueryVariables = Exact<{ [key: string]: never }>; -<<<<<<< HEAD -export type FooQuery = { - __typename?: 'Query'; - Tweets?: Array<{ __typename?: 'Tweet'; id: string } | null> | null; -}; -======= -export type FooQuery = { __typename?: 'Query'; Tweets: Array<{ __typename?: 'Tweet'; id: string } | null> | null }; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) +export type FooQuery = { Tweets: Array<{ id: string } | null> | null }; -export type LelFragment = { __typename?: 'Tweet'; id: string; body: string | null } & { +export type LelFragment = { id: string; body: string | null } & { ' $fragmentName'?: 'LelFragment'; }; export type BarQueryVariables = Exact<{ [key: string]: never }>; export type BarQuery = { - __typename?: 'Query'; -<<<<<<< HEAD - Tweets?: Array< - ({ __typename?: 'Tweet' } & { ' $fragmentRefs'?: { LelFragment: LelFragment } }) | null - > | null; -======= - Tweets: Array<({ __typename?: 'Tweet' } & { ' $fragmentRefs'?: { LelFragment: LelFragment } }) | null> | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + Tweets: Array<{ ' $fragmentRefs'?: { LelFragment: LelFragment } } | null> | null; }; export const LelFragmentDoc = { diff --git a/dev-test/gql-tag-operations/gql/graphql.ts b/dev-test/gql-tag-operations/gql/graphql.ts index 8e21640fff8..aa5c16c9b1c 100644 --- a/dev-test/gql-tag-operations/gql/graphql.ts +++ b/dev-test/gql-tag-operations/gql/graphql.ts @@ -7,30 +7,16 @@ export type Incremental = | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type FooQueryVariables = Exact<{ [key: string]: never }>; -<<<<<<< HEAD -export type FooQuery = { - __typename?: 'Query'; - Tweets?: Array<{ __typename?: 'Tweet'; id: string } | null> | null; -}; -======= -export type FooQuery = { __typename?: 'Query'; Tweets: Array<{ __typename?: 'Tweet'; id: string } | null> | null }; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) +export type FooQuery = { Tweets: Array<{ id: string } | null> | null }; -export type LelFragment = { __typename?: 'Tweet'; id: string; body: string | null } & { +export type LelFragment = { id: string; body: string | null } & { ' $fragmentName'?: 'LelFragment'; }; export type BarQueryVariables = Exact<{ [key: string]: never }>; export type BarQuery = { - __typename?: 'Query'; -<<<<<<< HEAD - Tweets?: Array< - ({ __typename?: 'Tweet' } & { ' $fragmentRefs'?: { LelFragment: LelFragment } }) | null - > | null; -======= - Tweets: Array<({ __typename?: 'Tweet' } & { ' $fragmentRefs'?: { LelFragment: LelFragment } }) | null> | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + Tweets: Array<{ ' $fragmentRefs'?: { LelFragment: LelFragment } } | null> | null; }; export const LelFragmentDoc = { diff --git a/dev-test/gql-tag-operations/graphql/graphql.ts b/dev-test/gql-tag-operations/graphql/graphql.ts index 8e21640fff8..aa5c16c9b1c 100644 --- a/dev-test/gql-tag-operations/graphql/graphql.ts +++ b/dev-test/gql-tag-operations/graphql/graphql.ts @@ -7,30 +7,16 @@ export type Incremental = | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type FooQueryVariables = Exact<{ [key: string]: never }>; -<<<<<<< HEAD -export type FooQuery = { - __typename?: 'Query'; - Tweets?: Array<{ __typename?: 'Tweet'; id: string } | null> | null; -}; -======= -export type FooQuery = { __typename?: 'Query'; Tweets: Array<{ __typename?: 'Tweet'; id: string } | null> | null }; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) +export type FooQuery = { Tweets: Array<{ id: string } | null> | null }; -export type LelFragment = { __typename?: 'Tweet'; id: string; body: string | null } & { +export type LelFragment = { id: string; body: string | null } & { ' $fragmentName'?: 'LelFragment'; }; export type BarQueryVariables = Exact<{ [key: string]: never }>; export type BarQuery = { - __typename?: 'Query'; -<<<<<<< HEAD - Tweets?: Array< - ({ __typename?: 'Tweet' } & { ' $fragmentRefs'?: { LelFragment: LelFragment } }) | null - > | null; -======= - Tweets: Array<({ __typename?: 'Tweet' } & { ' $fragmentRefs'?: { LelFragment: LelFragment } }) | null> | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + Tweets: Array<{ ' $fragmentRefs'?: { LelFragment: LelFragment } } | null> | null; }; export const LelFragmentDoc = { diff --git a/dev-test/standalone-operations/import-schema-types/_types.generated.ts b/dev-test/standalone-operations/import-schema-types/_types.generated.ts index 7727a8b4ac1..d1815ba4796 100644 --- a/dev-test/standalone-operations/import-schema-types/_types.generated.ts +++ b/dev-test/standalone-operations/import-schema-types/_types.generated.ts @@ -8,7 +8,4 @@ export type WithVariablesQueryVariables = Exact<{ role?: Types.UserRole | null; }>; -export type WithVariablesQuery = { - __typename?: 'Query'; - user: { __typename?: 'User'; id: string; name: string } | null; -}; +export type WithVariablesQuery = { user: { id: string; name: string } | null }; diff --git a/dev-test/star-wars/types.avoidOptionals.ts b/dev-test/star-wars/types.avoidOptionals.ts index bd588f1b5ef..da39a5549a9 100644 --- a/dev-test/star-wars/types.avoidOptionals.ts +++ b/dev-test/star-wars/types.avoidOptionals.ts @@ -1,10 +1,7 @@ type Exact = { [K in keyof T]: T[K] }; -<<<<<<< HEAD export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -======= -export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** The episodes in the Star Wars trilogy */ export type Episode = /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ @@ -14,66 +11,44 @@ export type Episode = /** Star Wars Episode IV: A New Hope, released in 1977. */ | 'NEWHOPE'; ->>>>>>> c7b5477b6 (Generate input types and output enums into target file (#10527)) export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; }>; export type CreateReviewForEpisodeMutation = { - __typename?: 'Mutation'; - createReview: { __typename?: 'Review'; stars: number; commentary: string | null } | null; + createReview: { stars: number; commentary: string | null } | null; }; export type ExcludeQueryAlphaQueryVariables = Exact<{ episode: Episode | null; }>; -export type ExcludeQueryAlphaQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +export type ExcludeQueryAlphaQuery = { hero: { name: string } | { name: string } | null }; export type ExcludeQueryBetaQueryVariables = Exact<{ episode: Episode | null; }>; -export type ExcludeQueryBetaQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +export type ExcludeQueryBetaQuery = { hero: { name: string } | { name: string } | null }; export type HeroAndFriendsNamesQueryVariables = Exact<{ episode: Episode | null; }>; export type HeroAndFriendsNamesQuery = { - __typename?: 'Query'; hero: - | { - __typename?: 'Droid'; - name: string; - friends: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null - > | null; - } - | { - __typename?: 'Human'; - name: string; - friends: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null - > | null; - } + | { name: string; friends: Array<{ name: string } | { name: string } | null> | null } + | { name: string; friends: Array<{ name: string } | { name: string } | null> | null } | null; }; export type HeroAppearsInQueryVariables = Exact<{ [key: string]: never }>; export type HeroAppearsInQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; name: string; appearsIn: Array } - | { __typename?: 'Human'; name: string; appearsIn: Array } + | { name: string; appearsIn: Array } + | { name: string; appearsIn: Array } | null; }; @@ -82,20 +57,15 @@ export type HeroDetailsQueryVariables = Exact<{ }>; export type HeroDetailsQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; primaryFunction: string | null; name: string } - | { __typename?: 'Human'; height: number | null; name: string } + | { primaryFunction: string | null; name: string } + | { height: number | null; name: string } | null; }; -type HeroDetails_Droid_Fragment = { - __typename?: 'Droid'; - primaryFunction: string | null; - name: string; -}; +type HeroDetails_Droid_Fragment = { primaryFunction: string | null; name: string }; -type HeroDetails_Human_Fragment = { __typename?: 'Human'; height: number | null; name: string }; +type HeroDetails_Human_Fragment = { height: number | null; name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; @@ -104,10 +74,9 @@ export type HeroDetailsWithFragmentQueryVariables = Exact<{ }>; export type HeroDetailsWithFragmentQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; primaryFunction: string | null; name: string } - | { __typename?: 'Human'; height: number | null; name: string } + | { primaryFunction: string | null; name: string } + | { height: number | null; name: string } | null; }; @@ -115,10 +84,7 @@ export type HeroNameQueryVariables = Exact<{ episode: Episode | null; }>; -export type HeroNameQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +export type HeroNameQuery = { hero: { name: string } | { name: string } | null }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ episode: Episode | null; @@ -126,8 +92,7 @@ export type HeroNameConditionalInclusionQueryVariables = Exact<{ }>; export type HeroNameConditionalInclusionQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { name?: string } | { name?: string } | null; }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ @@ -136,8 +101,7 @@ export type HeroNameConditionalExclusionQueryVariables = Exact<{ }>; export type HeroNameConditionalExclusionQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { name?: string } | { name?: string } | null; }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ @@ -145,25 +109,14 @@ export type HeroParentTypeDependentFieldQueryVariables = Exact<{ }>; export type HeroParentTypeDependentFieldQuery = { - __typename?: 'Query'; hero: | { - __typename?: 'Droid'; name: string; - friends: Array< - | { __typename?: 'Droid'; name: string } - | { __typename?: 'Human'; height: number | null; name: string } - | null - > | null; + friends: Array<{ name: string } | { height: number | null; name: string } | null> | null; } | { - __typename?: 'Human'; name: string; - friends: Array< - | { __typename?: 'Droid'; name: string } - | { __typename?: 'Human'; height: number | null; name: string } - | null - > | null; + friends: Array<{ name: string } | { height: number | null; name: string } | null> | null; } | null; }; @@ -173,26 +126,18 @@ export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ }>; export type HeroTypeDependentAliasedFieldQuery = { - __typename?: 'Query'; - hero: - | { __typename?: 'Droid'; property: string | null } - | { __typename?: 'Human'; property: string | null } - | null; + hero: { property: string | null } | { property: string | null } | null; }; -export type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass: number | null }; +export type HumanFieldsFragment = { name: string; mass: number | null }; export type HumanWithNullHeightQueryVariables = Exact<{ [key: string]: never }>; -export type HumanWithNullHeightQuery = { - __typename?: 'Query'; - human: { __typename?: 'Human'; name: string; mass: number | null } | null; -}; +export type HumanWithNullHeightQuery = { human: { name: string; mass: number | null } | null }; export type TwoHeroesQueryVariables = Exact<{ [key: string]: never }>; export type TwoHeroesQuery = { - __typename?: 'Query'; - r2: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; - luke: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + r2: { name: string } | { name: string } | null; + luke: { name: string } | { name: string } | null; }; diff --git a/dev-test/star-wars/types.excludeQueryAlpha.ts b/dev-test/star-wars/types.excludeQueryAlpha.ts index d294745831d..9e39464ddf0 100644 --- a/dev-test/star-wars/types.excludeQueryAlpha.ts +++ b/dev-test/star-wars/types.excludeQueryAlpha.ts @@ -1,10 +1,7 @@ type Exact = { [K in keyof T]: T[K] }; -<<<<<<< HEAD export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -======= -export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** The episodes in the Star Wars trilogy */ export type Episode = /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ @@ -14,65 +11,38 @@ export type Episode = /** Star Wars Episode IV: A New Hope, released in 1977. */ | 'NEWHOPE'; ->>>>>>> c7b5477b6 (Generate input types and output enums into target file (#10527)) export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; }>; export type CreateReviewForEpisodeMutation = { - __typename?: 'Mutation'; - createReview: { __typename?: 'Review'; stars: number; commentary: string | null } | null; + createReview: { stars: number; commentary: string | null } | null; }; export type ExcludeQueryBetaQueryVariables = Exact<{ episode?: Episode | null; }>; -export type ExcludeQueryBetaQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +export type ExcludeQueryBetaQuery = { hero: { name: string } | { name: string } | null }; export type HeroAndFriendsNamesQueryVariables = Exact<{ episode?: Episode | null; }>; export type HeroAndFriendsNamesQuery = { - __typename?: 'Query'; hero: - | { - __typename?: 'Droid'; - name: string; -<<<<<<< HEAD - friends?: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null - > | null; -======= - friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - } - | { - __typename?: 'Human'; - name: string; -<<<<<<< HEAD - friends?: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null - > | null; -======= - friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - } + | { name: string; friends: Array<{ name: string } | { name: string } | null> | null } + | { name: string; friends: Array<{ name: string } | { name: string } | null> | null } | null; }; export type HeroAppearsInQueryVariables = Exact<{ [key: string]: never }>; export type HeroAppearsInQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; name: string; appearsIn: Array } - | { __typename?: 'Human'; name: string; appearsIn: Array } + | { name: string; appearsIn: Array } + | { name: string; appearsIn: Array } | null; }; @@ -81,24 +51,15 @@ export type HeroDetailsQueryVariables = Exact<{ }>; export type HeroDetailsQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; primaryFunction: string | null; name: string } - | { __typename?: 'Human'; height: number | null; name: string } + | { primaryFunction: string | null; name: string } + | { height: number | null; name: string } | null; }; -<<<<<<< HEAD -type HeroDetails_Droid_Fragment = { - __typename?: 'Droid'; - primaryFunction?: string | null; - name: string; -}; -======= -type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction: string | null; name: string }; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) +type HeroDetails_Droid_Fragment = { primaryFunction: string | null; name: string }; -type HeroDetails_Human_Fragment = { __typename?: 'Human'; height: number | null; name: string }; +type HeroDetails_Human_Fragment = { height: number | null; name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; @@ -107,10 +68,9 @@ export type HeroDetailsWithFragmentQueryVariables = Exact<{ }>; export type HeroDetailsWithFragmentQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; primaryFunction: string | null; name: string } - | { __typename?: 'Human'; height: number | null; name: string } + | { primaryFunction: string | null; name: string } + | { height: number | null; name: string } | null; }; @@ -118,10 +78,7 @@ export type HeroNameQueryVariables = Exact<{ episode?: Episode | null; }>; -export type HeroNameQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +export type HeroNameQuery = { hero: { name: string } | { name: string } | null }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ episode?: Episode | null; @@ -129,8 +86,7 @@ export type HeroNameConditionalInclusionQueryVariables = Exact<{ }>; export type HeroNameConditionalInclusionQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { name?: string } | { name?: string } | null; }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ @@ -139,8 +95,7 @@ export type HeroNameConditionalExclusionQueryVariables = Exact<{ }>; export type HeroNameConditionalExclusionQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { name?: string } | { name?: string } | null; }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ @@ -148,35 +103,14 @@ export type HeroParentTypeDependentFieldQueryVariables = Exact<{ }>; export type HeroParentTypeDependentFieldQuery = { - __typename?: 'Query'; hero: | { - __typename?: 'Droid'; name: string; -<<<<<<< HEAD - friends?: Array< - | { __typename?: 'Droid'; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } - | null -======= - friends: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - > | null; + friends: Array<{ name: string } | { height: number | null; name: string } | null> | null; } | { - __typename?: 'Human'; name: string; -<<<<<<< HEAD - friends?: Array< - | { __typename?: 'Droid'; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } - | null -======= - friends: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - > | null; + friends: Array<{ name: string } | { height: number | null; name: string } | null> | null; } | null; }; @@ -186,30 +120,18 @@ export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ }>; export type HeroTypeDependentAliasedFieldQuery = { - __typename?: 'Query'; -<<<<<<< HEAD - hero?: - | { __typename?: 'Droid'; property?: string | null } - | { __typename?: 'Human'; property?: string | null } - | null; -======= - hero: { __typename?: 'Droid'; property: string | null } | { __typename?: 'Human'; property: string | null } | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + hero: { property: string | null } | { property: string | null } | null; }; -export type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass: number | null }; +export type HumanFieldsFragment = { name: string; mass: number | null }; export type HumanWithNullHeightQueryVariables = Exact<{ [key: string]: never }>; -export type HumanWithNullHeightQuery = { - __typename?: 'Query'; - human: { __typename?: 'Human'; name: string; mass: number | null } | null; -}; +export type HumanWithNullHeightQuery = { human: { name: string; mass: number | null } | null }; export type TwoHeroesQueryVariables = Exact<{ [key: string]: never }>; export type TwoHeroesQuery = { - __typename?: 'Query'; - r2: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; - luke: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + r2: { name: string } | { name: string } | null; + luke: { name: string } | { name: string } | null; }; diff --git a/dev-test/star-wars/types.excludeQueryBeta.ts b/dev-test/star-wars/types.excludeQueryBeta.ts index 172be46a898..ee1d68ff899 100644 --- a/dev-test/star-wars/types.excludeQueryBeta.ts +++ b/dev-test/star-wars/types.excludeQueryBeta.ts @@ -1,10 +1,7 @@ type Exact = { [K in keyof T]: T[K] }; -<<<<<<< HEAD export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -======= -export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** The episodes in the Star Wars trilogy */ export type Episode = /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ @@ -14,65 +11,38 @@ export type Episode = /** Star Wars Episode IV: A New Hope, released in 1977. */ | 'NEWHOPE'; ->>>>>>> c7b5477b6 (Generate input types and output enums into target file (#10527)) export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; }>; export type CreateReviewForEpisodeMutation = { - __typename?: 'Mutation'; - createReview: { __typename?: 'Review'; stars: number; commentary: string | null } | null; + createReview: { stars: number; commentary: string | null } | null; }; export type ExcludeQueryAlphaQueryVariables = Exact<{ episode?: Episode | null; }>; -export type ExcludeQueryAlphaQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +export type ExcludeQueryAlphaQuery = { hero: { name: string } | { name: string } | null }; export type HeroAndFriendsNamesQueryVariables = Exact<{ episode?: Episode | null; }>; export type HeroAndFriendsNamesQuery = { - __typename?: 'Query'; hero: - | { - __typename?: 'Droid'; - name: string; -<<<<<<< HEAD - friends?: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null - > | null; -======= - friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - } - | { - __typename?: 'Human'; - name: string; -<<<<<<< HEAD - friends?: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null - > | null; -======= - friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - } + | { name: string; friends: Array<{ name: string } | { name: string } | null> | null } + | { name: string; friends: Array<{ name: string } | { name: string } | null> | null } | null; }; export type HeroAppearsInQueryVariables = Exact<{ [key: string]: never }>; export type HeroAppearsInQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; name: string; appearsIn: Array } - | { __typename?: 'Human'; name: string; appearsIn: Array } + | { name: string; appearsIn: Array } + | { name: string; appearsIn: Array } | null; }; @@ -81,24 +51,15 @@ export type HeroDetailsQueryVariables = Exact<{ }>; export type HeroDetailsQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; primaryFunction: string | null; name: string } - | { __typename?: 'Human'; height: number | null; name: string } + | { primaryFunction: string | null; name: string } + | { height: number | null; name: string } | null; }; -<<<<<<< HEAD -type HeroDetails_Droid_Fragment = { - __typename?: 'Droid'; - primaryFunction?: string | null; - name: string; -}; -======= -type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction: string | null; name: string }; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) +type HeroDetails_Droid_Fragment = { primaryFunction: string | null; name: string }; -type HeroDetails_Human_Fragment = { __typename?: 'Human'; height: number | null; name: string }; +type HeroDetails_Human_Fragment = { height: number | null; name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; @@ -107,10 +68,9 @@ export type HeroDetailsWithFragmentQueryVariables = Exact<{ }>; export type HeroDetailsWithFragmentQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; primaryFunction: string | null; name: string } - | { __typename?: 'Human'; height: number | null; name: string } + | { primaryFunction: string | null; name: string } + | { height: number | null; name: string } | null; }; @@ -118,10 +78,7 @@ export type HeroNameQueryVariables = Exact<{ episode?: Episode | null; }>; -export type HeroNameQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +export type HeroNameQuery = { hero: { name: string } | { name: string } | null }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ episode?: Episode | null; @@ -129,8 +86,7 @@ export type HeroNameConditionalInclusionQueryVariables = Exact<{ }>; export type HeroNameConditionalInclusionQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { name?: string } | { name?: string } | null; }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ @@ -139,8 +95,7 @@ export type HeroNameConditionalExclusionQueryVariables = Exact<{ }>; export type HeroNameConditionalExclusionQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { name?: string } | { name?: string } | null; }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ @@ -148,35 +103,14 @@ export type HeroParentTypeDependentFieldQueryVariables = Exact<{ }>; export type HeroParentTypeDependentFieldQuery = { - __typename?: 'Query'; hero: | { - __typename?: 'Droid'; name: string; -<<<<<<< HEAD - friends?: Array< - | { __typename?: 'Droid'; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } - | null -======= - friends: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - > | null; + friends: Array<{ name: string } | { height: number | null; name: string } | null> | null; } | { - __typename?: 'Human'; name: string; -<<<<<<< HEAD - friends?: Array< - | { __typename?: 'Droid'; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } - | null -======= - friends: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - > | null; + friends: Array<{ name: string } | { height: number | null; name: string } | null> | null; } | null; }; @@ -186,30 +120,18 @@ export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ }>; export type HeroTypeDependentAliasedFieldQuery = { - __typename?: 'Query'; -<<<<<<< HEAD - hero?: - | { __typename?: 'Droid'; property?: string | null } - | { __typename?: 'Human'; property?: string | null } - | null; -======= - hero: { __typename?: 'Droid'; property: string | null } | { __typename?: 'Human'; property: string | null } | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + hero: { property: string | null } | { property: string | null } | null; }; -export type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass: number | null }; +export type HumanFieldsFragment = { name: string; mass: number | null }; export type HumanWithNullHeightQueryVariables = Exact<{ [key: string]: never }>; -export type HumanWithNullHeightQuery = { - __typename?: 'Query'; - human: { __typename?: 'Human'; name: string; mass: number | null } | null; -}; +export type HumanWithNullHeightQuery = { human: { name: string; mass: number | null } | null }; export type TwoHeroesQueryVariables = Exact<{ [key: string]: never }>; export type TwoHeroesQuery = { - __typename?: 'Query'; - r2: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; - luke: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + r2: { name: string } | { name: string } | null; + luke: { name: string } | { name: string } | null; }; diff --git a/dev-test/star-wars/types.globallyAvailable.d.ts b/dev-test/star-wars/types.globallyAvailable.d.ts index 9409ec381b3..36d3f1a7b10 100644 --- a/dev-test/star-wars/types.globallyAvailable.d.ts +++ b/dev-test/star-wars/types.globallyAvailable.d.ts @@ -1,10 +1,7 @@ type Exact = { [K in keyof T]: T[K] }; -<<<<<<< HEAD export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -======= -export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** The episodes in the Star Wars trilogy */ type Episode = /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ @@ -14,74 +11,44 @@ type Episode = /** Star Wars Episode IV: A New Hope, released in 1977. */ | 'NEWHOPE'; ->>>>>>> c7b5477b6 (Generate input types and output enums into target file (#10527)) type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; }>; type CreateReviewForEpisodeMutation = { - __typename?: 'Mutation'; - createReview: { __typename?: 'Review'; stars: number; commentary: string | null } | null; + createReview: { stars: number; commentary: string | null } | null; }; type ExcludeQueryAlphaQueryVariables = Exact<{ episode?: Episode | null; }>; -type ExcludeQueryAlphaQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +type ExcludeQueryAlphaQuery = { hero: { name: string } | { name: string } | null }; type ExcludeQueryBetaQueryVariables = Exact<{ episode?: Episode | null; }>; -type ExcludeQueryBetaQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +type ExcludeQueryBetaQuery = { hero: { name: string } | { name: string } | null }; type HeroAndFriendsNamesQueryVariables = Exact<{ episode?: Episode | null; }>; type HeroAndFriendsNamesQuery = { - __typename?: 'Query'; hero: - | { - __typename?: 'Droid'; - name: string; -<<<<<<< HEAD - friends?: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null - > | null; -======= - friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - } - | { - __typename?: 'Human'; - name: string; -<<<<<<< HEAD - friends?: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null - > | null; -======= - friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - } + | { name: string; friends: Array<{ name: string } | { name: string } | null> | null } + | { name: string; friends: Array<{ name: string } | { name: string } | null> | null } | null; }; type HeroAppearsInQueryVariables = Exact<{ [key: string]: never }>; type HeroAppearsInQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; name: string; appearsIn: Array } - | { __typename?: 'Human'; name: string; appearsIn: Array } + | { name: string; appearsIn: Array } + | { name: string; appearsIn: Array } | null; }; @@ -90,24 +57,15 @@ type HeroDetailsQueryVariables = Exact<{ }>; type HeroDetailsQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; primaryFunction: string | null; name: string } - | { __typename?: 'Human'; height: number | null; name: string } + | { primaryFunction: string | null; name: string } + | { height: number | null; name: string } | null; }; -<<<<<<< HEAD -type HeroDetails_Droid_Fragment = { - __typename?: 'Droid'; - primaryFunction?: string | null; - name: string; -}; -======= -type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction: string | null; name: string }; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) +type HeroDetails_Droid_Fragment = { primaryFunction: string | null; name: string }; -type HeroDetails_Human_Fragment = { __typename?: 'Human'; height: number | null; name: string }; +type HeroDetails_Human_Fragment = { height: number | null; name: string }; type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; @@ -116,10 +74,9 @@ type HeroDetailsWithFragmentQueryVariables = Exact<{ }>; type HeroDetailsWithFragmentQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; primaryFunction: string | null; name: string } - | { __typename?: 'Human'; height: number | null; name: string } + | { primaryFunction: string | null; name: string } + | { height: number | null; name: string } | null; }; @@ -127,65 +84,35 @@ type HeroNameQueryVariables = Exact<{ episode?: Episode | null; }>; -type HeroNameQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +type HeroNameQuery = { hero: { name: string } | { name: string } | null }; type HeroNameConditionalInclusionQueryVariables = Exact<{ episode?: Episode | null; includeName: boolean; }>; -type HeroNameConditionalInclusionQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; -}; +type HeroNameConditionalInclusionQuery = { hero: { name?: string } | { name?: string } | null }; type HeroNameConditionalExclusionQueryVariables = Exact<{ episode?: Episode | null; skipName: boolean; }>; -type HeroNameConditionalExclusionQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; -}; +type HeroNameConditionalExclusionQuery = { hero: { name?: string } | { name?: string } | null }; type HeroParentTypeDependentFieldQueryVariables = Exact<{ episode?: Episode | null; }>; type HeroParentTypeDependentFieldQuery = { - __typename?: 'Query'; hero: | { - __typename?: 'Droid'; name: string; -<<<<<<< HEAD - friends?: Array< - | { __typename?: 'Droid'; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } - | null -======= - friends: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - > | null; + friends: Array<{ name: string } | { height: number | null; name: string } | null> | null; } | { - __typename?: 'Human'; name: string; -<<<<<<< HEAD - friends?: Array< - | { __typename?: 'Droid'; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } - | null -======= - friends: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - > | null; + friends: Array<{ name: string } | { height: number | null; name: string } | null> | null; } | null; }; @@ -195,30 +122,18 @@ type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ }>; type HeroTypeDependentAliasedFieldQuery = { - __typename?: 'Query'; -<<<<<<< HEAD - hero?: - | { __typename?: 'Droid'; property?: string | null } - | { __typename?: 'Human'; property?: string | null } - | null; -======= - hero: { __typename?: 'Droid'; property: string | null } | { __typename?: 'Human'; property: string | null } | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + hero: { property: string | null } | { property: string | null } | null; }; -type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass: number | null }; +type HumanFieldsFragment = { name: string; mass: number | null }; type HumanWithNullHeightQueryVariables = Exact<{ [key: string]: never }>; -type HumanWithNullHeightQuery = { - __typename?: 'Query'; - human: { __typename?: 'Human'; name: string; mass: number | null } | null; -}; +type HumanWithNullHeightQuery = { human: { name: string; mass: number | null } | null }; type TwoHeroesQueryVariables = Exact<{ [key: string]: never }>; type TwoHeroesQuery = { - __typename?: 'Query'; - r2: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; - luke: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + r2: { name: string } | { name: string } | null; + luke: { name: string } | { name: string } | null; }; diff --git a/dev-test/star-wars/types.immutableTypes.ts b/dev-test/star-wars/types.immutableTypes.ts index 79acc648d06..d8335653496 100644 --- a/dev-test/star-wars/types.immutableTypes.ts +++ b/dev-test/star-wars/types.immutableTypes.ts @@ -1,10 +1,7 @@ type Exact = { [K in keyof T]: T[K] }; -<<<<<<< HEAD export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -======= -export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** The episodes in the Star Wars trilogy */ export type Episode = /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ @@ -14,19 +11,13 @@ export type Episode = /** Star Wars Episode IV: A New Hope, released in 1977. */ | 'NEWHOPE'; ->>>>>>> c7b5477b6 (Generate input types and output enums into target file (#10527)) export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; }>; export type CreateReviewForEpisodeMutation = { - readonly __typename?: 'Mutation'; - readonly createReview: { - readonly __typename?: 'Review'; - readonly stars: number; - readonly commentary: string | null; - } | null; + readonly createReview: { readonly stars: number; readonly commentary: string | null } | null; }; export type ExcludeQueryAlphaQueryVariables = Exact<{ @@ -34,11 +25,7 @@ export type ExcludeQueryAlphaQueryVariables = Exact<{ }>; export type ExcludeQueryAlphaQuery = { - readonly __typename?: 'Query'; - readonly hero: - | { readonly __typename?: 'Droid'; readonly name: string } - | { readonly __typename?: 'Human'; readonly name: string } - | null; + readonly hero: { readonly name: string } | { readonly name: string } | null; }; export type ExcludeQueryBetaQueryVariables = Exact<{ @@ -46,11 +33,7 @@ export type ExcludeQueryBetaQueryVariables = Exact<{ }>; export type ExcludeQueryBetaQuery = { - readonly __typename?: 'Query'; - readonly hero: - | { readonly __typename?: 'Droid'; readonly name: string } - | { readonly __typename?: 'Human'; readonly name: string } - | null; + readonly hero: { readonly name: string } | { readonly name: string } | null; }; export type HeroAndFriendsNamesQueryVariables = Exact<{ @@ -58,24 +41,17 @@ export type HeroAndFriendsNamesQueryVariables = Exact<{ }>; export type HeroAndFriendsNamesQuery = { - readonly __typename?: 'Query'; readonly hero: | { - readonly __typename?: 'Droid'; readonly name: string; readonly friends: ReadonlyArray< - | { readonly __typename?: 'Droid'; readonly name: string } - | { readonly __typename?: 'Human'; readonly name: string } - | null + { readonly name: string } | { readonly name: string } | null > | null; } | { - readonly __typename?: 'Human'; readonly name: string; readonly friends: ReadonlyArray< - | { readonly __typename?: 'Droid'; readonly name: string } - | { readonly __typename?: 'Human'; readonly name: string } - | null + { readonly name: string } | { readonly name: string } | null > | null; } | null; @@ -84,24 +60,9 @@ export type HeroAndFriendsNamesQuery = { export type HeroAppearsInQueryVariables = Exact<{ [key: string]: never }>; export type HeroAppearsInQuery = { - readonly __typename?: 'Query'; -<<<<<<< HEAD - readonly hero?: - | { - readonly __typename?: 'Droid'; - readonly name: string; - readonly appearsIn: ReadonlyArray; - } - | { - readonly __typename?: 'Human'; - readonly name: string; - readonly appearsIn: ReadonlyArray; - } -======= readonly hero: - | { readonly __typename?: 'Droid'; readonly name: string; readonly appearsIn: ReadonlyArray } - | { readonly __typename?: 'Human'; readonly name: string; readonly appearsIn: ReadonlyArray } ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + | { readonly name: string; readonly appearsIn: ReadonlyArray } + | { readonly name: string; readonly appearsIn: ReadonlyArray } | null; }; @@ -110,34 +71,18 @@ export type HeroDetailsQueryVariables = Exact<{ }>; export type HeroDetailsQuery = { - readonly __typename?: 'Query'; -<<<<<<< HEAD - readonly hero?: - | { - readonly __typename?: 'Droid'; - readonly primaryFunction?: string | null; - readonly name: string; - } - | { readonly __typename?: 'Human'; readonly height?: number | null; readonly name: string } -======= readonly hero: - | { readonly __typename?: 'Droid'; readonly primaryFunction: string | null; readonly name: string } - | { readonly __typename?: 'Human'; readonly height: number | null; readonly name: string } ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + | { readonly primaryFunction: string | null; readonly name: string } + | { readonly height: number | null; readonly name: string } | null; }; type HeroDetails_Droid_Fragment = { - readonly __typename?: 'Droid'; readonly primaryFunction: string | null; readonly name: string; }; -type HeroDetails_Human_Fragment = { - readonly __typename?: 'Human'; - readonly height: number | null; - readonly name: string; -}; +type HeroDetails_Human_Fragment = { readonly height: number | null; readonly name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; @@ -146,20 +91,9 @@ export type HeroDetailsWithFragmentQueryVariables = Exact<{ }>; export type HeroDetailsWithFragmentQuery = { - readonly __typename?: 'Query'; -<<<<<<< HEAD - readonly hero?: - | { - readonly __typename?: 'Droid'; - readonly primaryFunction?: string | null; - readonly name: string; - } - | { readonly __typename?: 'Human'; readonly height?: number | null; readonly name: string } -======= readonly hero: - | { readonly __typename?: 'Droid'; readonly primaryFunction: string | null; readonly name: string } - | { readonly __typename?: 'Human'; readonly height: number | null; readonly name: string } ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + | { readonly primaryFunction: string | null; readonly name: string } + | { readonly height: number | null; readonly name: string } | null; }; @@ -168,11 +102,7 @@ export type HeroNameQueryVariables = Exact<{ }>; export type HeroNameQuery = { - readonly __typename?: 'Query'; - readonly hero: - | { readonly __typename?: 'Droid'; readonly name: string } - | { readonly __typename?: 'Human'; readonly name: string } - | null; + readonly hero: { readonly name: string } | { readonly name: string } | null; }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ @@ -181,11 +111,7 @@ export type HeroNameConditionalInclusionQueryVariables = Exact<{ }>; export type HeroNameConditionalInclusionQuery = { - readonly __typename?: 'Query'; - readonly hero: - | { readonly __typename?: 'Droid'; readonly name?: string } - | { readonly __typename?: 'Human'; readonly name?: string } - | null; + readonly hero: { readonly name?: string } | { readonly name?: string } | null; }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ @@ -194,11 +120,7 @@ export type HeroNameConditionalExclusionQueryVariables = Exact<{ }>; export type HeroNameConditionalExclusionQuery = { - readonly __typename?: 'Query'; - readonly hero: - | { readonly __typename?: 'Droid'; readonly name?: string } - | { readonly __typename?: 'Human'; readonly name?: string } - | null; + readonly hero: { readonly name?: string } | { readonly name?: string } | null; }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ @@ -206,39 +128,20 @@ export type HeroParentTypeDependentFieldQueryVariables = Exact<{ }>; export type HeroParentTypeDependentFieldQuery = { - readonly __typename?: 'Query'; readonly hero: | { - readonly __typename?: 'Droid'; readonly name: string; readonly friends: ReadonlyArray< - | { readonly __typename?: 'Droid'; readonly name: string } -<<<<<<< HEAD - | { - readonly __typename?: 'Human'; - readonly height?: number | null; - readonly name: string; - } -======= - | { readonly __typename?: 'Human'; readonly height: number | null; readonly name: string } ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + | { readonly name: string } + | { readonly height: number | null; readonly name: string } | null > | null; } | { - readonly __typename?: 'Human'; readonly name: string; readonly friends: ReadonlyArray< - | { readonly __typename?: 'Droid'; readonly name: string } -<<<<<<< HEAD - | { - readonly __typename?: 'Human'; - readonly height?: number | null; - readonly name: string; - } -======= - | { readonly __typename?: 'Human'; readonly height: number | null; readonly name: string } ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + | { readonly name: string } + | { readonly height: number | null; readonly name: string } | null > | null; } @@ -250,44 +153,20 @@ export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ }>; export type HeroTypeDependentAliasedFieldQuery = { - readonly __typename?: 'Query'; - readonly hero: - | { readonly __typename?: 'Droid'; readonly property: string | null } - | { readonly __typename?: 'Human'; readonly property: string | null } - | null; + readonly hero: { readonly property: string | null } | { readonly property: string | null } | null; }; -export type HumanFieldsFragment = { - readonly __typename?: 'Human'; - readonly name: string; - readonly mass: number | null; -}; +export type HumanFieldsFragment = { readonly name: string; readonly mass: number | null }; export type HumanWithNullHeightQueryVariables = Exact<{ [key: string]: never }>; export type HumanWithNullHeightQuery = { - readonly __typename?: 'Query'; -<<<<<<< HEAD - readonly human?: { - readonly __typename?: 'Human'; - readonly name: string; - readonly mass?: number | null; - } | null; -======= - readonly human: { readonly __typename?: 'Human'; readonly name: string; readonly mass: number | null } | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + readonly human: { readonly name: string; readonly mass: number | null } | null; }; export type TwoHeroesQueryVariables = Exact<{ [key: string]: never }>; export type TwoHeroesQuery = { - readonly __typename?: 'Query'; - readonly r2: - | { readonly __typename?: 'Droid'; readonly name: string } - | { readonly __typename?: 'Human'; readonly name: string } - | null; - readonly luke: - | { readonly __typename?: 'Droid'; readonly name: string } - | { readonly __typename?: 'Human'; readonly name: string } - | null; + readonly r2: { readonly name: string } | { readonly name: string } | null; + readonly luke: { readonly name: string } | { readonly name: string } | null; }; diff --git a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts index 3eeecddb585..53346ac22c3 100644 --- a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts @@ -1,10 +1,7 @@ type Exact = { [K in keyof T]: T[K] }; -<<<<<<< HEAD export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -======= -export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** The episodes in the Star Wars trilogy */ export type Episode = /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ @@ -14,74 +11,44 @@ export type Episode = /** Star Wars Episode IV: A New Hope, released in 1977. */ | 'NEWHOPE'; ->>>>>>> c7b5477b6 (Generate input types and output enums into target file (#10527)) export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; }>; export type CreateReviewForEpisodeMutation = { - __typename?: 'Mutation'; - createReview: { __typename?: 'Review'; stars: number; commentary: string | null } | null; + createReview: { stars: number; commentary: string | null } | null; }; export type ExcludeQueryAlphaQueryVariables = Exact<{ episode?: Episode | null; }>; -export type ExcludeQueryAlphaQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +export type ExcludeQueryAlphaQuery = { hero: { name: string } | { name: string } | null }; export type ExcludeQueryBetaQueryVariables = Exact<{ episode?: Episode | null; }>; -export type ExcludeQueryBetaQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +export type ExcludeQueryBetaQuery = { hero: { name: string } | { name: string } | null }; export type HeroAndFriendsNamesQueryVariables = Exact<{ episode?: Episode | null; }>; export type HeroAndFriendsNamesQuery = { - __typename?: 'Query'; hero: - | { - __typename?: 'Droid'; - name: string; -<<<<<<< HEAD - friends?: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null - > | null; -======= - friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - } - | { - __typename?: 'Human'; - name: string; -<<<<<<< HEAD - friends?: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null - > | null; -======= - friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - } + | { name: string; friends: Array<{ name: string } | { name: string } | null> | null } + | { name: string; friends: Array<{ name: string } | { name: string } | null> | null } | null; }; export type HeroAppearsInQueryVariables = Exact<{ [key: string]: never }>; export type HeroAppearsInQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; name: string; appearsIn: Array } - | { __typename?: 'Human'; name: string; appearsIn: Array } + | { name: string; appearsIn: Array } + | { name: string; appearsIn: Array } | null; }; @@ -90,24 +57,15 @@ export type HeroDetailsQueryVariables = Exact<{ }>; export type HeroDetailsQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; primaryFunction: string | null; name: string } - | { __typename?: 'Human'; height: number | null; name: string } + | { primaryFunction: string | null; name: string } + | { height: number | null; name: string } | null; }; -<<<<<<< HEAD -type HeroDetails_Droid_Fragment = { - __typename?: 'Droid'; - primaryFunction?: string | null; - name: string; -}; -======= -type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction: string | null; name: string }; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) +type HeroDetails_Droid_Fragment = { primaryFunction: string | null; name: string }; -type HeroDetails_Human_Fragment = { __typename?: 'Human'; height: number | null; name: string }; +type HeroDetails_Human_Fragment = { height: number | null; name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; @@ -116,10 +74,9 @@ export type HeroDetailsWithFragmentQueryVariables = Exact<{ }>; export type HeroDetailsWithFragmentQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; primaryFunction: string | null; name: string } - | { __typename?: 'Human'; height: number | null; name: string } + | { primaryFunction: string | null; name: string } + | { height: number | null; name: string } | null; }; @@ -127,10 +84,7 @@ export type HeroNameQueryVariables = Exact<{ episode?: Episode | null; }>; -export type HeroNameQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +export type HeroNameQuery = { hero: { name: string } | { name: string } | null }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ episode?: Episode | null; @@ -138,8 +92,7 @@ export type HeroNameConditionalInclusionQueryVariables = Exact<{ }>; export type HeroNameConditionalInclusionQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { name?: string } | { name?: string } | null; }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ @@ -148,8 +101,7 @@ export type HeroNameConditionalExclusionQueryVariables = Exact<{ }>; export type HeroNameConditionalExclusionQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { name?: string } | { name?: string } | null; }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ @@ -157,35 +109,14 @@ export type HeroParentTypeDependentFieldQueryVariables = Exact<{ }>; export type HeroParentTypeDependentFieldQuery = { - __typename?: 'Query'; hero: | { - __typename?: 'Droid'; name: string; -<<<<<<< HEAD - friends?: Array< - | { __typename?: 'Droid'; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } - | null -======= - friends: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - > | null; + friends: Array<{ name: string } | { height: number | null; name: string } | null> | null; } | { - __typename?: 'Human'; name: string; -<<<<<<< HEAD - friends?: Array< - | { __typename?: 'Droid'; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } - | null -======= - friends: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - > | null; + friends: Array<{ name: string } | { height: number | null; name: string } | null> | null; } | null; }; @@ -195,30 +126,18 @@ export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ }>; export type HeroTypeDependentAliasedFieldQuery = { - __typename?: 'Query'; -<<<<<<< HEAD - hero?: - | { __typename?: 'Droid'; property?: string | null } - | { __typename?: 'Human'; property?: string | null } - | null; -======= - hero: { __typename?: 'Droid'; property: string | null } | { __typename?: 'Human'; property: string | null } | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + hero: { property: string | null } | { property: string | null } | null; }; -export type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass: number | null }; +export type HumanFieldsFragment = { name: string; mass: number | null }; export type HumanWithNullHeightQueryVariables = Exact<{ [key: string]: never }>; -export type HumanWithNullHeightQuery = { - __typename?: 'Query'; - human: { __typename?: 'Human'; name: string; mass: number | null } | null; -}; +export type HumanWithNullHeightQuery = { human: { name: string; mass: number | null } | null }; export type TwoHeroesQueryVariables = Exact<{ [key: string]: never }>; export type TwoHeroesQuery = { - __typename?: 'Query'; - r2: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; - luke: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + r2: { name: string } | { name: string } | null; + luke: { name: string } | { name: string } | null; }; diff --git a/dev-test/star-wars/types.preResolveTypes.ts b/dev-test/star-wars/types.preResolveTypes.ts index 3eeecddb585..53346ac22c3 100644 --- a/dev-test/star-wars/types.preResolveTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.ts @@ -1,10 +1,7 @@ type Exact = { [K in keyof T]: T[K] }; -<<<<<<< HEAD export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -======= -export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** The episodes in the Star Wars trilogy */ export type Episode = /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ @@ -14,74 +11,44 @@ export type Episode = /** Star Wars Episode IV: A New Hope, released in 1977. */ | 'NEWHOPE'; ->>>>>>> c7b5477b6 (Generate input types and output enums into target file (#10527)) export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; }>; export type CreateReviewForEpisodeMutation = { - __typename?: 'Mutation'; - createReview: { __typename?: 'Review'; stars: number; commentary: string | null } | null; + createReview: { stars: number; commentary: string | null } | null; }; export type ExcludeQueryAlphaQueryVariables = Exact<{ episode?: Episode | null; }>; -export type ExcludeQueryAlphaQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +export type ExcludeQueryAlphaQuery = { hero: { name: string } | { name: string } | null }; export type ExcludeQueryBetaQueryVariables = Exact<{ episode?: Episode | null; }>; -export type ExcludeQueryBetaQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +export type ExcludeQueryBetaQuery = { hero: { name: string } | { name: string } | null }; export type HeroAndFriendsNamesQueryVariables = Exact<{ episode?: Episode | null; }>; export type HeroAndFriendsNamesQuery = { - __typename?: 'Query'; hero: - | { - __typename?: 'Droid'; - name: string; -<<<<<<< HEAD - friends?: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null - > | null; -======= - friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - } - | { - __typename?: 'Human'; - name: string; -<<<<<<< HEAD - friends?: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null - > | null; -======= - friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - } + | { name: string; friends: Array<{ name: string } | { name: string } | null> | null } + | { name: string; friends: Array<{ name: string } | { name: string } | null> | null } | null; }; export type HeroAppearsInQueryVariables = Exact<{ [key: string]: never }>; export type HeroAppearsInQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; name: string; appearsIn: Array } - | { __typename?: 'Human'; name: string; appearsIn: Array } + | { name: string; appearsIn: Array } + | { name: string; appearsIn: Array } | null; }; @@ -90,24 +57,15 @@ export type HeroDetailsQueryVariables = Exact<{ }>; export type HeroDetailsQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; primaryFunction: string | null; name: string } - | { __typename?: 'Human'; height: number | null; name: string } + | { primaryFunction: string | null; name: string } + | { height: number | null; name: string } | null; }; -<<<<<<< HEAD -type HeroDetails_Droid_Fragment = { - __typename?: 'Droid'; - primaryFunction?: string | null; - name: string; -}; -======= -type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction: string | null; name: string }; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) +type HeroDetails_Droid_Fragment = { primaryFunction: string | null; name: string }; -type HeroDetails_Human_Fragment = { __typename?: 'Human'; height: number | null; name: string }; +type HeroDetails_Human_Fragment = { height: number | null; name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; @@ -116,10 +74,9 @@ export type HeroDetailsWithFragmentQueryVariables = Exact<{ }>; export type HeroDetailsWithFragmentQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; primaryFunction: string | null; name: string } - | { __typename?: 'Human'; height: number | null; name: string } + | { primaryFunction: string | null; name: string } + | { height: number | null; name: string } | null; }; @@ -127,10 +84,7 @@ export type HeroNameQueryVariables = Exact<{ episode?: Episode | null; }>; -export type HeroNameQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +export type HeroNameQuery = { hero: { name: string } | { name: string } | null }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ episode?: Episode | null; @@ -138,8 +92,7 @@ export type HeroNameConditionalInclusionQueryVariables = Exact<{ }>; export type HeroNameConditionalInclusionQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { name?: string } | { name?: string } | null; }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ @@ -148,8 +101,7 @@ export type HeroNameConditionalExclusionQueryVariables = Exact<{ }>; export type HeroNameConditionalExclusionQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { name?: string } | { name?: string } | null; }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ @@ -157,35 +109,14 @@ export type HeroParentTypeDependentFieldQueryVariables = Exact<{ }>; export type HeroParentTypeDependentFieldQuery = { - __typename?: 'Query'; hero: | { - __typename?: 'Droid'; name: string; -<<<<<<< HEAD - friends?: Array< - | { __typename?: 'Droid'; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } - | null -======= - friends: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - > | null; + friends: Array<{ name: string } | { height: number | null; name: string } | null> | null; } | { - __typename?: 'Human'; name: string; -<<<<<<< HEAD - friends?: Array< - | { __typename?: 'Droid'; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } - | null -======= - friends: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - > | null; + friends: Array<{ name: string } | { height: number | null; name: string } | null> | null; } | null; }; @@ -195,30 +126,18 @@ export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ }>; export type HeroTypeDependentAliasedFieldQuery = { - __typename?: 'Query'; -<<<<<<< HEAD - hero?: - | { __typename?: 'Droid'; property?: string | null } - | { __typename?: 'Human'; property?: string | null } - | null; -======= - hero: { __typename?: 'Droid'; property: string | null } | { __typename?: 'Human'; property: string | null } | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + hero: { property: string | null } | { property: string | null } | null; }; -export type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass: number | null }; +export type HumanFieldsFragment = { name: string; mass: number | null }; export type HumanWithNullHeightQueryVariables = Exact<{ [key: string]: never }>; -export type HumanWithNullHeightQuery = { - __typename?: 'Query'; - human: { __typename?: 'Human'; name: string; mass: number | null } | null; -}; +export type HumanWithNullHeightQuery = { human: { name: string; mass: number | null } | null }; export type TwoHeroesQueryVariables = Exact<{ [key: string]: never }>; export type TwoHeroesQuery = { - __typename?: 'Query'; - r2: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; - luke: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + r2: { name: string } | { name: string } | null; + luke: { name: string } | { name: string } | null; }; diff --git a/dev-test/star-wars/types.skipSchema.ts b/dev-test/star-wars/types.skipSchema.ts index 3eeecddb585..53346ac22c3 100644 --- a/dev-test/star-wars/types.skipSchema.ts +++ b/dev-test/star-wars/types.skipSchema.ts @@ -1,10 +1,7 @@ type Exact = { [K in keyof T]: T[K] }; -<<<<<<< HEAD export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -======= -export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** The episodes in the Star Wars trilogy */ export type Episode = /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ @@ -14,74 +11,44 @@ export type Episode = /** Star Wars Episode IV: A New Hope, released in 1977. */ | 'NEWHOPE'; ->>>>>>> c7b5477b6 (Generate input types and output enums into target file (#10527)) export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; }>; export type CreateReviewForEpisodeMutation = { - __typename?: 'Mutation'; - createReview: { __typename?: 'Review'; stars: number; commentary: string | null } | null; + createReview: { stars: number; commentary: string | null } | null; }; export type ExcludeQueryAlphaQueryVariables = Exact<{ episode?: Episode | null; }>; -export type ExcludeQueryAlphaQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +export type ExcludeQueryAlphaQuery = { hero: { name: string } | { name: string } | null }; export type ExcludeQueryBetaQueryVariables = Exact<{ episode?: Episode | null; }>; -export type ExcludeQueryBetaQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +export type ExcludeQueryBetaQuery = { hero: { name: string } | { name: string } | null }; export type HeroAndFriendsNamesQueryVariables = Exact<{ episode?: Episode | null; }>; export type HeroAndFriendsNamesQuery = { - __typename?: 'Query'; hero: - | { - __typename?: 'Droid'; - name: string; -<<<<<<< HEAD - friends?: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null - > | null; -======= - friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - } - | { - __typename?: 'Human'; - name: string; -<<<<<<< HEAD - friends?: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null - > | null; -======= - friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - } + | { name: string; friends: Array<{ name: string } | { name: string } | null> | null } + | { name: string; friends: Array<{ name: string } | { name: string } | null> | null } | null; }; export type HeroAppearsInQueryVariables = Exact<{ [key: string]: never }>; export type HeroAppearsInQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; name: string; appearsIn: Array } - | { __typename?: 'Human'; name: string; appearsIn: Array } + | { name: string; appearsIn: Array } + | { name: string; appearsIn: Array } | null; }; @@ -90,24 +57,15 @@ export type HeroDetailsQueryVariables = Exact<{ }>; export type HeroDetailsQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; primaryFunction: string | null; name: string } - | { __typename?: 'Human'; height: number | null; name: string } + | { primaryFunction: string | null; name: string } + | { height: number | null; name: string } | null; }; -<<<<<<< HEAD -type HeroDetails_Droid_Fragment = { - __typename?: 'Droid'; - primaryFunction?: string | null; - name: string; -}; -======= -type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction: string | null; name: string }; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) +type HeroDetails_Droid_Fragment = { primaryFunction: string | null; name: string }; -type HeroDetails_Human_Fragment = { __typename?: 'Human'; height: number | null; name: string }; +type HeroDetails_Human_Fragment = { height: number | null; name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; @@ -116,10 +74,9 @@ export type HeroDetailsWithFragmentQueryVariables = Exact<{ }>; export type HeroDetailsWithFragmentQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; primaryFunction: string | null; name: string } - | { __typename?: 'Human'; height: number | null; name: string } + | { primaryFunction: string | null; name: string } + | { height: number | null; name: string } | null; }; @@ -127,10 +84,7 @@ export type HeroNameQueryVariables = Exact<{ episode?: Episode | null; }>; -export type HeroNameQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +export type HeroNameQuery = { hero: { name: string } | { name: string } | null }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ episode?: Episode | null; @@ -138,8 +92,7 @@ export type HeroNameConditionalInclusionQueryVariables = Exact<{ }>; export type HeroNameConditionalInclusionQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { name?: string } | { name?: string } | null; }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ @@ -148,8 +101,7 @@ export type HeroNameConditionalExclusionQueryVariables = Exact<{ }>; export type HeroNameConditionalExclusionQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { name?: string } | { name?: string } | null; }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ @@ -157,35 +109,14 @@ export type HeroParentTypeDependentFieldQueryVariables = Exact<{ }>; export type HeroParentTypeDependentFieldQuery = { - __typename?: 'Query'; hero: | { - __typename?: 'Droid'; name: string; -<<<<<<< HEAD - friends?: Array< - | { __typename?: 'Droid'; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } - | null -======= - friends: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - > | null; + friends: Array<{ name: string } | { height: number | null; name: string } | null> | null; } | { - __typename?: 'Human'; name: string; -<<<<<<< HEAD - friends?: Array< - | { __typename?: 'Droid'; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } - | null -======= - friends: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - > | null; + friends: Array<{ name: string } | { height: number | null; name: string } | null> | null; } | null; }; @@ -195,30 +126,18 @@ export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ }>; export type HeroTypeDependentAliasedFieldQuery = { - __typename?: 'Query'; -<<<<<<< HEAD - hero?: - | { __typename?: 'Droid'; property?: string | null } - | { __typename?: 'Human'; property?: string | null } - | null; -======= - hero: { __typename?: 'Droid'; property: string | null } | { __typename?: 'Human'; property: string | null } | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + hero: { property: string | null } | { property: string | null } | null; }; -export type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass: number | null }; +export type HumanFieldsFragment = { name: string; mass: number | null }; export type HumanWithNullHeightQueryVariables = Exact<{ [key: string]: never }>; -export type HumanWithNullHeightQuery = { - __typename?: 'Query'; - human: { __typename?: 'Human'; name: string; mass: number | null } | null; -}; +export type HumanWithNullHeightQuery = { human: { name: string; mass: number | null } | null }; export type TwoHeroesQueryVariables = Exact<{ [key: string]: never }>; export type TwoHeroesQuery = { - __typename?: 'Query'; - r2: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; - luke: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + r2: { name: string } | { name: string } | null; + luke: { name: string } | { name: string } | null; }; diff --git a/dev-test/star-wars/types.ts b/dev-test/star-wars/types.ts index 3eeecddb585..53346ac22c3 100644 --- a/dev-test/star-wars/types.ts +++ b/dev-test/star-wars/types.ts @@ -1,10 +1,7 @@ type Exact = { [K in keyof T]: T[K] }; -<<<<<<< HEAD export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -======= -export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** The episodes in the Star Wars trilogy */ export type Episode = /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ @@ -14,74 +11,44 @@ export type Episode = /** Star Wars Episode IV: A New Hope, released in 1977. */ | 'NEWHOPE'; ->>>>>>> c7b5477b6 (Generate input types and output enums into target file (#10527)) export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; }>; export type CreateReviewForEpisodeMutation = { - __typename?: 'Mutation'; - createReview: { __typename?: 'Review'; stars: number; commentary: string | null } | null; + createReview: { stars: number; commentary: string | null } | null; }; export type ExcludeQueryAlphaQueryVariables = Exact<{ episode?: Episode | null; }>; -export type ExcludeQueryAlphaQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +export type ExcludeQueryAlphaQuery = { hero: { name: string } | { name: string } | null }; export type ExcludeQueryBetaQueryVariables = Exact<{ episode?: Episode | null; }>; -export type ExcludeQueryBetaQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +export type ExcludeQueryBetaQuery = { hero: { name: string } | { name: string } | null }; export type HeroAndFriendsNamesQueryVariables = Exact<{ episode?: Episode | null; }>; export type HeroAndFriendsNamesQuery = { - __typename?: 'Query'; hero: - | { - __typename?: 'Droid'; - name: string; -<<<<<<< HEAD - friends?: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null - > | null; -======= - friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - } - | { - __typename?: 'Human'; - name: string; -<<<<<<< HEAD - friends?: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null - > | null; -======= - friends: Array<{ __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null> | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - } + | { name: string; friends: Array<{ name: string } | { name: string } | null> | null } + | { name: string; friends: Array<{ name: string } | { name: string } | null> | null } | null; }; export type HeroAppearsInQueryVariables = Exact<{ [key: string]: never }>; export type HeroAppearsInQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; name: string; appearsIn: Array } - | { __typename?: 'Human'; name: string; appearsIn: Array } + | { name: string; appearsIn: Array } + | { name: string; appearsIn: Array } | null; }; @@ -90,24 +57,15 @@ export type HeroDetailsQueryVariables = Exact<{ }>; export type HeroDetailsQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; primaryFunction: string | null; name: string } - | { __typename?: 'Human'; height: number | null; name: string } + | { primaryFunction: string | null; name: string } + | { height: number | null; name: string } | null; }; -<<<<<<< HEAD -type HeroDetails_Droid_Fragment = { - __typename?: 'Droid'; - primaryFunction?: string | null; - name: string; -}; -======= -type HeroDetails_Droid_Fragment = { __typename?: 'Droid'; primaryFunction: string | null; name: string }; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) +type HeroDetails_Droid_Fragment = { primaryFunction: string | null; name: string }; -type HeroDetails_Human_Fragment = { __typename?: 'Human'; height: number | null; name: string }; +type HeroDetails_Human_Fragment = { height: number | null; name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; @@ -116,10 +74,9 @@ export type HeroDetailsWithFragmentQueryVariables = Exact<{ }>; export type HeroDetailsWithFragmentQuery = { - __typename?: 'Query'; hero: - | { __typename?: 'Droid'; primaryFunction: string | null; name: string } - | { __typename?: 'Human'; height: number | null; name: string } + | { primaryFunction: string | null; name: string } + | { height: number | null; name: string } | null; }; @@ -127,10 +84,7 @@ export type HeroNameQueryVariables = Exact<{ episode?: Episode | null; }>; -export type HeroNameQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; -}; +export type HeroNameQuery = { hero: { name: string } | { name: string } | null }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ episode?: Episode | null; @@ -138,8 +92,7 @@ export type HeroNameConditionalInclusionQueryVariables = Exact<{ }>; export type HeroNameConditionalInclusionQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { name?: string } | { name?: string } | null; }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ @@ -148,8 +101,7 @@ export type HeroNameConditionalExclusionQueryVariables = Exact<{ }>; export type HeroNameConditionalExclusionQuery = { - __typename?: 'Query'; - hero: { __typename?: 'Droid'; name?: string } | { __typename?: 'Human'; name?: string } | null; + hero: { name?: string } | { name?: string } | null; }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ @@ -157,35 +109,14 @@ export type HeroParentTypeDependentFieldQueryVariables = Exact<{ }>; export type HeroParentTypeDependentFieldQuery = { - __typename?: 'Query'; hero: | { - __typename?: 'Droid'; name: string; -<<<<<<< HEAD - friends?: Array< - | { __typename?: 'Droid'; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } - | null -======= - friends: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - > | null; + friends: Array<{ name: string } | { height: number | null; name: string } | null> | null; } | { - __typename?: 'Human'; name: string; -<<<<<<< HEAD - friends?: Array< - | { __typename?: 'Droid'; name: string } - | { __typename?: 'Human'; height?: number | null; name: string } - | null -======= - friends: Array< - { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; height: number | null; name: string } | null ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) - > | null; + friends: Array<{ name: string } | { height: number | null; name: string } | null> | null; } | null; }; @@ -195,30 +126,18 @@ export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ }>; export type HeroTypeDependentAliasedFieldQuery = { - __typename?: 'Query'; -<<<<<<< HEAD - hero?: - | { __typename?: 'Droid'; property?: string | null } - | { __typename?: 'Human'; property?: string | null } - | null; -======= - hero: { __typename?: 'Droid'; property: string | null } | { __typename?: 'Human'; property: string | null } | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + hero: { property: string | null } | { property: string | null } | null; }; -export type HumanFieldsFragment = { __typename?: 'Human'; name: string; mass: number | null }; +export type HumanFieldsFragment = { name: string; mass: number | null }; export type HumanWithNullHeightQueryVariables = Exact<{ [key: string]: never }>; -export type HumanWithNullHeightQuery = { - __typename?: 'Query'; - human: { __typename?: 'Human'; name: string; mass: number | null } | null; -}; +export type HumanWithNullHeightQuery = { human: { name: string; mass: number | null } | null }; export type TwoHeroesQueryVariables = Exact<{ [key: string]: never }>; export type TwoHeroesQuery = { - __typename?: 'Query'; - r2: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; - luke: { __typename?: 'Droid'; name: string } | { __typename?: 'Human'; name: string } | null; + r2: { name: string } | { name: string } | null; + luke: { name: string } | { name: string } | null; }; diff --git a/dev-test/test-null-value/result.d.ts b/dev-test/test-null-value/result.d.ts index 82dfe670c4b..fb0c8076f1a 100644 --- a/dev-test/test-null-value/result.d.ts +++ b/dev-test/test-null-value/result.d.ts @@ -6,10 +6,6 @@ export type CartLineFragment = { id: string; quantity: number }; export type TestQueryVariables = Exact<{ [key: string]: never }>; -<<<<<<< HEAD export type TestQuery = { - cart?: { lines: { nodes: Array<{ id: string; quantity: number }> } } | null; + cart: { lines: { nodes: Array<{ id: string; quantity: number }> } } | null; }; -======= -export type TestQuery = { cart: { lines: { nodes: Array<{ id: string; quantity: number }> } } | null }; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) diff --git a/dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts index 462accb7794..3891d0d999a 100644 --- a/dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts @@ -5,7 +5,6 @@ export type Incremental = export type TestQueryVariables = Exact<{ [key: string]: never }>; export type TestQuery = { - __typename?: 'Query'; testArr1: Array | null; testArr2: Array; testArr3: Array; diff --git a/dev-test/test-schema/types.preResolveTypes.ts b/dev-test/test-schema/types.preResolveTypes.ts index 462accb7794..3891d0d999a 100644 --- a/dev-test/test-schema/types.preResolveTypes.ts +++ b/dev-test/test-schema/types.preResolveTypes.ts @@ -5,7 +5,6 @@ export type Incremental = export type TestQueryVariables = Exact<{ [key: string]: never }>; export type TestQuery = { - __typename?: 'Query'; testArr1: Array | null; testArr2: Array; testArr3: Array; diff --git a/examples/persisted-documents-string-mode/src/gql/graphql.ts b/examples/persisted-documents-string-mode/src/gql/graphql.ts index a5fd33f5185..2fe6966db28 100644 --- a/examples/persisted-documents-string-mode/src/gql/graphql.ts +++ b/examples/persisted-documents-string-mode/src/gql/graphql.ts @@ -7,7 +7,7 @@ export type Incremental = | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type HelloQueryQueryVariables = Exact<{ [key: string]: never }>; -export type HelloQueryQuery = { __typename?: 'Query'; hello: string }; +export type HelloQueryQuery = { hello: string }; export class TypedDocumentString extends String diff --git a/examples/persisted-documents/src/gql/graphql.ts b/examples/persisted-documents/src/gql/graphql.ts index 7fd26f94347..158f8951d3a 100644 --- a/examples/persisted-documents/src/gql/graphql.ts +++ b/examples/persisted-documents/src/gql/graphql.ts @@ -7,7 +7,7 @@ export type Incremental = | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type HelloQueryQueryVariables = Exact<{ [key: string]: never }>; -export type HelloQueryQuery = { __typename?: 'Query'; hello: string }; +export type HelloQueryQuery = { hello: string }; export const HelloQueryDocument = { __meta__: { hash: '86f01e23de1c770cabbc35b2d87f2e5fd7557b6f' }, diff --git a/examples/react/apollo-client-defer/codegen.ts b/examples/react/apollo-client-defer/codegen.ts index e679ef78f6e..dea41622933 100644 --- a/examples/react/apollo-client-defer/codegen.ts +++ b/examples/react/apollo-client-defer/codegen.ts @@ -6,6 +6,10 @@ const config: CodegenConfig = { generates: { './src/gql/': { preset: 'client', + config: { + skipTypeNameForRoot: true, + nonOptionalTypename: true, + }, }, }, hooks: { afterAllFileWrite: ['prettier --write'] }, diff --git a/examples/react/apollo-client-defer/src/gql/graphql.ts b/examples/react/apollo-client-defer/src/gql/graphql.ts index a94db489602..5fd1e0fbbde 100644 --- a/examples/react/apollo-client-defer/src/gql/graphql.ts +++ b/examples/react/apollo-client-defer/src/gql/graphql.ts @@ -5,19 +5,16 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; -export type SlowFieldFragmentFragment = { __typename?: 'Query'; slowField: string } & { +export type SlowFieldFragmentFragment = { slowField: string } & { ' $fragmentName'?: 'SlowFieldFragmentFragment'; }; export type SlowAndFastFieldWithDeferQueryVariables = Exact<{ [key: string]: never }>; -export type SlowAndFastFieldWithDeferQuery = { __typename?: 'Query'; fastField: string } & ( - | { __typename?: 'Query'; inlinedSlowField: string } - | { __typename?: 'Query'; inlinedSlowField?: never } -) & - ({ __typename?: 'Query' } & { - ' $fragmentRefs'?: { SlowFieldFragmentFragment: Incremental }; - }); +export type SlowAndFastFieldWithDeferQuery = { fastField: string } & ( + | { inlinedSlowField: string } + | { inlinedSlowField?: never } +) & { ' $fragmentRefs'?: { SlowFieldFragmentFragment: Incremental } }; export const SlowFieldFragmentFragmentDoc = { kind: 'Document', diff --git a/examples/react/apollo-client/codegen.ts b/examples/react/apollo-client/codegen.ts index f2aa8f0746b..c0bd3435ce5 100644 --- a/examples/react/apollo-client/codegen.ts +++ b/examples/react/apollo-client/codegen.ts @@ -6,6 +6,10 @@ const config: CodegenConfig = { generates: { './src/gql/': { preset: 'client', + config: { + skipTypeNameForRoot: true, + nonOptionalTypename: true, + }, }, }, hooks: { afterAllFileWrite: ['prettier --write'] }, diff --git a/examples/react/apollo-client/src/gql/graphql.ts b/examples/react/apollo-client/src/gql/graphql.ts index b8a36fe5a42..9f483eedc67 100644 --- a/examples/react/apollo-client/src/gql/graphql.ts +++ b/examples/react/apollo-client/src/gql/graphql.ts @@ -10,24 +10,19 @@ export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ }>; export type AllFilmsWithVariablesQueryQuery = { - __typename?: 'Root'; allFilms: { - __typename?: 'FilmsConnection'; + __typename: 'FilmsConnection'; edges: Array<{ - __typename?: 'FilmsEdge'; -<<<<<<< HEAD - node?: - | ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) + __typename: 'FilmsEdge'; + node: + | ({ __typename: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; -======= - node: ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) } | null> | null; } | null; }; export type FilmItemFragment = { - __typename?: 'Film'; + __typename: 'Film'; id: string; title: string | null; releaseDate: string | null; diff --git a/examples/react/http-executor/src/gql/graphql.ts b/examples/react/http-executor/src/gql/graphql.ts index b8a36fe5a42..35ca172a4ff 100644 --- a/examples/react/http-executor/src/gql/graphql.ts +++ b/examples/react/http-executor/src/gql/graphql.ts @@ -10,24 +10,14 @@ export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ }>; export type AllFilmsWithVariablesQueryQuery = { - __typename?: 'Root'; allFilms: { - __typename?: 'FilmsConnection'; edges: Array<{ - __typename?: 'FilmsEdge'; -<<<<<<< HEAD - node?: - | ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) - | null; -======= - node: ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + node: { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } } | null; } | null> | null; } | null; }; export type FilmItemFragment = { - __typename?: 'Film'; id: string; title: string | null; releaseDate: string | null; diff --git a/examples/react/tanstack-react-query/src/gql/graphql.ts b/examples/react/tanstack-react-query/src/gql/graphql.ts index 835ab1cfe5c..6a5e52c1ba7 100644 --- a/examples/react/tanstack-react-query/src/gql/graphql.ts +++ b/examples/react/tanstack-react-query/src/gql/graphql.ts @@ -10,24 +10,14 @@ export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ }>; export type AllFilmsWithVariablesQueryQuery = { - __typename?: 'Root'; allFilms: { - __typename?: 'FilmsConnection'; edges: Array<{ - __typename?: 'FilmsEdge'; -<<<<<<< HEAD - node?: - | ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) - | null; -======= - node: ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + node: { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } } | null; } | null> | null; } | null; }; export type FilmItemFragment = { - __typename?: 'Film'; id: string; title: string | null; releaseDate: string | null; diff --git a/examples/react/urql/src/gql/graphql.ts b/examples/react/urql/src/gql/graphql.ts index 823889e065a..23a2c624e02 100644 --- a/examples/react/urql/src/gql/graphql.ts +++ b/examples/react/urql/src/gql/graphql.ts @@ -10,24 +10,14 @@ export type AllFilmsWithVariablesQuery199QueryVariables = Exact<{ }>; export type AllFilmsWithVariablesQuery199Query = { - __typename?: 'Root'; allFilms: { - __typename?: 'FilmsConnection'; edges: Array<{ - __typename?: 'FilmsEdge'; -<<<<<<< HEAD - node?: - | ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) - | null; -======= - node: ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + node: { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } } | null; } | null> | null; } | null; }; export type FilmItemFragment = { - __typename?: 'Film'; id: string; title: string | null; releaseDate: string | null; diff --git a/examples/typescript-esm/src/gql/graphql.ts b/examples/typescript-esm/src/gql/graphql.ts index f6974dc72b0..478717a7da7 100644 --- a/examples/typescript-esm/src/gql/graphql.ts +++ b/examples/typescript-esm/src/gql/graphql.ts @@ -8,16 +8,9 @@ export type Incremental = export type AllPeopleQueryQueryVariables = Exact<{ [key: string]: never }>; export type AllPeopleQueryQuery = { - __typename?: 'Root'; allPeople: { - __typename?: 'PeopleConnection'; edges: Array<{ - __typename?: 'PeopleEdge'; - node: { - __typename?: 'Person'; - name: string | null; - homeworld: { __typename?: 'Planet'; name: string | null } | null; - } | null; + node: { name: string | null; homeworld: { name: string | null } | null } | null; } | null> | null; } | null; }; @@ -27,16 +20,9 @@ export type AllPeopleWithVariablesQueryQueryVariables = Exact<{ }>; export type AllPeopleWithVariablesQueryQuery = { - __typename?: 'Root'; allPeople: { - __typename?: 'PeopleConnection'; edges: Array<{ - __typename?: 'PeopleEdge'; - node: { - __typename?: 'Person'; - name: string | null; - homeworld: { __typename?: 'Planet'; name: string | null } | null; - } | null; + node: { name: string | null; homeworld: { name: string | null } | null } | null; } | null> | null; } | null; }; diff --git a/examples/typescript-graphql-request/src/gql/graphql.ts b/examples/typescript-graphql-request/src/gql/graphql.ts index f41b60648d0..2d4c1973778 100644 --- a/examples/typescript-graphql-request/src/gql/graphql.ts +++ b/examples/typescript-graphql-request/src/gql/graphql.ts @@ -8,16 +8,9 @@ export type Incremental = export type AllPeopleQueryQueryVariables = Exact<{ [key: string]: never }>; export type AllPeopleQueryQuery = { - __typename?: 'Root'; allPeople: { - __typename?: 'PeopleConnection'; edges: Array<{ - __typename?: 'PeopleEdge'; - node: { - __typename?: 'Person'; - name: string | null; - homeworld: { __typename?: 'Planet'; name: string | null } | null; - } | null; + node: { name: string | null; homeworld: { name: string | null } | null } | null; } | null> | null; } | null; }; @@ -27,16 +20,9 @@ export type AllPeopleWithVariablesQueryQueryVariables = Exact<{ }>; export type AllPeopleWithVariablesQueryQuery = { - __typename?: 'Root'; allPeople: { - __typename?: 'PeopleConnection'; edges: Array<{ - __typename?: 'PeopleEdge'; - node: { - __typename?: 'Person'; - name: string | null; - homeworld: { __typename?: 'Planet'; name: string | null } | null; - } | null; + node: { name: string | null; homeworld: { name: string | null } | null } | null; } | null> | null; } | null; }; diff --git a/examples/vite/vite-react-cts/src/gql/graphql.ts b/examples/vite/vite-react-cts/src/gql/graphql.ts index effe8955b72..73f95a195d4 100644 --- a/examples/vite/vite-react-cts/src/gql/graphql.ts +++ b/examples/vite/vite-react-cts/src/gql/graphql.ts @@ -6,7 +6,6 @@ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type FilmItemFragment = { - __typename?: 'Film'; id: string; title: string | null; releaseDate: string | null; @@ -18,18 +17,9 @@ export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ }>; export type AllFilmsWithVariablesQueryQuery = { - __typename?: 'Root'; allFilms: { - __typename?: 'FilmsConnection'; edges: Array<{ - __typename?: 'FilmsEdge'; -<<<<<<< HEAD - node?: - | ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) - | null; -======= - node: ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + node: { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } } | null; } | null> | null; } | null; }; diff --git a/examples/vite/vite-react-mts/src/gql/graphql.ts b/examples/vite/vite-react-mts/src/gql/graphql.ts index effe8955b72..73f95a195d4 100644 --- a/examples/vite/vite-react-mts/src/gql/graphql.ts +++ b/examples/vite/vite-react-mts/src/gql/graphql.ts @@ -6,7 +6,6 @@ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type FilmItemFragment = { - __typename?: 'Film'; id: string; title: string | null; releaseDate: string | null; @@ -18,18 +17,9 @@ export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ }>; export type AllFilmsWithVariablesQueryQuery = { - __typename?: 'Root'; allFilms: { - __typename?: 'FilmsConnection'; edges: Array<{ - __typename?: 'FilmsEdge'; -<<<<<<< HEAD - node?: - | ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) - | null; -======= - node: ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + node: { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } } | null; } | null> | null; } | null; }; diff --git a/examples/vite/vite-react-ts/src/gql/graphql.ts b/examples/vite/vite-react-ts/src/gql/graphql.ts index effe8955b72..73f95a195d4 100644 --- a/examples/vite/vite-react-ts/src/gql/graphql.ts +++ b/examples/vite/vite-react-ts/src/gql/graphql.ts @@ -6,7 +6,6 @@ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type FilmItemFragment = { - __typename?: 'Film'; id: string; title: string | null; releaseDate: string | null; @@ -18,18 +17,9 @@ export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ }>; export type AllFilmsWithVariablesQueryQuery = { - __typename?: 'Root'; allFilms: { - __typename?: 'FilmsConnection'; edges: Array<{ - __typename?: 'FilmsEdge'; -<<<<<<< HEAD - node?: - | ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) - | null; -======= - node: ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + node: { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } } | null; } | null> | null; } | null; }; diff --git a/examples/vue/apollo-composable/src/gql/graphql.ts b/examples/vue/apollo-composable/src/gql/graphql.ts index aba4d5220af..7a4aaeb85ae 100644 --- a/examples/vue/apollo-composable/src/gql/graphql.ts +++ b/examples/vue/apollo-composable/src/gql/graphql.ts @@ -10,24 +10,14 @@ export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ }>; export type AllFilmsWithVariablesQueryQuery = { - __typename?: 'Root'; allFilms: { - __typename?: 'FilmsConnection'; edges: Array<{ - __typename?: 'FilmsEdge'; -<<<<<<< HEAD - node?: - | ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) - | null; -======= - node: ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + node: { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } } | null; } | null> | null; } | null; }; export type FilmItemFragment = { - __typename?: 'Film'; id: string; title: string | null; releaseDate: string | null; diff --git a/examples/vue/urql/src/gql/graphql.ts b/examples/vue/urql/src/gql/graphql.ts index aba4d5220af..7a4aaeb85ae 100644 --- a/examples/vue/urql/src/gql/graphql.ts +++ b/examples/vue/urql/src/gql/graphql.ts @@ -10,24 +10,14 @@ export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ }>; export type AllFilmsWithVariablesQueryQuery = { - __typename?: 'Root'; allFilms: { - __typename?: 'FilmsConnection'; edges: Array<{ - __typename?: 'FilmsEdge'; -<<<<<<< HEAD - node?: - | ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) - | null; -======= - node: ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + node: { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } } | null; } | null> | null; } | null; }; export type FilmItemFragment = { - __typename?: 'Film'; id: string; title: string | null; releaseDate: string | null; diff --git a/examples/vue/villus/src/gql/graphql.ts b/examples/vue/villus/src/gql/graphql.ts index aba4d5220af..7a4aaeb85ae 100644 --- a/examples/vue/villus/src/gql/graphql.ts +++ b/examples/vue/villus/src/gql/graphql.ts @@ -10,24 +10,14 @@ export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ }>; export type AllFilmsWithVariablesQueryQuery = { - __typename?: 'Root'; allFilms: { - __typename?: 'FilmsConnection'; edges: Array<{ - __typename?: 'FilmsEdge'; -<<<<<<< HEAD - node?: - | ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) - | null; -======= - node: ({ __typename?: 'Film' } & { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } }) | null; ->>>>>>> caa1c98e0 ([typescript-operations] No optional Result fields, unless deferred or conditional (#10548)) + node: { ' $fragmentRefs'?: { FilmItemFragment: FilmItemFragment } } | null; } | null> | null; } | null; }; export type FilmItemFragment = { - __typename?: 'Film'; id: string; title: string | null; releaseDate: string | null; diff --git a/examples/yoga-tests/src/gql/graphql.ts b/examples/yoga-tests/src/gql/graphql.ts index ad230c423b5..946b85f42e5 100644 --- a/examples/yoga-tests/src/gql/graphql.ts +++ b/examples/yoga-tests/src/gql/graphql.ts @@ -7,13 +7,13 @@ export type Incremental = | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type HelloQueryQueryVariables = Exact<{ [key: string]: never }>; -export type HelloQueryQuery = { __typename?: 'Query'; hello: string }; +export type HelloQueryQuery = { hello: string }; export type EchoMutationMutationVariables = Exact<{ message: string; }>; -export type EchoMutationMutation = { __typename?: 'Mutation'; echo: string }; +export type EchoMutationMutation = { echo: string }; export const HelloQueryDocument = { kind: 'Document', diff --git a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts index 5ad05f464cc..f529298abd4 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts @@ -33,7 +33,6 @@ function getRootType(operation: OperationTypeNode, schema: GraphQLSchema) { } export interface ParsedDocumentsConfig extends ParsedTypesConfig { - addTypename: boolean; preResolveTypes: boolean; extractAllFieldsToTypes: boolean; globalNamespace: boolean; @@ -257,7 +256,6 @@ export class BaseDocumentsVisitor< skipTypeNameForRoot: getConfigValue(rawConfig.skipTypeNameForRoot, false), namespacedImportName: getConfigValue(rawConfig.namespacedImportName, null), experimentalFragmentVariables: getConfigValue(rawConfig.experimentalFragmentVariables, false), - addTypename: !rawConfig.skipTypename, globalNamespace: !!rawConfig.globalNamespace, operationResultSuffix: getConfigValue(rawConfig.operationResultSuffix, ''), scalars: buildScalarsFromConfig(_schema, rawConfig, defaultScalars), @@ -297,10 +295,6 @@ export class BaseDocumentsVisitor< return this._schema; } - public get addTypename(): boolean { - return this._parsedConfig.addTypename; - } - private handleAnonymousOperation(node: OperationDefinitionNode): string { const name = node.name?.value; diff --git a/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts b/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts index 57e525929cc..095f6cdd202 100644 --- a/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts +++ b/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts @@ -755,7 +755,6 @@ export class SelectionSetToObject< const typeInfoField = this.buildTypeNameField( parentSchemaType, this._config.nonOptionalTypename, - this._config.addTypename, requireTypename, this._config.skipTypeNameForRoot, ); @@ -822,25 +821,26 @@ export class SelectionSetToObject< protected buildTypeNameField( type: GraphQLObjectType, - nonOptionalTypename: boolean = this._config.nonOptionalTypename, - addTypename: boolean = this._config.addTypename, - queriedForTypename: boolean = this._queriedForTypename, - skipTypeNameForRoot: boolean = this._config.skipTypeNameForRoot, - ): { name: string; type: string } { + nonOptionalTypename: boolean, + queriedForTypename: boolean, + skipTypeNameForRoot: boolean, + ): { name: string; type: string } | null { + const typenameField = { + name: this._processor.config.formatNamedField({ name: '__typename' }), + type: `'${type.name}'`, + }; + + if (queriedForTypename) { + return typenameField; + } + const rootTypes = getRootTypes(this._schema); - if (rootTypes.has(type) && skipTypeNameForRoot && !queriedForTypename) { + if (rootTypes.has(type) && skipTypeNameForRoot) { return null; } - if (nonOptionalTypename || addTypename || queriedForTypename) { - const optionalTypename = !queriedForTypename && !nonOptionalTypename; - return { - name: this._processor.config.formatNamedField({ - name: '__typename', - isOptional: optionalTypename, - }), - type: `'${type.name}'`, - }; + if (nonOptionalTypename) { + return typenameField; } return null; @@ -973,10 +973,6 @@ export class SelectionSetToObject< const declarationName = this.buildFragmentTypeName(fragmentName, fragmentSuffix, typeName); if (possibleFields.length === 0) { - if (!this._config.addTypename) { - return [{ name: declarationName, content: this.getEmptyObjectType() }]; - } - return []; } diff --git a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap index 07c552f2903..210cac2e1a8 100644 --- a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap +++ b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap @@ -1,7 +1,7 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`TypeScript Operations Plugin > Config > should include fragment variable definitions when experimentalFragmentVariables is set 1`] = ` -"export type TextNotificationFragmentFragment = { __typename?: 'TextNotification', text?: string }; +"export type TextNotificationFragmentFragment = { text?: string }; export type TextNotificationFragmentFragmentVariables = Exact<{ @@ -17,20 +17,20 @@ exports[`TypeScript Operations Plugin > Issues > #2699 - Issues with multiple in }>; -export type GetEntityBrandDataQuery = { __typename?: 'Query', node: - | { __typename: 'Company', active: boolean, id: string, createdAt: any, updatedAt: any, brandData: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null, createdBy: { __typename?: 'User', id: string, name: string } | null, updatedBy: { __typename?: 'User', id: string, name: string } | null } - | { __typename: 'Theater', active: boolean, id: string, createdAt: any, updatedAt: any, brandData: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null, createdBy: { __typename?: 'User', id: string, name: string } | null, updatedBy: { __typename?: 'User', id: string, name: string } | null } - | { __typename: 'Movie', id: string, createdAt: any, updatedAt: any, brandData: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null, createdBy: { __typename?: 'User', id: string, name: string } | null, updatedBy: { __typename?: 'User', id: string, name: string } | null } - | { __typename: 'User', id: string, createdAt: any, updatedAt: any, brandData: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null, createdBy: { __typename?: 'User', id: string, name: string } | null, updatedBy: { __typename?: 'User', id: string, name: string } | null } +export type GetEntityBrandDataQuery = { node: + | { __typename: 'Company', active: boolean, id: string, createdAt: any, updatedAt: any, brandData: { active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null } + | { __typename: 'Theater', active: boolean, id: string, createdAt: any, updatedAt: any, brandData: { active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null } + | { __typename: 'Movie', id: string, createdAt: any, updatedAt: any, brandData: { active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null } + | { __typename: 'User', id: string, createdAt: any, updatedAt: any, brandData: { active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null } }; -type EntityBrandData_Company_Fragment = { __typename?: 'Company', brandData: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null }; +type EntityBrandData_Company_Fragment = { brandData: { active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null }; -type EntityBrandData_Theater_Fragment = { __typename?: 'Theater', brandData: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null }; +type EntityBrandData_Theater_Fragment = { brandData: { active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null }; -type EntityBrandData_Movie_Fragment = { __typename?: 'Movie', brandData: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null }; +type EntityBrandData_Movie_Fragment = { brandData: { active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null }; -type EntityBrandData_User_Fragment = { __typename?: 'User', brandData: { __typename?: 'EntityBrandData', active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null }; +type EntityBrandData_User_Fragment = { brandData: { active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null }; export type EntityBrandDataFragment = | EntityBrandData_Company_Fragment @@ -39,13 +39,13 @@ export type EntityBrandDataFragment = | EntityBrandData_User_Fragment ; -type ElementMetadata_Company_Fragment = { __typename?: 'Company', createdAt: any, updatedAt: any, createdBy: { __typename?: 'User', id: string, name: string } | null, updatedBy: { __typename?: 'User', id: string, name: string } | null }; +type ElementMetadata_Company_Fragment = { createdAt: any, updatedAt: any, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null }; -type ElementMetadata_Theater_Fragment = { __typename?: 'Theater', createdAt: any, updatedAt: any, createdBy: { __typename?: 'User', id: string, name: string } | null, updatedBy: { __typename?: 'User', id: string, name: string } | null }; +type ElementMetadata_Theater_Fragment = { createdAt: any, updatedAt: any, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null }; -type ElementMetadata_Movie_Fragment = { __typename?: 'Movie', createdAt: any, updatedAt: any, createdBy: { __typename?: 'User', id: string, name: string } | null, updatedBy: { __typename?: 'User', id: string, name: string } | null }; +type ElementMetadata_Movie_Fragment = { createdAt: any, updatedAt: any, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null }; -type ElementMetadata_User_Fragment = { __typename?: 'User', createdAt: any, updatedAt: any, createdBy: { __typename?: 'User', id: string, name: string } | null, updatedBy: { __typename?: 'User', id: string, name: string } | null }; +type ElementMetadata_User_Fragment = { createdAt: any, updatedAt: any, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null }; export type ElementMetadataFragment = | ElementMetadata_Company_Fragment @@ -69,9 +69,9 @@ export type UserQuery = { user: { id: string, username: string, email: string, d `; exports[`TypeScript Operations Plugin > Issues > #3064 - fragments over interfaces causes issues with fields 1`] = ` -"type Venue_Hotel_Fragment = { __typename?: 'Hotel', id: string, gpsPosition: { __typename?: 'GPSPosition', lat: number, lng: number } }; +"type Venue_Hotel_Fragment = { id: string, gpsPosition: { lat: number, lng: number } }; -type Venue_Transport_Fragment = { __typename?: 'Transport', id: string }; +type Venue_Transport_Fragment = { id: string }; export type VenueFragment = | Venue_Hotel_Fragment @@ -81,14 +81,14 @@ export type VenueFragment = export type QQueryVariables = Exact<{ [key: string]: never; }>; -export type QQuery = { __typename?: 'Query', hotel: { __typename?: 'Hotel', id: string, gpsPosition: { __typename?: 'GPSPosition', lat: number, lng: number } }, transport: { __typename?: 'Transport', id: string } }; +export type QQuery = { hotel: { id: string, gpsPosition: { lat: number, lng: number } }, transport: { id: string } }; " `; exports[`TypeScript Operations Plugin > Issues > #3064 - fragments over interfaces causes issues with fields 2`] = ` -"type Venue_Hotel_Fragment = { __typename?: 'Hotel', id: string, gpsPosition: { __typename?: 'GPSPosition', lat: number, lng: number } }; +"type Venue_Hotel_Fragment = { id: string, gpsPosition: { lat: number, lng: number } }; -type Venue_Transport_Fragment = { __typename?: 'Transport', id: string }; +type Venue_Transport_Fragment = { id: string }; export type VenueFragment = | Venue_Hotel_Fragment @@ -98,7 +98,7 @@ export type VenueFragment = export type QQueryVariables = Exact<{ [key: string]: never; }>; -export type QQuery = { __typename?: 'Query', hotel: { __typename?: 'Hotel', id: string, gpsPosition: { __typename?: 'GPSPosition', lat: number, lng: number } }, transport: { __typename?: 'Transport', id: string } }; +export type QQuery = { hotel: { id: string, gpsPosition: { lat: number, lng: number } }, transport: { id: string } }; function test(q: QQuery) { if (q.hotel) { const t1 = q.hotel.gpsPosition.lat @@ -114,14 +114,14 @@ exports[`TypeScript Operations Plugin > Issues > #6874 - generates types when pa "export type SnakeQueryQueryVariables = Exact<{ [key: string]: never; }>; -export type SnakeQueryQuery = { __typename?: 'Query', snake: - | { __typename?: 'Snake', name: string, features: { __typename?: 'SnakeFeatures', color: string, length: number } } - | { __typename?: 'Error' } +export type SnakeQueryQuery = { snake: + | { name: string, features: { color: string, length: number } } + | Record }; -type AnimalFragment_Bat_Fragment = { __typename?: 'Bat', features: { __typename?: 'BatFeatures', color: string, wingspan: number } }; +type AnimalFragment_Bat_Fragment = { features: { color: string, wingspan: number } }; -type AnimalFragment_Snake_Fragment = { __typename?: 'Snake', features: { __typename?: 'SnakeFeatures', color: string, length: number } }; +type AnimalFragment_Snake_Fragment = { features: { color: string, length: number } }; export type AnimalFragmentFragment = | AnimalFragment_Bat_Fragment @@ -145,18 +145,9 @@ exports[`TypeScript Operations Plugin > Selection Set > Should generate the corr "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; -export type UserQueryQuery = ( - { __typename?: 'Query' } - & { user: Maybe<( - { __typename?: 'User' } - & Pick - )> } -); +export type UserQueryQuery = { user: Maybe> }; -export type UserFragment = ( - { __typename?: 'User' } - & Pick -); +export type UserFragment = Pick; " `; @@ -164,13 +155,7 @@ exports[`TypeScript Operations Plugin > Selection Set > Should generate the corr "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; -export type UserQueryQuery = ( - { __typename?: 'Query' } - & { user: Maybe<( - { __typename?: 'User' } - & Pick - )> } -); +export type UserQueryQuery = { user: Maybe> }; " `; @@ -178,67 +163,37 @@ exports[`TypeScript Operations Plugin > Selection Set > Should generate the corr "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; -export type UserQueryQuery = ( - { __typename?: 'Query' } - & { user: Maybe<( - { __typename?: 'User' } - & Pick - )> } -); +export type UserQueryQuery = { user: Maybe> }; -export type UserFragment = ( - { __typename?: 'User' } - & Pick -); +export type UserFragment = Pick; " `; exports[`TypeScript Operations Plugin > Selection Set > Should generate the correct __typename when using fragment spread over union 1`] = ` -"export type UserFragmentFragment = ( - { __typename?: 'User' } - & Pick -); +"export type UserFragmentFragment = Pick; export type AaaQueryVariables = Exact<{ [key: string]: never; }>; -export type AaaQuery = ( - { __typename?: 'Query' } - & { user: - | ( - { __typename?: 'User' } - & Pick - ) - | { __typename?: 'Error' } - } -); +export type AaaQuery = { user: + | Pick + | Record + }; " `; -exports[`TypeScript Operations Plugin > Selection Set > Should generate the correct intersection for fragments when using with interfaces with same type 1`] = ` +exports[`TypeScript Operations Plugin > Selection Set > Should generate the correct intersection for fragments when using with interfaces with same type 2`] = ` "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; -export type Unnamed_1_Query = ( - { __typename?: 'Query' } - & { b: Maybe< - | ( - { __typename?: 'A' } - & Pick - ) - | { __typename?: 'B' } - > } -); +export type Unnamed_1_Query = { b: Maybe< + | Pick + | Record + > }; -export type AFragment = ( - { __typename?: 'A' } - & Pick -); +export type AFragment = Pick; -export type BFragment = ( - { __typename?: 'A' } - & Pick -); +export type BFragment = Pick; " `; @@ -267,9 +222,7 @@ export type NetRouteFragment = export type QqQueryVariables = Exact<{ [key: string]: never; }>; -export type QqQuery = ( - { __typename?: 'Query' } - & { routes: Array< +export type QqQuery = { routes: Array< | ( { __typename: 'IPV4Route' } & { @@ -284,8 +237,7 @@ export type QqQuery = ( ipv6Gateway: Ipv6Route['gateway'], } ) - > } -); + > }; " `; @@ -311,20 +263,15 @@ export type NetRouteFragment = | NetRoute_Ipv6Route_Fragment ; -export type TestFragment = ( - { __typename?: 'IPV6Route' } - & { +export type TestFragment = { ipv6Address: Ipv6Route['address'], ipv6Gateway: Ipv6Route['gateway'], - } -); + }; export type QqQueryVariables = Exact<{ [key: string]: never; }>; -export type QqQuery = ( - { __typename?: 'Query' } - & { routes: Array< +export type QqQuery = { routes: Array< | ( { __typename: 'IPV4Route' } & { @@ -339,31 +286,18 @@ export type QqQuery = ( ipv6Gateway: Ipv6Route['gateway'], } ) - > } -); + > }; " `; exports[`TypeScript Operations Plugin > Selection Set > Should have valid fragments intersection on different types (with usage) #2498 1`] = ` -"export type TomFragment = ( - { __typename?: 'Tom' } - & Pick -); +"export type TomFragment = Pick; -export type JerryFragment = ( - { __typename?: 'Jerry' } - & Pick -); +export type JerryFragment = Pick; -type User_Tom_Fragment = ( - { __typename?: 'Tom' } - & Pick -); +type User_Tom_Fragment = Pick; -type User_Jerry_Fragment = ( - { __typename?: 'Jerry' } - & Pick -); +type User_Jerry_Fragment = Pick; export type UserFragment = | User_Tom_Fragment @@ -373,19 +307,10 @@ export type UserFragment = export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; -export type UserQueryQuery = ( - { __typename?: 'Query' } - & { user: Maybe< - | ( - { __typename?: 'Tom' } - & Pick - ) - | ( - { __typename?: 'Jerry' } - & Pick - ) - > } -); +export type UserQueryQuery = { user: Maybe< + | Pick + | Pick + > }; " `; @@ -393,23 +318,13 @@ exports[`TypeScript Operations Plugin > Union & Interfaces > #4216 - handle frag "export type SearchPopularQueryVariables = Exact<{ [key: string]: never; }>; -export type SearchPopularQuery = ( - { __typename?: 'Query' } - & { search: Maybe | ( - { __typename?: 'Dimension' } - & Pick + Pick + & { dimension: Maybe> } ) - | ( - { __typename?: 'DimValue' } - & Pick - & { dimension: Maybe<( - { __typename?: 'Dimension' } - & Pick - )> } - ) - >> } -); + >> }; " `; @@ -417,70 +332,33 @@ exports[`TypeScript Operations Plugin > Union & Interfaces > Should handle union "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; -export type UserQueryQuery = ( - { __typename?: 'Query' } - & { user: - | ( - { __typename?: 'User' } - & Pick - ) - | ( - { __typename?: 'Error2' } - & Pick - ) +export type UserQueryQuery = { user: + | Pick + | Pick | ( - { __typename?: 'Error3' } - & Pick - & { info: Maybe<( - { __typename?: 'AdditionalInfo' } - & Pick - )> } + Pick + & { info: Maybe> } ) - } -); + }; -export type AdditionalInfoFragment = ( - { __typename?: 'AdditionalInfo' } - & Pick -); +export type AdditionalInfoFragment = Pick; -type UserResult1_User_Fragment = ( - { __typename?: 'User' } - & Pick -); +type UserResult1_User_Fragment = Pick; -type UserResult1_Error2_Fragment = { __typename?: 'Error2' }; - -type UserResult1_Error3_Fragment = ( - { __typename?: 'Error3' } - & { info: Maybe<( - { __typename?: 'AdditionalInfo' } - & Pick - )> } -); +type UserResult1_Error3_Fragment = { info: Maybe> }; export type UserResult1Fragment = | UserResult1_User_Fragment - | UserResult1_Error2_Fragment | UserResult1_Error3_Fragment ; -type UserResult_User_Fragment = ( - { __typename?: 'User' } - & Pick -); - -type UserResult_Error2_Fragment = ( - { __typename?: 'Error2' } - & Pick -); +type UserResult_User_Fragment = Pick; -type UserResult_Error3_Fragment = { __typename?: 'Error3' }; +type UserResult_Error2_Fragment = Pick; export type UserResultFragment = | UserResult_User_Fragment | UserResult_Error2_Fragment - | UserResult_Error3_Fragment ; " `; @@ -489,27 +367,14 @@ exports[`TypeScript Operations Plugin > Union & Interfaces > Should handle union "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; -export type UserQueryQuery = ( - { __typename?: 'Query' } - & { user: - | ( - { __typename?: 'User' } - & Pick - ) +export type UserQueryQuery = { user: + | Pick + | Pick | ( - { __typename?: 'Error2' } - & Pick + Pick + & { info: Maybe> } ) - | ( - { __typename?: 'Error3' } - & Pick - & { info: Maybe<( - { __typename?: 'AdditionalInfo' } - & Pick - )> } - ) - } -); + }; function t(q: UserQueryQuery) { if (q.user) { @@ -534,33 +399,20 @@ exports[`TypeScript Operations Plugin > Union & Interfaces > Should handle union "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; -export type UserQueryQuery = ( - { __typename?: 'Query' } - & { user: - | ( - { __typename?: 'User' } - & Pick< +export type UserQueryQuery = { user: + | Pick< User, | 'id' | 'test2' | 'login' | 'test' > - ) + | Pick | ( - { __typename?: 'Error2' } - & Pick + Pick + & { info: Maybe> } ) - | ( - { __typename?: 'Error3' } - & Pick - & { info: Maybe<( - { __typename?: 'AdditionalInfo' } - & Pick - )> } - ) - } -); + }; function t(q: UserQueryQuery) { if (q.user) { diff --git a/packages/plugins/typescript/operations/tests/ts-documents.apolloUnmask.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.apolloUnmask.spec.ts index 904eb73cb55..0f7d7294a64 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.apolloUnmask.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.apolloUnmask.spec.ts @@ -25,9 +25,9 @@ describe('TypeScript Operations Plugin - apolloUnmask', () => { "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type Unnamed_1_Query = { me: { id: string } | null }; - export type UserFragmentFragment = { __typename?: 'User', id: string } & { ' $fragmentName'?: 'UserFragmentFragment' }; + export type UserFragmentFragment = { id: string } & { ' $fragmentName'?: 'UserFragmentFragment' }; " `); }); @@ -53,12 +53,9 @@ describe('TypeScript Operations Plugin - apolloUnmask', () => { "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { __typename?: 'Query', me: ( - { __typename?: 'User' } - & { ' $fragmentRefs'?: { 'UserFragmentFragment': UserFragmentFragment } } - ) | null }; + export type Unnamed_1_Query = { me: { ' $fragmentRefs'?: { 'UserFragmentFragment': UserFragmentFragment } } | null }; - export type UserFragmentFragment = { __typename?: 'User', id: string } & { ' $fragmentName'?: 'UserFragmentFragment' }; + export type UserFragmentFragment = { id: string } & { ' $fragmentName'?: 'UserFragmentFragment' }; " `); }); @@ -87,12 +84,9 @@ describe('TypeScript Operations Plugin - apolloUnmask', () => { "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { __typename?: 'Query', me: ( - { __typename?: 'User' } - & { ' $fragmentRefs'?: { 'UserFragmentFragment': UserFragmentFragment } } - ) | null }; + export type Unnamed_1_Query = { me: { ' $fragmentRefs'?: { 'UserFragmentFragment': UserFragmentFragment } } | null }; - export type UserFragmentFragment = { __typename?: 'User', id: string } & { ' $fragmentName'?: 'UserFragmentFragment' }; + export type UserFragmentFragment = { id: string } & { ' $fragmentName'?: 'UserFragmentFragment' }; " `); }); @@ -123,14 +117,14 @@ describe('TypeScript Operations Plugin - apolloUnmask', () => { "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { __typename?: 'Query', me: ( - { __typename?: 'User', id: string } + export type Unnamed_1_Query = { me: ( + { id: string } & { ' $fragmentRefs'?: { 'UserFragment2Fragment': UserFragment2Fragment } } ) | null }; - export type UserFragmentFragment = { __typename?: 'User', id: string } & { ' $fragmentName'?: 'UserFragmentFragment' }; + export type UserFragmentFragment = { id: string } & { ' $fragmentName'?: 'UserFragmentFragment' }; - export type UserFragment2Fragment = { __typename?: 'User', email: string } & { ' $fragmentName'?: 'UserFragment2Fragment' }; + export type UserFragment2Fragment = { email: string } & { ' $fragmentName'?: 'UserFragment2Fragment' }; " `); }); @@ -162,14 +156,14 @@ describe('TypeScript Operations Plugin - apolloUnmask', () => { "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { __typename?: 'Query', me: ( - { __typename?: 'User', id: string, email: string } + export type Unnamed_1_Query = { me: ( + { id: string, email: string } & { ' $fragmentRefs'?: { 'UserFragment2Fragment': UserFragment2Fragment } } ) | null }; - export type UserFragmentFragment = { __typename?: 'User', id: string, email: string } & { ' $fragmentName'?: 'UserFragmentFragment' }; + export type UserFragmentFragment = { id: string, email: string } & { ' $fragmentName'?: 'UserFragmentFragment' }; - export type UserFragment2Fragment = { __typename?: 'User', email: string } & { ' $fragmentName'?: 'UserFragment2Fragment' }; + export type UserFragment2Fragment = { email: string } & { ' $fragmentName'?: 'UserFragment2Fragment' }; " `); }); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.nullability.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.nullability.spec.ts index f4eac85be0c..43364d22955 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.nullability.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.nullability.spec.ts @@ -80,9 +80,7 @@ describe('TypeScript Operations Plugin - nullability', () => { "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never }>; export type Unnamed_1_Query = { - __typename?: "Query"; me: { - __typename?: "User"; field: string; fieldLevel0: string; fieldLevel1: string | null; @@ -128,9 +126,7 @@ describe('TypeScript Operations Plugin - nullability', () => { "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never }>; export type Unnamed_1_Query = { - __typename?: "Query"; me: { - __typename?: "User"; field: string | null; fieldLevel0: string | null; fieldLevel1: string | null; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts index 5ac885c7151..b0fa860ef10 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts @@ -1,7 +1,6 @@ import { buildClientSchema, buildSchema, parse } from 'graphql'; import { mergeOutputs, Types } from '@graphql-codegen/plugin-helpers'; import { validateTs } from '@graphql-codegen/testing'; -import { plugin as tsPlugin } from '../../typescript/src/index.js'; import { plugin } from '../src/index.js'; import { schema } from './shared/schema.js'; @@ -83,22 +82,21 @@ describe('TypeScript Operations Plugin', () => { }, ); - expect(content).toBeSimilarStringTo(` - export type NotificationsQuery = ( - { __typename?: 'Query' } - & { notifications: Array<( - { __typename?: 'TextNotification' } - & Pick - & { textAlias: Types.TextNotification['text'] } - ) | ( - { __typename?: 'ImageNotification' } - & Pick - & { metadata: ( - { __typename?: 'ImageMetadata' } - & { created: Types.ImageMetadata['createdBy'] } - ) } - )> } - ); + expect(content).toMatchInlineSnapshot(` + "export type NotificationsQueryVariables = Exact<{ [key: string]: never; }>; + + + export type NotificationsQuery = { notifications: Array< + | ( + Pick + & { textAlias: Types.TextNotification['text'] } + ) + | ( + Pick + & { metadata: { created: Types.ImageMetadata['createdBy'] } } + ) + > }; + " `); await validate(content); }); @@ -154,10 +152,17 @@ describe('TypeScript Operations Plugin', () => { outputFile: '', }, ); - expect(content).toBeSimilarStringTo(` - export type PostFragment = { __typename?: 'Post', id: string, comments: Array<{ __typename?: 'TextComment', text: string } | { __typename?: 'ImageComment' }> }; + expect(content).toMatchInlineSnapshot(` + "export type PostFragment = { id: string, comments: Array< + | { text: string } + | Record + > }; - export type PostPlusFragment = { __typename?: 'Post', id: string, comments: Array<{ __typename?: 'TextComment', text: string, id: string } | { __typename?: 'ImageComment', id: string }> }; + export type PostPlusFragment = { id: string, comments: Array< + | { text: string, id: string } + | { id: string } + > }; + " `); }); @@ -201,6 +206,20 @@ describe('TypeScript Operations Plugin', () => { }, ); + expect(content).toMatchInlineSnapshot( + ` + "export type E = + | 'A' + | 'B'; + + export type TestQueryVariables = Exact<{ [key: string]: never; }>; + + + export type TestQuery = { f: Types.E | null, user: { id: string, f: Types.E | null, j: any | null } }; + " + `, + ); + expect(content).toBeSimilarStringTo( `export type TestQuery = { __typename?: 'Query', f: Types.E | null, user: { __typename?: 'User', id: string, f: Types.E | null, j: any | null } };`, ); @@ -241,21 +260,18 @@ describe('TypeScript Operations Plugin', () => { }, ); - expect(content).toBeSimilarStringTo(` - export type notificationsquery = ( - { readonly __typename?: 'Query' } - & { readonly notifications: ReadonlyArray<( - { readonly __typename?: 'TextNotification' } - & Pick - ) | ( - { readonly __typename?: 'ImageNotification' } - & Pick - & { readonly metadata: ( - { readonly __typename?: 'ImageMetadata' } - & Pick - ) } - )> } - ); + expect(content).toMatchInlineSnapshot(` + "export type notificationsqueryvariables = Exact<{ [key: string]: never; }>; + + + export type notificationsquery = { readonly notifications: ReadonlyArray< + | Pick + | ( + Pick + & { readonly metadata: Pick } + ) + > }; + " `); await validate(content); }); @@ -323,8 +339,14 @@ describe('TypeScript Operations Plugin', () => { outputFile: 'graphql.ts', }, ); - expect(content).toBeSimilarStringTo(` - export type UserQuery = { __typename?: 'Query', user: { __typename?: 'User', name: string, age: number | 'specialType', address?: string, nicknames?: Array | 'specialType', parents?: Array } }; + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + showProperty: boolean; + }>; + + + export type UserQuery = { user: { name: string, age: number | 'specialType', address?: string, nicknames?: Array | 'specialType', parents?: Array } }; + " `); }); @@ -367,10 +389,14 @@ describe('TypeScript Operations Plugin', () => { }, ); - expect(content).toBeSimilarStringTo(` - export type UserQueryVariables = Exact<{ + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ showProperty: boolean; }> | undefined; + + + export type UserQuery = { user: { name: string, age: number | null, address?: string, nicknames?: Array | null, parents?: Array } }; + " `); }); }); @@ -443,24 +469,18 @@ describe('TypeScript Operations Plugin', () => { }, ); - expect(content).toBeSimilarStringTo( - `export type NotificationsQueryVariables = Exact<{ [key: string]: never; }>;`, - ); - expect(content).toBeSimilarStringTo(` - export type NotificationsQueryResult = ( - { __typename?: 'Query' } - & { notifications: Array<( - { __typename?: 'TextNotification' } - & Pick - ) | ( - { __typename?: 'ImageNotification' } - & Pick - & { metadata: ( - { __typename?: 'ImageMetadata' } - & Pick - ) } - )> } - ); + expect(content).toMatchInlineSnapshot(` + "export type NotificationsQueryVariables = Exact<{ [key: string]: never; }>; + + + export type NotificationsQueryResult = { notifications: Array< + | Pick + | ( + Pick + & { metadata: Pick } + ) + > }; + " `); await validate(content); @@ -500,21 +520,18 @@ describe('TypeScript Operations Plugin', () => { }, ); - expect(content).toBeSimilarStringTo(` - export type notificationsquery = ( - { __typename?: 'Query' } - & { notifications: Array<( - { __typename?: 'TextNotification' } - & Pick - ) | ( - { __typename?: 'ImageNotification' } - & Pick - & { metadata: ( - { __typename?: 'ImageMetadata' } - & Pick - ) } - )> } - ); + expect(content).toMatchInlineSnapshot(` + "export type notificationsqueryvariables = Exact<{ [key: string]: never; }>; + + + export type notificationsquery = { notifications: Array< + | Pick + | ( + Pick + & { metadata: Pick } + ) + > }; + " `); await validate(content); }); @@ -553,24 +570,18 @@ describe('TypeScript Operations Plugin', () => { }, ); - expect(content).toBeSimilarStringTo( - `export type inotificationsqueryvariables = Exact<{ [key: string]: never; }>;`, - ); - expect(content).toBeSimilarStringTo(` - export type inotificationsquery = ( - { __typename?: 'Query' } - & { notifications: Array<( - { __typename?: 'TextNotification' } - & Pick - ) | ( - { __typename?: 'ImageNotification' } - & Pick - & { metadata: ( - { __typename?: 'ImageMetadata' } - & Pick - ) } - )> } - ); + expect(content).toMatchInlineSnapshot(` + "export type inotificationsqueryvariables = Exact<{ [key: string]: never; }>; + + + export type inotificationsquery = { notifications: Array< + | Pick + | ( + Pick + & { metadata: Pick } + ) + > }; + " `); await validate(content); }); @@ -703,29 +714,35 @@ describe('TypeScript Operations Plugin', () => { { outputFile: '' }, ) ).content; - expect(withUsage).toBeSimilarStringTo(` - export type MyFragment = ( - { __typename?: 'Query' } - & { notifications: Array<( - { __typename?: 'TextNotification' } - & Pick - ) | ( - { __typename?: 'ImageNotification' } - & Pick - )> } - ); + expect(withUsage).toMatchInlineSnapshot(` + "export type NotificationsQueryVariables = Exact<{ [key: string]: never; }>; + + + export type NotificationsQuery = { notifications: Array< + | Pick + | Pick + > }; + + export type MyFragment = { notifications: Array< + | Pick + | Pick + > }; + " `); - expect(withUsage).toBeSimilarStringTo(` - export type NotificationsQuery = ( - { __typename?: 'Query' } - & { notifications: Array<( - { __typename?: 'TextNotification' } - & Pick - ) | ( - { __typename?: 'ImageNotification' } - & Pick - )> } - ); + expect(withUsage).toMatchInlineSnapshot(` + "export type NotificationsQueryVariables = Exact<{ [key: string]: never; }>; + + + export type NotificationsQuery = { notifications: Array< + | Pick + | Pick + > }; + + export type MyFragment = { notifications: Array< + | Pick + | Pick + > }; + " `); }); }); @@ -858,29 +875,35 @@ describe('TypeScript Operations Plugin', () => { { outputFile: '' }, ) ).content; - expect(withUsage).toBeSimilarStringTo(` - export type My = ( - { __typename?: 'Query' } - & { notifications: Array<( - { __typename?: 'TextNotification' } - & Pick - ) | ( - { __typename?: 'ImageNotification' } - & Pick - )> } - ); + expect(withUsage).toMatchInlineSnapshot(` + "export type NotificationsVariables = Exact<{ [key: string]: never; }>; + + + export type Notifications = { notifications: Array< + | Pick + | Pick + > }; + + export type My = { notifications: Array< + | Pick + | Pick + > }; + " `); - expect(withUsage).toBeSimilarStringTo(` - export type Notifications = ( - { __typename?: 'Query' } - & { notifications: Array<( - { __typename?: 'TextNotification' } - & Pick - ) | ( - { __typename?: 'ImageNotification' } - & Pick - )> } - ); + expect(withUsage).toMatchInlineSnapshot(` + "export type NotificationsVariables = Exact<{ [key: string]: never; }>; + + + export type Notifications = { notifications: Array< + | Pick + | Pick + > }; + + export type My = { notifications: Array< + | Pick + | Pick + > }; + " `); }); @@ -915,11 +938,14 @@ describe('TypeScript Operations Plugin', () => { }, ); - expect(content).toBeSimilarStringTo( - `export type Q1Query = { test: Maybe<( - { __typename?: 'Test' } - & Pick - )> };`, + expect(content).toMatchInlineSnapshot( + ` + "export type Q1QueryVariables = Exact<{ [key: string]: never; }>; + + + export type Q1Query = { test: Maybe> }; + " + `, ); await validate(content); }); @@ -955,11 +981,17 @@ describe('TypeScript Operations Plugin', () => { }, ); - expect(content).toBeSimilarStringTo( - `export type Q1Query = { test: Maybe<( - { __typename: 'Test' } - & Pick - )> };`, + expect(content).toMatchInlineSnapshot( + ` + "export type Q1QueryVariables = Exact<{ [key: string]: never; }>; + + + export type Q1Query = { test: Maybe<( + { __typename: 'Test' } + & Pick + )> }; + " + `, ); await validate(content); }); @@ -996,14 +1028,20 @@ describe('TypeScript Operations Plugin', () => { }, ); - expect(content).toBeSimilarStringTo( - `export type Q1Query = ( + expect(content).toMatchInlineSnapshot( + ` + "export type Q1QueryVariables = Exact<{ [key: string]: never; }>; + + + export type Q1Query = ( { __typename: 'Query' } & { test: Maybe<( { __typename: 'Test' } & Pick )> } - );`, + ); + " + `, ); await validate(content); }); @@ -1150,17 +1188,36 @@ export type Q2Query = { search: Array< outputFile: '', }, ); - expect(content).toBeSimilarStringTo(` - export type TestQuery = ( - { __typename?: 'Query' } - & { some: Maybe<( + expect(content).toMatchInlineSnapshot(` + "type Node_A_Fragment = ( { __typename: 'A' } & Pick - ) | ( + ); + + type Node_B_Fragment = ( { __typename: 'B' } & Pick - )> } - ); + ); + + export type NodeFragment = + | Node_A_Fragment + | Node_B_Fragment + ; + + export type TestQueryVariables = Exact<{ [key: string]: never; }>; + + + export type TestQuery = { some: Maybe< + | ( + { __typename: 'A' } + & Pick + ) + | ( + { __typename: 'B' } + & Pick + ) + > }; + " `); await validate(content); }); @@ -1181,12 +1238,15 @@ export type Q2Query = { search: Array< outputFile: '', }, ); - expect(content).toBeSimilarStringTo(` - export type Unnamed_1_Query = ( - { __typename?: 'Query' } - & Pick - & { type: 'Query' } - ); + expect(content).toMatchInlineSnapshot(` + "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + + + export type Unnamed_1_Query = ( + Pick + & { type: 'Query' } + ); + " `); await validate(content); }); @@ -1207,8 +1267,12 @@ export type Q2Query = { search: Array< outputFile: '', }, ); - expect(content).toBeSimilarStringTo(` - export type Unnamed_1_Query = { __typename?: 'Query', dummy: string | null, type: 'Query' }; + expect(content).toMatchInlineSnapshot(` + "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + + + export type Unnamed_1_Query = { dummy: string | null, type: 'Query' }; + " `); await validate(content); }); @@ -1229,11 +1293,15 @@ export type Q2Query = { search: Array< outputFile: '', }, ); - expect(content).toBeSimilarStringTo(` + expect(content).toMatchInlineSnapshot(` + "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + + export type Unnamed_1_Query = ( { __typename: 'Query' } & Pick ); + " `); await validate(content); }); @@ -1253,11 +1321,15 @@ export type Q2Query = { search: Array< outputFile: '', }, ); - expect(content).toBeSimilarStringTo(` + expect(content).toMatchInlineSnapshot(` + "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + + export type Unnamed_1_Query = ( { __typename: 'Query' } & Pick ); + " `); await validate(content); }); @@ -1277,11 +1349,12 @@ export type Q2Query = { search: Array< outputFile: '', }, ); - expect(content).toBeSimilarStringTo(` - export type Unnamed_1_Query = ( - { __typename?: 'Query' } - & Pick - ); + expect(content).toMatchInlineSnapshot(` + "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + + + export type Unnamed_1_Query = Pick; + " `); await validate(content); }); @@ -1303,11 +1376,15 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` + expect(content).toMatchInlineSnapshot(` + "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + + export type Unnamed_1_Query = ( { __typename: 'Query' } & Pick ); + " `); await validate(content); }); @@ -1335,17 +1412,15 @@ export type Q2Query = { search: Array< outputFile: '', }, ); - expect(content).toBeSimilarStringTo(` - export type UnionTestQuery = ( - { __typename?: 'Query' } - & { unionTest: Maybe<( - { __typename?: 'User' } - & Pick - ) | ( - { __typename?: 'Profile' } - & Pick - )> } - ); + expect(content).toMatchInlineSnapshot(` + "export type UnionTestQueryVariables = Exact<{ [key: string]: never; }>; + + + export type UnionTestQuery = { unionTest: Maybe< + | Pick + | Pick + > }; + " `); await validate(content); }); @@ -1378,21 +1453,18 @@ export type Q2Query = { search: Array< outputFile: '', }, ); - expect(content).toBeSimilarStringTo(` - export type NotificationsQuery = ( - { __typename?: 'Query' } - & { notifications: Array<( - { __typename?: 'TextNotification' } - & Pick - ) | ( - { __typename?: 'ImageNotification' } - & Pick - & { metadata: ( - { __typename?: 'ImageMetadata' } - & Pick - ) } - )> } - ); + expect(content).toMatchInlineSnapshot(` + "export type NotificationsQueryVariables = Exact<{ [key: string]: never; }>; + + + export type NotificationsQuery = { notifications: Array< + | Pick + | ( + Pick + & { metadata: Pick } + ) + > }; + " `); await validate(content); }); @@ -1419,17 +1491,21 @@ export type Q2Query = { search: Array< outputFile: '', }, ); - expect(content).toBeSimilarStringTo(` - export type NotificationsQuery = ( - { __typename?: 'Query' } - & { notifications: Array<( - { __typename: 'TextNotification' } - & Pick - ) | ( - { __typename: 'ImageNotification' } - & Pick - )> } - ); + expect(content).toMatchInlineSnapshot(` + "export type NotificationsQueryVariables = Exact<{ [key: string]: never; }>; + + + export type NotificationsQuery = { notifications: Array< + | ( + { __typename: 'TextNotification' } + & Pick + ) + | ( + { __typename: 'ImageNotification' } + & Pick + ) + > }; + " `); await validate(content); }); @@ -1456,16 +1532,21 @@ export type Q2Query = { search: Array< outputFile: '', }, ); - expect(content).toBeSimilarStringTo(` - { __typename?: 'Query' } - & { unionTest: Maybe<( - { __typename: 'User' } - & Pick - ) | ( - { __typename: 'Profile' } - & Pick - )> } - ); + expect(content).toMatchInlineSnapshot(` + "export type UnionTestQueryVariables = Exact<{ [key: string]: never; }>; + + + export type UnionTestQuery = { unionTest: Maybe< + | ( + { __typename: 'User' } + & Pick + ) + | ( + { __typename: 'Profile' } + & Pick + ) + > }; + " `); await validate(content); }); @@ -1487,11 +1568,19 @@ export type Q2Query = { search: Array< outputFile: '', }, ); - expect(content).toBeSimilarStringTo(` + expect(content).toMatchInlineSnapshot(` + "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + + export type Unnamed_1_Query = Pick; + " `); - expect(content).toBeSimilarStringTo(` - export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + expect(content).toMatchInlineSnapshot(` + "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + + + export type Unnamed_1_Query = Pick; + " `); await validate(content); }); @@ -1516,17 +1605,53 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` + expect(content).toMatchInlineSnapshot(` + "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + + export type Unnamed_1_Query = Pick; - `); - expect(content).toBeSimilarStringTo(` - export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - `); - expect(content).toBeSimilarStringTo(` - export type Unnamed_2_Query = Pick; - `); - expect(content).toBeSimilarStringTo(` + export type Unnamed_2_QueryVariables = Exact<{ [key: string]: never; }>; + + + export type Unnamed_2_Query = Pick; + " + `); + expect(content).toMatchInlineSnapshot(` + "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + + + export type Unnamed_1_Query = Pick; + + export type Unnamed_2_QueryVariables = Exact<{ [key: string]: never; }>; + + + export type Unnamed_2_Query = Pick; + " + `); + expect(content).toMatchInlineSnapshot(` + "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + + + export type Unnamed_1_Query = Pick; + + export type Unnamed_2_QueryVariables = Exact<{ [key: string]: never; }>; + + + export type Unnamed_2_Query = Pick; + " + `); + expect(content).toMatchInlineSnapshot(` + "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + + + export type Unnamed_1_Query = Pick; + + export type Unnamed_2_QueryVariables = Exact<{ [key: string]: never; }>; + + + export type Unnamed_2_Query = Pick; + " `); await validate(content); }); @@ -1937,11 +2062,24 @@ export type Q2Query = { search: Array< outputFile: '', }, ); - expect(content).toBeSimilarStringTo(` + expect(content).toMatchInlineSnapshot(` + "export type Role = + | 'USER' + | 'ADMIN'; + + export type UserFieldsFragment = ( + Pick + & { profile: Maybe> } + ); + + export type MeQueryVariables = Exact<{ [key: string]: never; }>; + + export type MeQuery = { me: Maybe<( Pick & { profile: Maybe> } )> }; + " `); await validate(content); }); @@ -1972,11 +2110,20 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - export type MeQuery = { me: Maybe<( - Pick - & { profile: Maybe> } - )> }; + expect(content).toMatchInlineSnapshot(` + "export type UserFieldsFragment = ( + Pick + & { profile: Maybe> } + ); + + export type MeQueryVariables = Exact<{ [key: string]: never; }>; + + + export type MeQuery = { me: Maybe<( + Pick + & { profile: Maybe> } + )> }; + " `); await validate(content); }); @@ -2011,33 +2158,47 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - export type MeQuery = ( - { __typename?: 'Query' } - & { me: Maybe<( - { __typename?: 'User' } - & Pick - & { profile: Maybe<( - { __typename?: 'Profile' } - & Pick - )> } - )> } - ); + expect(content).toMatchInlineSnapshot(` + "export type UserFieldsFragment = Pick; + + export type UserProfileFragment = { profile: Maybe> }; + + export type MeQueryVariables = Exact<{ [key: string]: never; }>; + + + export type MeQuery = { me: Maybe<( + Pick + & { profile: Maybe> } + )> }; + " `); - expect(content).toBeSimilarStringTo(` - export type UserProfileFragment = ( - { __typename?: 'User' } - & { profile: Maybe<( - { __typename?: 'Profile' } - & Pick - )> } - ); + expect(content).toMatchInlineSnapshot(` + "export type UserFieldsFragment = Pick; + + export type UserProfileFragment = { profile: Maybe> }; + + export type MeQueryVariables = Exact<{ [key: string]: never; }>; + + + export type MeQuery = { me: Maybe<( + Pick + & { profile: Maybe> } + )> }; + " `); - expect(content).toBeSimilarStringTo(` - export type UserFieldsFragment = ( - { __typename?: 'User' } - & Pick - ); + expect(content).toMatchInlineSnapshot(` + "export type UserFieldsFragment = Pick; + + export type UserProfileFragment = { profile: Maybe> }; + + export type MeQueryVariables = Exact<{ [key: string]: never; }>; + + + export type MeQuery = { me: Maybe<( + Pick + & { profile: Maybe> } + )> }; + " `); await validate(content); }); @@ -2091,27 +2252,19 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - export type Unnamed_1_Query = ( - { __typename?: 'Query' } - & { b: Maybe<( - { __typename?: 'A' } - & Pick - ) | ( - { __typename?: 'B' } - & Pick - )> } - ); + expect(content).toMatchInlineSnapshot(` + "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type AFragment = ( - { __typename?: 'A' } - & Pick - ); - export type BFragment = ( - { __typename?: 'B' } - & Pick - ); + export type Unnamed_1_Query = { b: Maybe< + | Pick + | Pick + > }; + + export type AFragment = Pick; + + export type BFragment = Pick; + " `); await validate(content); }); @@ -2167,14 +2320,18 @@ export type Q2Query = { search: Array< outputFile: '', }, ); - expect(content).toBeSimilarStringTo(` - export type Unnamed_1_Query = ( - { __typename?: 'Query' } - & { myType: ( - { __typename?: 'MyType' } - & Pick - ) } - ); + expect(content).toMatchInlineSnapshot(` + "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + + + export type Unnamed_1_Query = { myType: Pick }; + + export type CFragment = Pick; + + export type AFragment = Pick; + + export type BFragment = Pick; + " `); await validate(content); }); @@ -2226,24 +2383,19 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - export type Unnamed_1_Query = ( - { __typename?: 'Query' } - & { b: Maybe<( - { __typename?: 'A' } - & Pick - ) | { __typename?: 'B' }> } - ); + expect(content).toMatchInlineSnapshot(` + "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type AFragment = ( - { __typename?: 'A' } - & Pick - ); - export type BFragment = ( - { __typename?: 'A' } - & Pick - ); + export type Unnamed_1_Query = { b: Maybe< + | Pick + | Record + > }; + + export type AFragment = Pick; + + export type BFragment = Pick; + " `); validateTs(mergeOutputs([content]), config); expect(mergeOutputs([content])).toMatchSnapshot(); @@ -2278,21 +2430,18 @@ export type Q2Query = { search: Array< outputFile: '', }, ); - expect(content).toBeSimilarStringTo(` - export type NotificationsQuery = ( - { __typename?: 'Query' } - & { notifications: Array<( - { __typename?: 'TextNotification' } - & Pick - ) | ( - { __typename?: 'ImageNotification' } - & Pick - & { metadata: ( - { __typename?: 'ImageMetadata' } - & Pick - ) } - )> } - ); + expect(content).toMatchInlineSnapshot(` + "export type NotificationsQueryVariables = Exact<{ [key: string]: never; }>; + + + export type NotificationsQuery = { notifications: Array< + | Pick + | ( + Pick + & { metadata: Pick } + ) + > }; + " `); await validate(content); }); @@ -2321,17 +2470,15 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - export type UnionTestQuery = ( - { __typename?: 'Query' } - & { unionTest: Maybe<( - { __typename?: 'User' } - & Pick - ) | ( - { __typename?: 'Profile' } - & Pick - )> } - ); + expect(content).toMatchInlineSnapshot(` + "export type UnionTestQueryVariables = Exact<{ [key: string]: never; }>; + + + export type UnionTestQuery = { unionTest: Maybe< + | Pick + | Pick + > }; + " `); await validate(content); }); @@ -2364,17 +2511,15 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - export type UnionTestQuery = ( - { __typename?: 'Query' } - & { mixedNotifications: Array<( - { __typename?: 'TextNotification' } - & Pick - ) | ( - { __typename?: 'ImageNotification' } - & Pick - )> } - ); + expect(content).toMatchInlineSnapshot(` + "export type UnionTestQueryVariables = Exact<{ [key: string]: never; }>; + + + export type UnionTestQuery = { mixedNotifications: Array< + | Pick + | Pick + > }; + " `); await validate(content); }); @@ -2411,20 +2556,16 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - export type UnionTestQuery = ( - { __typename?: 'Query' } - & { search: Array<( - { __typename?: 'TextNotification' } - & Pick - ) | ( - { __typename?: 'ImageNotification' } - & Pick - ) | ( - { __typename?: 'User' } - & Pick - )> } - ); + expect(content).toMatchInlineSnapshot(` + "export type UnionTestQueryVariables = Exact<{ [key: string]: never; }>; + + + export type UnionTestQuery = { search: Array< + | Pick + | Pick + | Pick + > }; + " `); await validate(content); }); @@ -2455,22 +2596,15 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - export type testQueryVariables = Exact<{ [key: string]: never; }>; + expect(content).toMatchInlineSnapshot(` + "export type testQueryVariables = Exact<{ [key: string]: never; }>; - export type testQuery = ( - { notifications: Array<( - { id: string } - & { __typename?: 'TextNotification' | 'ImageNotification' } - )> } - & { __typename?: 'Query' } - ); - export type NFragment = ( - { id: string } - & { __typename?: 'TextNotification' | 'ImageNotification' } - ); - `); + export type testQuery = { notifications: Array<{ id: string }> }; + + export type NFragment = { id: string }; + " + `); await validate(content); }); @@ -2497,18 +2631,16 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - type N_TextNotification_Fragment = ( - { text: string, id: string } - & { __typename?: 'TextNotification' } - ); + expect(content).toMatchInlineSnapshot(` + "type N_TextNotification_Fragment = { text: string, id: string }; - type N_ImageNotification_Fragment = ( - { id: string } - & { __typename?: 'ImageNotification' } - ); + type N_ImageNotification_Fragment = { id: string }; - export type NFragment = N_TextNotification_Fragment | N_ImageNotification_Fragment; + export type NFragment = + | N_TextNotification_Fragment + | N_ImageNotification_Fragment + ; + " `); await validate(content); }); @@ -2567,18 +2699,16 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - type N_A_Fragment = ( - { text: string, id: string } - & { __typename?: 'A' } - ); + expect(content).toMatchInlineSnapshot(` + "type N_A_Fragment = { text: string, id: string }; - type N_zhJJUzpMTyh98zugnx0IKwiLetPNjV8KybSlmpAEUU_Fragment = ( - { id: string } - & { __typename?: 'B' | 'C' | 'D' | 'E' } - ); + type N_ZMkK3KeglIQrCEb6gIP8zgzig3OXIb4iuHrFFPW86a4_Fragment = { id: string }; - export type NFragment = N_A_Fragment | N_zhJJUzpMTyh98zugnx0IKwiLetPNjV8KybSlmpAEUU_Fragment; + export type NFragment = + | N_A_Fragment + | N_ZMkK3KeglIQrCEb6gIP8zgzig3OXIb4iuHrFFPW86a4_Fragment + ; + " `); await validate(content); }); @@ -2607,14 +2737,9 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - export type NFragment = ( - { notifications: Array<( - { text: string } - & { __typename?: 'TextNotification' } - ) | { __typename?: 'ImageNotification' }> } - & { __typename?: 'Query' } - ); + expect(content).toMatchInlineSnapshot(` + "export type NFragment = { notifications: Array<{ text: string }> }; + " `); await validate(content); }); @@ -2646,10 +2771,14 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - export type testQueryVariables = Exact<{ [key: string]: never; }>; + expect(content).toMatchInlineSnapshot(` + "export type testQueryVariables = Exact<{ [key: string]: never; }>; + export type testQuery = { notifications: Array<{ id: string }> }; + + export type NFragment = { id: string }; + " `); await validate(content); }); @@ -2678,12 +2807,16 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - type N_TextNotification_Fragment = { text: string, id: string }; + expect(content).toMatchInlineSnapshot(` + "type N_TextNotification_Fragment = { text: string, id: string }; - type N_ImageNotification_Fragment = { id: string }; + type N_ImageNotification_Fragment = { id: string }; - export type NFragment = N_TextNotification_Fragment | N_ImageNotification_Fragment; + export type NFragment = + | N_TextNotification_Fragment + | N_ImageNotification_Fragment + ; + " `); await validate(content); }); @@ -2714,24 +2847,25 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - export type TestQueryVariables = Exact<{ [key: string]: never; }>; + expect(content).toMatchInlineSnapshot(` + "export type TestQueryVariables = Exact<{ [key: string]: never; }>; - export type TestQuery = { __typename?: 'Query', notifications: Array<( - { __typename?: 'TextNotification' } - & { ' $fragmentRefs'?: { 'N_TextNotification_Fragment': N_TextNotification_Fragment } } - ) | ( - { __typename?: 'ImageNotification' } - & { ' $fragmentRefs'?: { 'N_ImageNotification_Fragment': N_ImageNotification_Fragment } } - )> }; + export type TestQuery = { notifications: Array< + | { ' $fragmentRefs'?: { 'N_TextNotification_Fragment': N_TextNotification_Fragment } } + | { ' $fragmentRefs'?: { 'N_ImageNotification_Fragment': N_ImageNotification_Fragment } } + > }; - type N_TextNotification_Fragment = { __typename?: 'TextNotification', id: string } & { ' $fragmentName'?: 'N_TextNotification_Fragment' }; + type N_TextNotification_Fragment = { id: string } & { ' $fragmentName'?: 'N_TextNotification_Fragment' }; - type N_ImageNotification_Fragment = { __typename?: 'ImageNotification', id: string } & { ' $fragmentName'?: 'N_ImageNotification_Fragment' }; + type N_ImageNotification_Fragment = { id: string } & { ' $fragmentName'?: 'N_ImageNotification_Fragment' }; - export type NFragment = N_TextNotification_Fragment | N_ImageNotification_Fragment; - `); + export type NFragment = + | N_TextNotification_Fragment + | N_ImageNotification_Fragment + ; + " + `); await validate(content); }); @@ -2758,11 +2892,15 @@ export type Q2Query = { search: Array< outputFile: '', }, ); - expect(content).toBeSimilarStringTo(` + expect(content).toMatchInlineSnapshot(` + "export type CurrentUserQueryVariables = Exact<{ [key: string]: never; }>; + + export type CurrentUserQuery = { me: Maybe<( Pick & { profile: Maybe> } - )> }; + )> }; + " `); await validate(content); @@ -2795,16 +2933,20 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo( - `export type MeQueryVariables = Exact<{ + expect(content).toMatchInlineSnapshot(` + "export type MeQueryVariables = Exact<{ repoFullName: string; - }>;`, - ); - expect(content).toBeSimilarStringTo(` - export type MeQuery = { currentUser: Maybe>, entry: Maybe<( - Pick - & { postedBy: Pick } - )> }; + }>; + + + export type MeQuery = { + currentUser: Maybe>, + entry: Maybe<( + Pick + & { postedBy: Pick } + )>, + }; + " `); await validate(content); }); @@ -2836,8 +2978,14 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - export type MeQuery = { __typename?: 'Query', currentUser: { __typename?: 'User', login: string, html_url: string } | null, entry: { __typename?: 'Entry', id: number, createdAt: number, postedBy: { __typename?: 'User', login: string, html_url: string } } | null }; + expect(content).toMatchInlineSnapshot(` + "export type MeQueryVariables = Exact<{ + repoFullName: string; + }>; + + + export type MeQuery = { currentUser: { login: string, html_url: string } | null, entry: { id: number, createdAt: number, postedBy: { login: string, html_url: string } } | null }; + " `); await validate(content); }); @@ -2887,8 +3035,19 @@ export type Q2Query = { search: Array< ); const o = await validate(content); - // expect(o).toContain(`export type Information_EntryType =\n | 'NAME'\n | 'ADDRESS';`); FIXME: eddeee888 this must be generated because enum is used in a Result field - expect(o).toContain(`__typename?: 'Information_Entry', id: Information_EntryType,`); + expect(o).toMatchInlineSnapshot(` + "export type Information_EntryType = + | 'NAME' + | 'ADDRESS'; + + export type TestQueryVariables = Exact<{ [key: string]: never; }>; + + + export type TestQuery = { info: { entries: Array<{ id: Information_EntryType, value: string | null }> } | null }; + + export type InformationFragment = { entries: Array<{ id: Information_EntryType, value: string | null }> }; + " + `); }); it('Should produce valid output with preResolveTypes=true and enums with prefixes set', async () => { @@ -2944,11 +3103,21 @@ export type Q2Query = { search: Array< ); const o = await validate(content); - expect(o).toBeSimilarStringTo(` export type ITestQueryVariables = Exact<{ - e: Information_EntryType; - }>;`); - expect(o).toContain(`export type Information_EntryType =\n | 'NAME'\n | 'ADDRESS';`); - expect(o).toContain(`__typename?: 'Information_Entry', id: Information_EntryType,`); + expect(o).toMatchInlineSnapshot(` + "export type Information_EntryType = + | 'NAME' + | 'ADDRESS'; + + export type ITestQueryVariables = Exact<{ + e: Information_EntryType; + }>; + + + export type ITestQuery = { info: { entries: Array<{ id: Information_EntryType, value: string | null }> } | null, infoArgTest: { entries: Array<{ id: Information_EntryType, value: string | null }> } | null }; + + export type IInformationFragment = { entries: Array<{ id: Information_EntryType, value: string | null }> }; + " + `); }); it('Should produce valid output with preResolveTypes=true and enums with no suffixes', async () => { @@ -3004,11 +3173,21 @@ export type Q2Query = { search: Array< ); const o = await validate(content); - expect(o).toBeSimilarStringTo(` export type TestQueryVariablesI = Exact<{ - e: Information_EntryType; - }>;`); - expect(o).toContain(`export type Information_EntryType =\n | 'NAME'\n | 'ADDRESS';`); - expect(o).toContain(`__typename?: 'Information_Entry', id: Information_EntryType,`); + expect(o).toMatchInlineSnapshot(` + "export type Information_EntryType = + | 'NAME' + | 'ADDRESS'; + + export type TestQueryVariablesI = Exact<{ + e: Information_EntryType; + }>; + + + export type TestQueryI = { info: { entries: Array<{ id: Information_EntryType, value: string | null }> } | null, infoArgTest: { entries: Array<{ id: Information_EntryType, value: string | null }> } | null }; + + export type InformationFragmentI = { entries: Array<{ id: Information_EntryType, value: string | null }> }; + " + `); }); it('Should build a basic selection set based on basic query', async () => { @@ -3027,8 +3206,12 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` + expect(content).toMatchInlineSnapshot(` + "export type DummyQueryVariables = Exact<{ [key: string]: never; }>; + + export type DummyQuery = Pick; + " `); await validate(content); }); @@ -3052,11 +3235,15 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` + expect(content).toMatchInlineSnapshot(` + "export type DummyQueryVariables = Exact<{ [key: string]: never; }>; + + export type DummyQuery = ( { customName: Query['dummy'] } & { customName2: Maybe> } ); + " `); await validate(content); }); @@ -3084,11 +3271,19 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` + expect(content).toMatchInlineSnapshot(` + "export type Role = + | 'USER' + | 'ADMIN'; + + export type CurrentUserQueryVariables = Exact<{ [key: string]: never; }>; + + export type CurrentUserQuery = { me: Maybe<( - Pick - & { profile: Maybe> } - )> }; + Pick + & { profile: Maybe> } + )> }; + " `); await validate(content); }); @@ -3115,11 +3310,12 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - export type UserFieldsFragment = ( + expect(content).toMatchInlineSnapshot(` + "export type UserFieldsFragment = ( Pick & { profile: Maybe> } ); + " `); await validate(content); }); @@ -3148,11 +3344,15 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` + expect(content).toMatchInlineSnapshot(` + "export type LoginMutationVariables = Exact<{ [key: string]: never; }>; + + export type LoginMutation = { login: Maybe<( - Pick - & { profile: Maybe> } - )> }; + Pick + & { profile: Maybe> } + )> }; + " `); await validate(content); }); @@ -3173,8 +3373,12 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` + expect(content).toMatchInlineSnapshot(` + "export type TestQueryVariables = Exact<{ [key: string]: never; }>; + + export type TestQuery = Pick; + " `); await validate(content); }); @@ -3197,8 +3401,12 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` + expect(content).toMatchInlineSnapshot(` + "export type TestSubscriptionVariables = Exact<{ [key: string]: never; }>; + + export type TestSubscription = { userCreated: Maybe> }; + " `); await validate(content); }); @@ -3228,7 +3436,12 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` + expect(content).toMatchInlineSnapshot( + ` + "type InputType = { + t?: string | null | undefined; + }; + export type TestQueryQueryVariables = Exact<{ username?: string | null; email?: string | null; @@ -3238,7 +3451,13 @@ export type Q2Query = { search: Array< testArray?: Array | string | null; requireString: Array | string; innerRequired: Array | string; - }>;`); + }>; + + + export type TestQueryQuery = { dummy: string | null }; + " + `, + ); await validate(content); }); @@ -3258,10 +3477,16 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo( - `export type TestQueryQueryVariables = Exact<{ + expect(content).toMatchInlineSnapshot( + ` + "export type TestQueryQueryVariables = Exact<{ test?: any | null; - }>;`, + }>; + + + export type TestQueryQuery = { dummy: string | null }; + " + `, ); await validate(content); }); @@ -3282,9 +3507,13 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo( - `export type TestQueryQueryVariables = Exact<{ [key: string]: never; }>;`, - ); + expect(content).toMatchInlineSnapshot(` + "export type TestQueryQueryVariables = Exact<{ [key: string]: never; }>; + + + export type TestQueryQuery = { dummy: string | null }; + " + `); await validate(content); }); @@ -3326,17 +3555,17 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - export type SubmitMessageMutation = ( - { __typename?: 'Mutation' } - & { mutation: ( - { __typename?: 'DeleteMutation' } - & Pick - ) | ( - { __typename?: 'UpdateMutation' } - & Pick - ) } - ); + expect(content).toMatchInlineSnapshot(` + "export type SubmitMessageMutationVariables = Exact<{ + message: string; + }>; + + + export type SubmitMessageMutation = { mutation: + | Pick + | Pick + }; + " `); }); @@ -3368,11 +3597,12 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - export type PostQuery = ( - { __typename?: 'Query' } - & { post: { __typename: 'Post' } } - ); + expect(content).toMatchInlineSnapshot(` + "export type PostQueryVariables = Exact<{ [key: string]: never; }>; + + + export type PostQuery = { post: { __typename: 'Post' } }; + " `); }); @@ -3406,75 +3636,16 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - export type InfoQuery = ( - { __typename?: 'Query' } - & { __schema: ( - { __typename?: '__Schema' } - & { queryType: ( - { __typename?: '__Type' } - & { fields: Maybe - )>> } - ) } - ) } - );`); - }); + expect(content).toMatchInlineSnapshot(` + "export type InfoQueryVariables = Exact<{ [key: string]: never; }>; - it('should handle introspection types (__type)', async () => { - const testSchema = buildSchema(/* GraphQL */ ` - type Post { - title: String - } - type Query { - post: Post! - } - `); - const query = parse(/* GraphQL */ ` - query Info { - __type(name: "Post") { - name - fields { - name - type { - name - kind - } - } - } - } - `); - const { content } = await plugin( - testSchema, - [{ location: '', document: query }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, - ); - - expect(content).toBeSimilarStringTo(` - export type InfoQuery = ( - { __typename?: 'Query' } - & { __type: Maybe<( - { __typename?: '__Type' } - & Pick<__Type, 'name'> - & { fields: Maybe - & { type: ( - { __typename?: '__Type' } - & Pick<__Type, 'name' | 'kind'> - ) } - )>> } - )> } - ); + export type InfoQuery = { __schema: { queryType: { fields: Maybe>> } } }; + " `); }); - it('should handle introspection types (like __TypeKind)', async () => { + it('should handle introspection types (__type)', async () => { const testSchema = buildSchema(/* GraphQL */ ` type Post { title: String @@ -3498,49 +3669,28 @@ export type Q2Query = { search: Array< } `); - const coreContent = await tsPlugin( + const { content } = await plugin( testSchema, [{ location: '', document: query }], - {}, + { preResolveTypes: false }, { outputFile: 'graphql.ts', }, ); - const pluginContent = await plugin( - testSchema, - [{ location: '', document: query }], - {}, - { - outputFile: 'graphql.ts', - }, - ); + expect(content).toMatchInlineSnapshot(` + "export type InfoQueryVariables = Exact<{ [key: string]: never; }>; - const content = mergeOutputs([coreContent, pluginContent]); - expect(content).toBeSimilarStringTo(` - /** An enum describing what kind of type a given \`__Type\` is. */ - export enum __TypeKind { - /** Indicates this type is a scalar. */ - Scalar = 'SCALAR', - /** Indicates this type is an object. \`fields\` and \`interfaces\` are valid fields. */ - Object = 'OBJECT', - /** Indicates this type is an interface. \`fields\`, \`interfaces\`, and \`possibleTypes\` are valid fields. */ - Interface = 'INTERFACE', - /** Indicates this type is a union. \`possibleTypes\` is a valid field. */ - Union = 'UNION', - /** Indicates this type is an enum. \`enumValues\` is a valid field. */ - Enum = 'ENUM', - /** Indicates this type is an input object. \`inputFields\` is a valid field. */ - InputObject = 'INPUT_OBJECT', - /** Indicates this type is a list. \`ofType\` is a valid field. */ - List = 'LIST', - /** Indicates this type is a non-null. \`ofType\` is a valid field. */ - NonNull = 'NON_NULL' - } + export type InfoQuery = { __type: Maybe<( + Pick<__Type, 'name'> + & { fields: Maybe + & { type: Pick<__Type, 'name' | 'kind'> } + )>> } + )> }; + " `); - - validateTs(content); }); it('Should generate correctly when using enums and typesPrefix', async () => { @@ -3568,28 +3718,50 @@ export type Q2Query = { search: Array< } `); - const { content } = await plugin( - testSchema, - [{ location: '', document: query }], - { typesPrefix: 'PREFIX_', preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, - ); + const { content } = await plugin( + testSchema, + [{ location: '', document: query }], + { typesPrefix: 'PREFIX_', preResolveTypes: false }, + { + outputFile: 'graphql.ts', + }, + ); + + expect(content).toMatchInlineSnapshot(` + "export type PREFIX_Access = + | 'Read' + | 'Write' + | 'All'; + + type PREFIX_Filter = { + match: string; + }; + + export type PREFIX_UsersQueryVariables = Exact<{ + filter: PREFIX_Filter; + }>; + + + export type PREFIX_UsersQuery = { users: Maybe>>> }; + " + `); + expect(content).toMatchInlineSnapshot(` + "export type PREFIX_Access = + | 'Read' + | 'Write' + | 'All'; + + type PREFIX_Filter = { + match: string; + }; - expect(content).toBeSimilarStringTo(` export type PREFIX_UsersQueryVariables = Exact<{ filter: PREFIX_Filter; }>; - `); - expect(content).toBeSimilarStringTo(` - export type PREFIX_UsersQuery = ( - { __typename?: 'Query' } - & { users: Maybe - )>>> } - ); + + + export type PREFIX_UsersQuery = { users: Maybe>>> }; + " `); }); @@ -3619,10 +3791,14 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - export type UsersQueryVariables = Exact<{ + expect(content).toMatchInlineSnapshot(` + "export type UsersQueryVariables = Exact<{ reverse?: boolean | null; }>; + + + export type UsersQuery = { users: Array<{ name: string }> }; + " `); }); }); @@ -3683,23 +3859,29 @@ export type Q2Query = { search: Array< outputFile: 'graphql.ts', }, ); - expect(content).toBeSimilarStringTo(` - export type FieldQuery = ( - { __typename?: 'Query' } - & { field: ( - { __typename: 'Error1' } - & Pick - ) | ( - { __typename: 'Error2' } - & Pick - ) | ( - { __typename: 'ComplexError' } - & Pick - ) | ( - { __typename: 'FieldResultSuccess' } - & Pick - ) } - ); + expect(content).toMatchInlineSnapshot(` + "export type FieldQueryVariables = Exact<{ [key: string]: never; }>; + + + export type FieldQuery = { field: + | ( + { __typename: 'Error1' } + & Pick + ) + | ( + { __typename: 'Error2' } + & Pick + ) + | ( + { __typename: 'ComplexError' } + & Pick + ) + | ( + { __typename: 'FieldResultSuccess' } + & Pick + ) + }; + " `); }); @@ -3758,23 +3940,26 @@ export type Q2Query = { search: Array< outputFile: 'graphql.ts', }, ); - expect(content).toBeSimilarStringTo(` - export type FieldQuery = ( - { __typename?: 'Query' } - & { field: ( - { __typename: 'Error1' } - & Pick - ) | ( - { __typename: 'Error2' } - & Pick - ) | ( - { __typename: 'ComplexError' } - & Pick - ) | ( - { __typename?: 'FieldResultSuccess' } - & Pick - ) } - ); + expect(content).toMatchInlineSnapshot(` + "export type FieldQueryVariables = Exact<{ [key: string]: never; }>; + + + export type FieldQuery = { field: + | ( + { __typename: 'Error1' } + & Pick + ) + | ( + { __typename: 'Error2' } + & Pick + ) + | ( + { __typename: 'ComplexError' } + & Pick + ) + | Pick + }; + " `); }); it('interface with same field names', async () => { @@ -3821,17 +4006,15 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - export type SomethingQuery = ( - { __typename?: 'Query' } - & { node: Maybe<( - { __typename?: 'A' } - & Pick - ) | ( - { __typename?: 'B' } - & Pick - )> } - ); + expect(content).toMatchInlineSnapshot(` + "export type SomethingQueryVariables = Exact<{ [key: string]: never; }>; + + + export type SomethingQuery = { node: Maybe< + | Pick + | Pick + > }; + " `); }); it('union returning single interface types', async () => { @@ -3891,24 +4074,19 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - export type UserQuery = ( - { __typename?: 'Query' } - & { user: Maybe<( - { __typename?: 'User' } - & Pick - ) | ( - { __typename?: 'Error2' } - & Pick - ) | ( - { __typename?: 'Error3' } - & Pick - & { info: Maybe<( - { __typename?: 'AdditionalInfo' } - & Pick - )> } - )> } - ); + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ [key: string]: never; }>; + + + export type UserQuery = { user: Maybe< + | Pick + | Pick + | ( + Pick + & { info: Maybe> } + ) + > }; + " `); }); @@ -3984,24 +4162,19 @@ export type Q2Query = { search: Array< }, ); - expect(content).toBeSimilarStringTo(` - export type UserQuery = ( - { __typename?: 'Query' } - & { user: Maybe<( - { __typename?: 'User' } - & Pick - ) | ( - { __typename?: 'Error2' } - & Pick - ) | ( - { __typename?: 'Error3' } - & Pick - & { info: Maybe<( - { __typename?: 'AdditionalInfo' } - & Pick - )> } - )> } - ); + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ [key: string]: never; }>; + + + export type UserQuery = { user: Maybe< + | Pick + | Pick + | ( + Pick + & { info: Maybe> } + ) + > }; + " `); }); @@ -4042,14 +4215,12 @@ export type Q2Query = { search: Array< const o = await validate(content); - expect(o).toBeSimilarStringTo(` - export type UserQueryQuery = ( - { __typename?: 'Query' } - & { user: ( - { __typename?: 'User' } - & Pick - ) } - ); + expect(o).toMatchInlineSnapshot(` + "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; + + + export type UserQueryQuery = { user: Pick }; + " `); }); @@ -4092,19 +4263,25 @@ export type Q2Query = { search: Array< const o = await validate(content); - expect(o).toBeSimilarStringTo(` - export type UserQueryQuery = ( - { __typename?: 'Query' } - & { user: ( - { __typename?: 'User' } - & Pick - ) } - );`); + expect(o).toMatchInlineSnapshot(` + "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; - expect(o).toBeSimilarStringTo(`export type TestFragment = ( - { __typename?: 'User' } - & Pick - );`); + + export type UserQueryQuery = { user: Pick }; + + export type TestFragment = Pick; + " + `); + + expect(o).toMatchInlineSnapshot(` + "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; + + + export type UserQueryQuery = { user: Pick }; + + export type TestFragment = Pick; + " + `); }); it('Should handle union selection sets with both FragmentSpreads and InlineFragments', async () => { @@ -4212,61 +4389,109 @@ export type Q2Query = { search: Array< ); expect(mergeOutputs([content])).toMatchSnapshot(); - expect(output).toBeSimilarStringTo(` - export type UserQueryQuery = ( - { __typename?: 'Query' } - & { user: ( - { __typename?: 'User' } - & Pick - ) | ( - { __typename?: 'Error2' } - & Pick - ) | ( - { __typename?: 'Error3' } - & Pick - & { info: Maybe<( - { __typename?: 'AdditionalInfo' } - & Pick - )> } - ) } - );`); + expect(output).toMatchInlineSnapshot(` + "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; - expect(output).toBeSimilarStringTo(` - export type AdditionalInfoFragment = ( - { __typename?: 'AdditionalInfo' } - & Pick - ); - type UserResult1_User_Fragment = ( - { __typename?: 'User' } - & Pick - ); + export type UserQueryQuery = { user: + | Pick + | Pick + | ( + Pick + & { info: Maybe> } + ) + }; - type UserResult1_Error2_Fragment = { __typename?: 'Error2' }; + export type AdditionalInfoFragment = Pick; - type UserResult1_Error3_Fragment = ( - { __typename?: 'Error3' } - & { info: Maybe<( - { __typename?: 'AdditionalInfo' } - & Pick - )> } - ); + type UserResult1_User_Fragment = Pick; - export type UserResult1Fragment = UserResult1_User_Fragment | UserResult1_Error2_Fragment | UserResult1_Error3_Fragment; + type UserResult1_Error3_Fragment = { info: Maybe> }; - type UserResult_User_Fragment = ( - { __typename?: 'User' } - & Pick - ); + export type UserResult1Fragment = + | UserResult1_User_Fragment + | UserResult1_Error3_Fragment + ; - type UserResult_Error2_Fragment = ( - { __typename?: 'Error2' } - & Pick - ); + type UserResult_User_Fragment = Pick; + + type UserResult_Error2_Fragment = Pick; + + export type UserResultFragment = + | UserResult_User_Fragment + | UserResult_Error2_Fragment + ; + + function t(q: UserQueryQuery) { + if (q.user) { + if (q.user.__typename === 'User') { + if (q.user.id) { + const u = q.user.login; + } + } + if (q.user.__typename === 'Error2') { + console.log(q.user.message); + } + if (q.user.__typename === 'Error3') { + if (q.user.info) { + console.log(q.user.info.__typename) + } + } + } + }" + `); + + expect(output).toMatchInlineSnapshot(` + "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; + + + export type UserQueryQuery = { user: + | Pick + | Pick + | ( + Pick + & { info: Maybe> } + ) + }; - type UserResult_Error3_Fragment = { __typename?: 'Error3' }; + export type AdditionalInfoFragment = Pick; - export type UserResultFragment = UserResult_User_Fragment | UserResult_Error2_Fragment | UserResult_Error3_Fragment;`); + type UserResult1_User_Fragment = Pick; + + type UserResult1_Error3_Fragment = { info: Maybe> }; + + export type UserResult1Fragment = + | UserResult1_User_Fragment + | UserResult1_Error3_Fragment + ; + + type UserResult_User_Fragment = Pick; + + type UserResult_Error2_Fragment = Pick; + + export type UserResultFragment = + | UserResult_User_Fragment + | UserResult_Error2_Fragment + ; + + function t(q: UserQueryQuery) { + if (q.user) { + if (q.user.__typename === 'User') { + if (q.user.id) { + const u = q.user.login; + } + } + if (q.user.__typename === 'Error2') { + console.log(q.user.message); + } + if (q.user.__typename === 'Error3') { + if (q.user.info) { + console.log(q.user.info.__typename) + } + } + } + }" + `); }); it('Should handle union selection sets with both FragmentSpreads and InlineFragments with flattenGeneratedTypes', async () => { @@ -4374,24 +4599,36 @@ export type Q2Query = { search: Array< ); expect(mergeOutputs([output])).toMatchSnapshot(); - expect(output).toBeSimilarStringTo(` - export type UserQueryQuery = ( - { __typename?: 'Query' } - & { user: ( - { __typename?: 'User' } - & Pick - ) | ( - { __typename?: 'Error2' } - & Pick - ) | ( - { __typename?: 'Error3' } - & Pick - & { info: Maybe<( - { __typename?: 'AdditionalInfo' } - & Pick - )> } - ) } - ); + expect(output).toMatchInlineSnapshot(` + "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; + + + export type UserQueryQuery = { user: + | Pick + | Pick + | ( + Pick + & { info: Maybe> } + ) + }; + + function t(q: UserQueryQuery) { + if (q.user) { + if (q.user.__typename === 'User') { + if (q.user.id) { + const u = q.user.login; + } + } + if (q.user.__typename === 'Error2') { + console.log(q.user.message); + } + if (q.user.__typename === 'Error3') { + if (q.user.info) { + console.log(q.user.info.__typename) + } + } + } + }" `); }); @@ -4457,23 +4694,19 @@ export type Q2Query = { search: Array< const output = await validate(content); expect(mergeOutputs([output])).toMatchSnapshot(); - expect(output).toBeSimilarStringTo(` - export type SearchPopularQueryVariables = Exact<{ [key: string]: never; }>; + expect(output).toMatchInlineSnapshot(` + "export type SearchPopularQueryVariables = Exact<{ [key: string]: never; }>; - export type SearchPopularQuery = ( - { __typename?: 'Query' } - & { search: Maybe - ) | ( - { __typename?: 'DimValue' } - & Pick - & { dimension: Maybe<( - { __typename?: 'Dimension' } - & Pick - )> } - )>> } - );`); + + export type SearchPopularQuery = { search: Maybe + | ( + Pick + & { dimension: Maybe> } + ) + >> }; + " + `); }); it('Handles fragments across files with flattenGeneratedTypes', async () => { @@ -4530,12 +4763,15 @@ export type Q2Query = { search: Array< const output = await validate(content); - expect(output).toBeSimilarStringTo(` - export type SearchableFragmentFragment = { __typename?: 'Dimension', id: string | null }; + expect(output).toMatchInlineSnapshot(` + "export type SearchableFragmentFragment = { id: string | null }; export type SearchPopularQueryVariables = Exact<{ [key: string]: never; }>; - export type SearchPopularQuery = { __typename?: 'Query', search: Array<{ __typename?: 'Dimension', id: string | null }> | null };`); + + export type SearchPopularQuery = { search: Array<{ id: string | null }> | null }; + " + `); }); it('Drops fragments with flattenGeneratedTypes', async () => { @@ -4593,10 +4829,13 @@ export type Q2Query = { search: Array< const output = await validate(content); - expect(output).toBeSimilarStringTo(` - export type SearchPopularQueryVariables = Exact<{ [key: string]: never; }>; + expect(output).toMatchInlineSnapshot(` + "export type SearchPopularQueryVariables = Exact<{ [key: string]: never; }>; + - export type SearchPopularQuery = { __typename?: 'Query', search: Array<{ __typename?: 'Dimension', id: string | null }> | null };`); + export type SearchPopularQuery = { search: Array<{ id: string | null }> | null }; + " + `); }); it('Should add operation name when addOperationExport is true', async () => { @@ -4633,29 +4872,19 @@ export type Q2Query = { search: Array< outputFile: 'graphql.ts', }); - expect(content).toBeSimilarStringTo(` - export type UserIdQueryQueryVariables = Exact<{ [key: string]: never; }>; + expect(content).toMatchInlineSnapshot(` + "export type UserIdQueryQueryVariables = Exact<{ [key: string]: never; }>; - export type UserIdQueryQuery = ( - { __typename?: 'Query' } - & { user: ( - { __typename?: 'User' } - & Pick - ) } - ); - export type UserLoginQueryQueryVariables = Exact<{ [key: string]: never; }>; + export type UserIdQueryQuery = { user: Pick }; - export type UserLoginQueryQuery = ( - { __typename?: 'Query' } - & { user: ( - { __typename?: 'User' } - & Pick - ) } - ); + export type UserLoginQueryQueryVariables = Exact<{ [key: string]: never; }>; + + + export type UserLoginQueryQuery = { user: Pick }; - export declare const UserIdQuery: import("graphql").DocumentNode; - export declare const UserLoginQuery: import("graphql").DocumentNode; + export declare const UserIdQuery: import("graphql").DocumentNode; + export declare const UserLoginQuery: import("graphql").DocumentNode;" `); }); @@ -4771,24 +5000,42 @@ export type Q2Query = { search: Array< ); expect(mergeOutputs([output])).toMatchSnapshot(); - expect(output).toBeSimilarStringTo(` - export type UserQueryQuery = ( - { __typename?: 'Query' } - & { user: ( - { __typename?: 'User' } - & Pick - ) | ( - { __typename?: 'Error2' } - & Pick - ) | ( - { __typename?: 'Error3' } - & Pick - & { info: Maybe<( - { __typename?: 'AdditionalInfo' } - & Pick - )> } - ) } - ); + expect(output).toMatchInlineSnapshot(` + "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; + + + export type UserQueryQuery = { user: + | Pick< + User, + | 'id' + | 'test2' + | 'login' + | 'test' + > + | Pick + | ( + Pick + & { info: Maybe> } + ) + }; + + function t(q: UserQueryQuery) { + if (q.user) { + if (q.user.__typename === 'User') { + if (q.user.id) { + const u = q.user.login; + } + } + if (q.user.__typename === 'Error2') { + console.log(q.user.message); + } + if (q.user.__typename === 'Error3') { + if (q.user.info) { + console.log(q.user.info.__typename) + } + } + } + }" `); }); }); @@ -4928,7 +5175,13 @@ export type Q2Query = { search: Array< outputFile: 'graphql.ts', }, ); - expect(content).toContain(`{ foo: Maybe<{ __typename?: 'C' }> }`); + expect(content).toMatchInlineSnapshot(` + "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + + + export type Unnamed_1_Query = { foo: Maybe> }; + " + `); }); it('#5001 - incorrect output with typeSuffix', async () => { @@ -5283,29 +5536,24 @@ function test(q: GetEntityBrandDataQuery): void { }, ); - expect(content).toBeSimilarStringTo(` - export type TestQueryQuery = ( - { __typename?: 'Query' } - & { fooBar: Array<( - { __typename?: 'Foo' } - & Pick - ) | ( - { __typename?: 'Bar' } - & Pick - )> } - ); + expect(content).toMatchInlineSnapshot(` + "export type TestQueryQueryVariables = Exact<{ [key: string]: never; }>; - type FooBarFragment_Foo_Fragment = ( - { __typename?: 'Foo' } - & Pick - ); - type FooBarFragment_Bar_Fragment = ( - { __typename?: 'Bar' } - & Pick - ); + export type TestQueryQuery = { fooBar: Array< + | Pick + | Pick + > }; - export type FooBarFragmentFragment = FooBarFragment_Foo_Fragment | FooBarFragment_Bar_Fragment; + type FooBarFragment_Foo_Fragment = Pick; + + type FooBarFragment_Bar_Fragment = Pick; + + export type FooBarFragmentFragment = + | FooBarFragment_Foo_Fragment + | FooBarFragment_Bar_Fragment + ; + " `); }); @@ -5358,20 +5606,14 @@ function test(q: GetEntityBrandDataQuery): void { }, ); - expect(content).toBeSimilarStringTo(` - export type ProductFragmentFragment = ( - { __typename?: 'Product' } - & Pick - ); + expect(content).toMatchInlineSnapshot(` + "export type ProductFragmentFragment = Pick; export type PriceFragmentFragment = ( - { __typename?: 'Price' } - & Pick - & { item: Array - )>> } + Pick + & { item: Array>> } ); + " `); }); @@ -5405,14 +5647,15 @@ function test(q: GetEntityBrandDataQuery): void { }, ); - expect(content).toBeSimilarStringTo(` - export type UserQuery = ( - { __typename?: 'Query' } - & { user?: Maybe<( - { __typename?: 'User' } - & Pick - )> } - );`); + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + withUser?: boolean; + }>; + + + export type UserQuery = { user?: Maybe> }; + " + `); }); it('#2436 - interface with field of same name but different type is correctly handled', async () => { @@ -5472,25 +5715,18 @@ function test(q: GetEntityBrandDataQuery): void { }, ); - expect(content).toBeSimilarStringTo(` - export type DashboardVersionFragmentFragment = ( - { __typename?: 'DashboardVersion' } - & { tiles: ( - { __typename?: 'DashboardTileFilterDetails' } - & Pick - & { md: ( - { __typename?: 'TileFilterMetadata' } - & Pick - ) } - ) | ( - { __typename?: 'DashboardTileParameterDetails' } - & Pick - & { md: ( - { __typename?: 'TileParameterMetadata' } - & Pick - ) } - ) } - ); + expect(content).toMatchInlineSnapshot(` + "export type DashboardVersionFragmentFragment = { tiles: + | ( + Pick + & { md: Pick } + ) + | ( + Pick + & { md: Pick } + ) + }; + " `); }); @@ -5550,25 +5786,18 @@ function test(q: GetEntityBrandDataQuery): void { }, ); - expect(content).toBeSimilarStringTo(` - export type DashboardVersionFragmentFragment = ( - { __typename?: 'DashboardVersion' } - & { tiles: ( - { __typename?: 'DashboardTileFilterDetails' } - & Pick - & { md: ( - { __typename?: 'TileFilterMetadata' } - & Pick - ) } - ) | ( - { __typename?: 'DashboardTileParameterDetails' } - & Pick - & { md: ( - { __typename?: 'TileParameterMetadata' } - & Pick - ) } - ) } - ); + expect(content).toMatchInlineSnapshot(` + "export type DashboardVersionFragmentFragment = { tiles: + | ( + Pick + & { md: Pick } + ) + | ( + Pick + & { md: Pick } + ) + }; + " `); }); @@ -5624,19 +5853,13 @@ function test(q: GetEntityBrandDataQuery): void { ); expect(content).toMatchInlineSnapshot(` - "type CatFragment_Duck_Fragment = Record; - - type CatFragment_Lion_Fragment = { id: string }; + "type CatFragment_Lion_Fragment = { id: string }; type CatFragment_Puma_Fragment = { id: string }; - type CatFragment_Wolf_Fragment = Record; - export type CatFragmentFragment = - | CatFragment_Duck_Fragment | CatFragment_Lion_Fragment | CatFragment_Puma_Fragment - | CatFragment_Wolf_Fragment ; export type KittyQueryVariables = Exact<{ [key: string]: never; }>; @@ -5703,29 +5926,22 @@ function test(q: GetEntityBrandDataQuery): void { ); expect(content).toMatchInlineSnapshot(` - "type CatFragment_Duck_Fragment = { __typename?: 'Duck' }; - - type CatFragment_Lion_Fragment = { __typename?: 'Lion', id: string }; + "type CatFragment_Lion_Fragment = { id: string }; - type CatFragment_Puma_Fragment = { __typename?: 'Puma', id: string }; - - type CatFragment_Wolf_Fragment = { __typename?: 'Wolf' }; + type CatFragment_Puma_Fragment = { id: string }; export type CatFragmentFragment = - | CatFragment_Duck_Fragment | CatFragment_Lion_Fragment | CatFragment_Puma_Fragment - | CatFragment_Wolf_Fragment ; export type KittyQueryVariables = Exact<{ [key: string]: never; }>; - export type KittyQuery = { __typename?: 'Query', animals: Array< - | { __typename?: 'Duck' } - | { __typename?: 'Lion', id: string } - | { __typename?: 'Puma', id: string } - | { __typename?: 'Wolf' } + export type KittyQuery = { animals: Array< + | { id: string } + | { id: string } + | Record > }; " `); @@ -5772,8 +5988,15 @@ function test(q: GetEntityBrandDataQuery): void { }, ); - expect(content).toBeSimilarStringTo(` - export type UserQuery = { user: Pick | Record }; + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ [key: string]: never; }>; + + + export type UserQuery = { user: + | Pick + | Record + }; + " `); }); @@ -5804,12 +6027,17 @@ function test(q: GetEntityBrandDataQuery): void { outputFile: 'graphql.ts', }); - expect(content).toBeSimilarStringTo(` - export type UserQueryVariables = Exact<{ - testArray?: Array | string | null; - requireString: Array | string; - innerRequired: Array | string; - }>;`); + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + testArray?: Array | string | null; + requireString: Array | string; + innerRequired: Array | string; + }>; + + + export type UserQuery = { search: Array<{ id: string }> | null }; + " + `); await validate(content); }); @@ -5840,12 +6068,17 @@ function test(q: GetEntityBrandDataQuery): void { outputFile: 'graphql.ts', }); - expect(content).toBeSimilarStringTo(` - export type UserQueryVariables = Exact<{ - testArray?: Array | null; - requireString: Array; - innerRequired: Array; - }>;`); + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + testArray?: Array | null; + requireString: Array; + innerRequired: Array; + }>; + + + export type UserQuery = { search: Array<{ id: string }> | null }; + " + `); await validate(content); }); @@ -5895,17 +6128,15 @@ function test(q: GetEntityBrandDataQuery): void { }, ); - expect(content).toBeSimilarStringTo(` - export type EntityQuery = ( - { __typename?: 'Query' } - & { entity: ( - { __typename?: 'Session' } - & Pick - ) | ( - { __typename?: 'User' } - & Pick - ) } - ); + expect(content).toMatchInlineSnapshot(` + "export type EntityQueryVariables = Exact<{ [key: string]: never; }>; + + + export type EntityQuery = { entity: + | Pick + | Pick + }; + " `); }); @@ -5949,19 +6180,12 @@ function test(q: GetEntityBrandDataQuery): void { }, ); - expect(content).toBeSimilarStringTo(` - export type InlineFragmentQueryQueryVariables = Exact<{ [key: string]: never; }>; - - export type InlineFragmentQueryQuery = ( - { __typename?: 'Query' } - & { user: ( - { __typename?: 'User' } - & { friends: Array<( - { __typename?: 'User' } - & Pick - )> } - ) } - ); + expect(content).toMatchInlineSnapshot(` + "export type InlineFragmentQueryQueryVariables = Exact<{ [key: string]: never; }>; + + + export type InlineFragmentQueryQuery = { user: { friends: Array> } }; + " `); }); it('SpreadFragmentQuery', async () => { @@ -5997,42 +6221,16 @@ function test(q: GetEntityBrandDataQuery): void { }, ); - expect(content).toBeSimilarStringTo(` - export type UserFriendsIdFragmentFragment = ( - { __typename?: 'Query' } - & { user: ( - { __typename?: 'User' } - & { friends: Array<( - { __typename?: 'User' } - & Pick - )> } - ) } - ); - - export type UserFriendsNameFragmentFragment = ( - { __typename?: 'Query' } - & { user: ( - { __typename?: 'User' } - & { friends: Array<( - { __typename?: 'User' } - & Pick - )> } - ) } - ); + expect(content).toMatchInlineSnapshot(` + "export type UserFriendsIdFragmentFragment = { user: { friends: Array> } }; + + export type UserFriendsNameFragmentFragment = { user: { friends: Array> } }; export type SpreadFragmentQueryQueryVariables = Exact<{ [key: string]: never; }>; - export type SpreadFragmentQueryQuery = ( - { __typename?: 'Query' } - & { user: ( - { __typename?: 'User' } - & { friends: Array<( - { __typename?: 'User' } - & Pick - )> } - ) } - ); + export type SpreadFragmentQueryQuery = { user: { friends: Array> } }; + " `); }); it('SpreadFragmentWithSelectionQuery', async () => { @@ -6065,31 +6263,17 @@ function test(q: GetEntityBrandDataQuery): void { }, ); - expect(content).toBeSimilarStringTo(` - export type UserFriendsNameFragmentFragment = ( - { __typename?: 'Query' } - & { user: ( - { __typename?: 'User' } - & { friends: Array<( - { __typename?: 'User' } - & Pick - )> } - ) } - ); + expect(content).toMatchInlineSnapshot(` + "export type UserFriendsNameFragmentFragment = { user: { friends: Array> } }; export type SpreadFragmentWithSelectionQueryQueryVariables = Exact<{ [key: string]: never; }>; - export type SpreadFragmentWithSelectionQueryQuery = ( - { __typename?: 'Query' } - & { user: ( - { __typename?: 'User' } - & Pick - & { friends: Array<( - { __typename?: 'User' } - & Pick - )> } - ) } - ); + + export type SpreadFragmentWithSelectionQueryQuery = { user: ( + Pick + & { friends: Array> } + ) }; + " `); }); it('SpreadFragmentWithSelectionQuery - flatten', async () => { @@ -6122,31 +6306,17 @@ function test(q: GetEntityBrandDataQuery): void { }, ); - expect(content).toBeSimilarStringTo(` - export type UserFriendsNameFragmentFragment = ( - { __typename?: 'Query' } - & { user: ( - { __typename?: 'User' } - & { friends: Array<( - { __typename?: 'User' } - & Pick - )> } - ) } - ); + expect(content).toMatchInlineSnapshot(` + "export type UserFriendsNameFragmentFragment = { user: { friends: Array> } }; export type SpreadFragmentWithSelectionQueryQueryVariables = Exact<{ [key: string]: never; }>; - export type SpreadFragmentWithSelectionQueryQuery = ( - { __typename?: 'Query' } - & { user: ( - { __typename?: 'User' } - & Pick - & { friends: Array<( - { __typename?: 'User' } - & Pick - )> } - ) } - ); + + export type SpreadFragmentWithSelectionQueryQuery = { user: ( + Pick + & { friends: Array> } + ) }; + " `); }); }); @@ -6211,26 +6381,17 @@ function test(q: GetEntityBrandDataQuery): void { "export type GetPeopleQueryVariables = Exact<{ [key: string]: never; }>; - export type GetPeopleQuery = { __typename?: 'Query', people: - | ( - { __typename?: 'Character' } - & { ' $fragmentRefs'?: { 'PeopleInfo_Character_Fragment': PeopleInfo_Character_Fragment } } - ) - | ( - { __typename?: 'Jedi' } - & { ' $fragmentRefs'?: { 'PeopleInfo_Jedi_Fragment': PeopleInfo_Jedi_Fragment } } - ) - | ( - { __typename?: 'Droid' } - & { ' $fragmentRefs'?: { 'PeopleInfo_Droid_Fragment': PeopleInfo_Droid_Fragment } } - ) + export type GetPeopleQuery = { people: + | { ' $fragmentRefs'?: { 'PeopleInfo_Character_Fragment': PeopleInfo_Character_Fragment } } + | { ' $fragmentRefs'?: { 'PeopleInfo_Jedi_Fragment': PeopleInfo_Jedi_Fragment } } + | { ' $fragmentRefs'?: { 'PeopleInfo_Droid_Fragment': PeopleInfo_Droid_Fragment } } }; - type PeopleInfo_Character_Fragment = { __typename?: 'Character', name: string | null } & { ' $fragmentName'?: 'PeopleInfo_Character_Fragment' }; + type PeopleInfo_Character_Fragment = { name: string | null } & { ' $fragmentName'?: 'PeopleInfo_Character_Fragment' }; - type PeopleInfo_Jedi_Fragment = { __typename?: 'Jedi', side: string | null } & { ' $fragmentName'?: 'PeopleInfo_Jedi_Fragment' }; + type PeopleInfo_Jedi_Fragment = { side: string | null } & { ' $fragmentName'?: 'PeopleInfo_Jedi_Fragment' }; - type PeopleInfo_Droid_Fragment = { __typename?: 'Droid', model: string | null } & { ' $fragmentName'?: 'PeopleInfo_Droid_Fragment' }; + type PeopleInfo_Droid_Fragment = { model: string | null } & { ' $fragmentName'?: 'PeopleInfo_Droid_Fragment' }; export type PeopleInfoFragment = | PeopleInfo_Character_Fragment @@ -6388,24 +6549,15 @@ function test(q: GetEntityBrandDataQuery): void { outputFile: 'graphql.ts', }); - expect(content).toBeSimilarStringTo(` - export type UserQueryQueryVariables = Exact<{ + expect(content).toMatchInlineSnapshot(` + "export type UserQueryQueryVariables = Exact<{ skipFirstName: boolean; skipAddress: boolean; }>; - export type UserQueryQuery = { - __typename?: 'Query', - viewer: { - __typename?: 'User', - lastName: number, - givenName?: string, - mailingAddress?: { - __typename?: 'Address', - postalCode: string - } - } - }; + + export type UserQueryQuery = { viewer: { lastName: number, givenName?: string, mailingAddress?: { postalCode: string } } }; + " `); }); }); @@ -6447,12 +6599,15 @@ function test(q: GetEntityBrandDataQuery): void { }, ); - expect(content).toBeSimilarStringTo(` - export type UserQueryVariables = Exact<{ - showAddress: boolean; - }>; + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + showAddress: boolean; + }>; - export type UserQuery = { __typename?: 'Query', user: { __typename?: 'User', name: string, address?: string, nicknames?: Array | null, parents?: Array } };`); + + export type UserQuery = { user: { name: string, address?: string, nicknames?: Array | null, parents?: Array } }; + " + `); }); it('objects with @skip, @include should pre resolve into optional', async () => { @@ -6500,12 +6655,16 @@ function test(q: GetEntityBrandDataQuery): void { }, ); - expect(content).toBeSimilarStringTo(` - export type UserQueryVariables = Exact<{ - showAddress: boolean; - showName: boolean; - }>; - export type UserQuery = { __typename?: 'Query', user: { __typename?: 'User', id: string, name?: string, address?: { __typename?: 'Address', city: string }, friends?: Array<{ __typename?: 'User', id: string }> } };`); + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + showAddress: boolean; + showName: boolean; + }>; + + + export type UserQuery = { user: { id: string, name?: string, address?: { city: string }, friends?: Array<{ id: string }> } }; + " + `); }); it('fields with @skip, @include should make container resolve into MakeOptional type', async () => { @@ -6548,26 +6707,22 @@ function test(q: GetEntityBrandDataQuery): void { }, ); - expect(content).toBeSimilarStringTo(` - export type UserQueryVariables = Exact<{ - showAddress: boolean; - showName: boolean; - }>; - - export type UserQuery = ( - { __typename?: 'Query' } - & { user: ( - { __typename?: 'User' } - & MakeOptional, 'name'> - & { address?: ( - { __typename?: 'Address' } - & Pick - ), friends?: Array<( - { __typename?: 'User' } - & Pick - )> } - ) } - );`); + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + showAddress: boolean; + showName: boolean; + }>; + + + export type UserQuery = { user: ( + MakeOptional, 'name'> + & { + address?: Pick, + friends?: Array>, + } + ) }; + " + `); }); it('On avoidOptionals:true, fields with @skip, @include should make container resolve into MakeMaybe type', async () => { @@ -6644,8 +6799,14 @@ function test(q: GetEntityBrandDataQuery): void { outputFile: 'graphql.ts', }); - expect(content).toBeSimilarStringTo( - `export type UserQuery = { __typename?: 'Query', user: { __typename?: 'User', id: string, username: string, email: string | null } }`, + expect(content).toMatchInlineSnapshot( + ` + "export type UserQueryVariables = Exact<{ [key: string]: never; }>; + + + export type UserQuery = { user: { id: string, username: string, email: string | null } }; + " + `, ); }); @@ -6686,7 +6847,12 @@ function test(q: GetEntityBrandDataQuery): void { }, ); - expect(content).toBeSimilarStringTo(` + expect(content).toMatchInlineSnapshot(` + "export type MyQueryQueryVariables = Exact<{ + include: boolean; + }>; + + export type MyQueryQuery = ( { __typename: 'Query' } & { me: ( @@ -6697,6 +6863,7 @@ function test(q: GetEntityBrandDataQuery): void { )> } ) } ); + " `); }); @@ -6738,18 +6905,15 @@ function test(q: GetEntityBrandDataQuery): void { }, ); - expect(content).toBeSimilarStringTo(` - export type UserQuery = { - __typename?: 'Query', - user?: { - __typename?: 'User', - name: string | null - } | null, - group?: { - __typename?: 'Group', - id: number - } - };`); + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + withUser?: boolean; + }>; + + + export type UserQuery = { user?: { name: string | null } | null, group?: { id: number } }; + " + `); }); it('resolve optionals according to maybeValue and conditional directives', async () => { @@ -6790,8 +6954,14 @@ function test(q: GetEntityBrandDataQuery): void { outputFile: 'graphql.ts', }, ); - expect(content).toBeSimilarStringTo(` - export type UserQuery = { __typename?: 'Query', user: { __typename?: 'User', name: string, age: number | 'specialType', address?: string, nicknames?: Array | 'specialType', parents?: Array } }; + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + showProperty: boolean; + }>; + + + export type UserQuery = { user: { name: string, age: number | 'specialType', address?: string, nicknames?: Array | 'specialType', parents?: Array } }; + " `); }); @@ -6833,23 +7003,24 @@ function test(q: GetEntityBrandDataQuery): void { }, ); - expect(content).toBeSimilarStringTo(` - export type UserQuery = ( - { __typename?: 'Query' } - & { user?: Maybe<( - { __typename?: 'User' } - & Pick - )>, group?: ( - { __typename?: 'Group' } - & Pick - ) } - );`); + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + withUser?: boolean; + }>; + + + export type UserQuery = { + user?: Maybe>, + group?: Pick, + }; + " + `); }); }); describe('incremental delivery directive handling', () => { it('should generate an union of initial and deferred fields for fragments (preResolveTypes: true)', async () => { - const schema = buildSchema(` + const schema = buildSchema(/* GraphQL */ ` type Address { street1: String! } @@ -6880,7 +7051,7 @@ function test(q: GetEntityBrandDataQuery): void { } `); - const fragment = parse(` + const fragment = parse(/* GraphQL */ ` fragment WidgetFragment on User { widgetCount widgetPreference @@ -6937,35 +7108,23 @@ function test(q: GetEntityBrandDataQuery): void { { outputFile: 'graphql.ts' }, ); - expect(content).toBeSimilarStringTo(` + expect(content).toMatchInlineSnapshot(` + "export type WidgetFragmentFragment = { widgetCount: number, widgetPreference: string }; + + export type FoodFragmentFragment = { favoriteFood: string, leastFavoriteFood: string }; + + export type EmploymentFragmentFragment = { employment: { title: string } }; + export type UserQueryVariables = Exact<{ [key: string]: never; }>; - export type UserQuery = { - __typename?: 'Query', - user: { - __typename?: 'User', - clearanceLevel: string, - name: string, - phone: { - __typename?: 'Phone', - home: string - }, - employment: { - __typename?: 'Employment', - title: string - } - } & ({ __typename?: 'User', email: string } - | { __typename?: 'User', email?: never }) - & ({ __typename?: 'User', address: { __typename?: 'Address', street1: string } } - | { __typename?: 'User', address?: never }) - & ({ __typename?: 'User', widgetCount: number, widgetPreference: string } - | { __typename?: 'User', widgetCount?: never, widgetPreference?: never }) - & ({ __typename?: 'User', favoriteFood: string, leastFavoriteFood: string } - | { __typename?: 'User', favoriteFood?: never, leastFavoriteFood?: never }) }; + + + export type UserQuery = { user: { clearanceLevel: string, name: string, phone: { home: string }, employment: { title: string } } & ({ email: string } | { email?: never }) & ({ address: { street1: string } } | { address?: never }) & ({ widgetCount: number, widgetPreference: string } | { widgetCount?: never, widgetPreference?: never }) & ({ favoriteFood: string, leastFavoriteFood: string } | { favoriteFood?: never, leastFavoriteFood?: never }) }; + " `); }); it('should generate an union of initial and deferred fields for fragments using MakeEmpty (preResolveTypes: false)', async () => { - const schema = buildSchema(` + const schema = buildSchema(/* GraphQL */ ` type Address { street1: String! } @@ -6993,7 +7152,7 @@ function test(q: GetEntityBrandDataQuery): void { } `); - const fragment = parse(` + const fragment = parse(/* GraphQL */ ` fragment WidgetFragment on User { widgetCount } @@ -7041,65 +7200,27 @@ function test(q: GetEntityBrandDataQuery): void { { outputFile: 'graphql.ts' }, ); - expect(content).toBeSimilarStringTo(` - export type WidgetFragmentFragment = ( - { __typename?: 'User' } - & Pick - ); + expect(content).toMatchInlineSnapshot(` + "export type WidgetFragmentFragment = Pick; - export type EmploymentFragmentFragment = ( - { __typename?: 'User' } - & { employment: ( - { __typename?: 'Employment' } - & Pick - ) } - ); + export type EmploymentFragmentFragment = { employment: Pick }; export type UserQueryVariables = Exact<{ [key: string]: never; }>; - export type UserQuery = ( - { __typename?: 'Query' } - & { user: ( - { __typename?: 'User' } - & Pick - & { phone: ( - { __typename?: 'Phone' } - & Pick - ), employment: ( - { __typename?: 'Employment' } - & Pick - ) } - ) & (( - { __typename?: 'User' } - & Pick - ) | ( - { __typename?: 'User' } - & MakeEmpty - )) & (( - { __typename?: 'User' } - & { address: ( - { __typename?: 'Address' } - & Pick - ) } - ) | ( - { __typename?: 'User' } - & { address?: ( - { __typename?: 'Address' } - & Pick - ) } - )) & (( - { __typename?: 'User' } - & Pick - ) | ( - { __typename?: 'User' } - & MakeEmpty - )) } - ); + + export type UserQuery = { user: ( + Pick + & { + phone: Pick, + employment: Pick, + } + ) & (Pick | MakeEmpty) & ({ address: Pick } | { address?: Pick }) & (Pick | MakeEmpty) }; + " `); }); it('should generate an union of initial and deferred fields for fragments MakeEmpty', async () => { - const schema = buildSchema(` + const schema = buildSchema(/* GraphQL */ ` type Address { street1: String! } @@ -7128,7 +7249,7 @@ function test(q: GetEntityBrandDataQuery): void { } `); - const fragment = parse(` + const fragment = parse(/* GraphQL */ ` fragment WidgetFragment on User { widgetName widgetCount @@ -7179,65 +7300,27 @@ function test(q: GetEntityBrandDataQuery): void { { outputFile: 'graphql.ts' }, ); - expect(content).toBeSimilarStringTo(` - export type WidgetFragmentFragment = ( - { __typename?: 'User' } - & Pick - ); + expect(content).toMatchInlineSnapshot(` + "export type WidgetFragmentFragment = Pick; - export type EmploymentFragmentFragment = ( - { __typename?: 'User' } - & { employment: ( - { __typename?: 'Employment' } - & Pick - ) } - ); + export type EmploymentFragmentFragment = { employment: Pick }; export type UserQueryVariables = Exact<{ [key: string]: never; }>; - export type UserQuery = ( - { __typename?: 'Query' } - & { user: ( - { __typename?: 'User' } - & Pick - & { phone: ( - { __typename?: 'Phone' } - & Pick - ), employment: ( - { __typename?: 'Employment' } - & Pick - ) } - ) & (( - { __typename?: 'User' } - & Pick - ) | ( - { __typename?: 'User' } - & MakeEmpty - )) & (( - { __typename?: 'User' } - & { address: ( - { __typename?: 'Address' } - & Pick - ) } - ) | ( - { __typename?: 'User' } - & { address?: ( - { __typename?: 'Address' } - & Pick - ) } - )) & (( - { __typename?: 'User' } - & Pick - ) | ( - { __typename?: 'User' } - & MakeEmpty - )) } - ); + + export type UserQuery = { user: ( + Pick + & { + phone: Pick, + employment: Pick, + } + ) & (Pick | MakeEmpty) & ({ address: Pick } | { address?: Pick }) & (Pick | MakeEmpty) }; + " `); }); it('should support "preResolveTypes: true"', async () => { - const schema = buildSchema(` + const schema = buildSchema(/* GraphQL */ ` type Address { street1: String! } @@ -7265,7 +7348,7 @@ function test(q: GetEntityBrandDataQuery): void { } `); - const fragment = parse(` + const fragment = parse(/* GraphQL */ ` fragment WidgetFragment on User { widgetCount } @@ -7315,28 +7398,21 @@ function test(q: GetEntityBrandDataQuery): void { { outputFile: 'graphql.ts' }, ); - expect(content).toBeSimilarStringTo(` + expect(content).toMatchInlineSnapshot(` + "export type WidgetFragmentFragment = { widgetCount: number }; + + export type EmploymentFragmentFragment = { employment: { title: string } }; + export type UserQueryVariables = Exact<{ [key: string]: never; }>; - export type UserQuery = { - __typename?: 'Query', - user: { - __typename?: 'User', - clearanceLevel: string, - name: string, - phone: { __typename?: 'Phone', home: string }, - employment: { __typename?: 'Employment', title: string } - } & ({ __typename?: 'User', email: string } - | { __typename?: 'User', email?: never }) - & ({ __typename?: 'User', address: { __typename?: 'Address', street1: string } } - | { __typename?: 'User', address?: never }) - & ({ __typename?: 'User', widgetCount: number } - | { __typename?: 'User', widgetCount?: never }) - }; + + + export type UserQuery = { user: { clearanceLevel: string, name: string, phone: { home: string }, employment: { title: string } } & ({ email: string } | { email?: never }) & ({ address: { street1: string } } | { address?: never }) & ({ widgetCount: number } | { widgetCount?: never }) }; + " `); }); it('should resolve optionals according to maybeValue together with deferred fragments', async () => { - const schema = buildSchema(` + const schema = buildSchema(/* GraphQL */ ` type Address { street1: String } @@ -7365,7 +7441,7 @@ function test(q: GetEntityBrandDataQuery): void { } `); - const fragment = parse(` + const fragment = parse(/* GraphQL */ ` fragment WidgetFragment on User { widgetName widgetCount @@ -7417,107 +7493,100 @@ function test(q: GetEntityBrandDataQuery): void { { outputFile: 'graphql.ts' }, ); - expect(content).toBeSimilarStringTo(` + expect(content).toMatchInlineSnapshot(` + "export type WidgetFragmentFragment = { widgetName: string, widgetCount: number }; + + export type EmploymentFragmentFragment = { employment: { title: string } }; + export type UserQueryVariables = Exact<{ [key: string]: never; }>; - export type UserQuery = { - __typename?: 'Query', - user: { - __typename?: 'User', - clearanceLevel: string, - name: string, - phone: { __typename?: 'Phone', home: string }, - employment: { __typename?: 'Employment', title: string } - } & ({ __typename?: 'User', email: string } - | { __typename?: 'User', email?: never }) - & ({ __typename?: 'User', address: { __typename?: 'Address', street1: string | 'specialType' } } - | { __typename?: 'User', address?: never }) - & ({ __typename?: 'User', widgetName: string, widgetCount: number } - | { __typename?: 'User', widgetName?: never, widgetCount?: never }) - }; + + + export type UserQuery = { user: { clearanceLevel: string, name: string, phone: { home: string }, employment: { title: string } } & ({ email: string } | { email?: never }) & ({ address: { street1: string | 'specialType' } } | { address?: never }) & ({ widgetName: string, widgetCount: number } | { widgetName?: never, widgetCount?: never }) }; + " `); }); it('should generate correct types with inlineFragmentTypes: "mask""', async () => { - const schema = buildSchema(` - type Address { - street1: String! - } - - type Phone { - home: String! - } + const schema = buildSchema(/* GraphQL */ ` + type Address { + street1: String! + } - type Employment { - title: String! - } + type Phone { + home: String! + } - type User { - name: String! - email: String! - address: Address! - phone: Phone! - employment: Employment! - widgetCount: Int! - widgetPreference: String! - clearanceLevel: String! - favoriteFood: String! - leastFavoriteFood: String! - } + type Employment { + title: String! + } - type Query { - user: User! - } - `); + type User { + name: String! + email: String! + address: Address! + phone: Phone! + employment: Employment! + widgetCount: Int! + widgetPreference: String! + clearanceLevel: String! + favoriteFood: String! + leastFavoriteFood: String! + } - const fragment = parse(` - fragment WidgetFragment on User { - widgetCount - widgetPreference - } + type Query { + user: User! + } + `); - fragment FoodFragment on User { - favoriteFood - leastFavoriteFood - } + const fragment = parse(/* GraphQL */ ` + fragment WidgetFragment on User { + widgetCount + widgetPreference + } - fragment EmploymentFragment on User { - employment { - title + fragment FoodFragment on User { + favoriteFood + leastFavoriteFood } - } - query user { - user { - # Test inline fragment defer - ... @defer { - email + fragment EmploymentFragment on User { + employment { + title } + } - # Test inline fragment defer with nested selection set - ... @defer { - address { - street1 + query user { + user { + # Test inline fragment defer + ... @defer { + email } - } - # Test named fragment defer - ...WidgetFragment @defer + # Test inline fragment defer with nested selection set + ... @defer { + address { + street1 + } + } - # Test a secondary named fragment defer - ...FoodFragment @defer + # Test named fragment defer + ...WidgetFragment @defer - # Not deferred fields, fragments, selection sets, etc are left alone - name - phone { - home - } - ...EmploymentFragment - ... { - clearanceLevel + # Test a secondary named fragment defer + ...FoodFragment @defer + + # Not deferred fields, fragments, selection sets, etc are left alone + name + phone { + home + } + ...EmploymentFragment + ... { + clearanceLevel + } } } - } - `); + `); const { content } = await plugin( schema, @@ -7526,32 +7595,22 @@ function test(q: GetEntityBrandDataQuery): void { { outputFile: 'graphql.ts' }, ); - expect(content).toBeSimilarStringTo(` - export type WidgetFragmentFragment = { __typename?: 'User', widgetCount: number, widgetPreference: string } & { ' $fragmentName'?: 'WidgetFragmentFragment' }; + expect(content).toMatchInlineSnapshot(` + "export type WidgetFragmentFragment = { widgetCount: number, widgetPreference: string } & { ' $fragmentName'?: 'WidgetFragmentFragment' }; - export type FoodFragmentFragment = { __typename?: 'User', favoriteFood: string, leastFavoriteFood: string } & { ' $fragmentName'?: 'FoodFragmentFragment' }; + export type FoodFragmentFragment = { favoriteFood: string, leastFavoriteFood: string } & { ' $fragmentName'?: 'FoodFragmentFragment' }; - export type EmploymentFragmentFragment = { __typename?: 'User', employment: { __typename?: 'Employment', title: string } } & { ' $fragmentName'?: 'EmploymentFragmentFragment' }; + export type EmploymentFragmentFragment = { employment: { title: string } } & { ' $fragmentName'?: 'EmploymentFragmentFragment' }; - export type UserQueryVariables = Exact<{ [key: string]: never; }>; + export type UserQueryVariables = Exact<{ [key: string]: never; }>; - export type UserQuery = { - __typename?: 'Query', - user: ( - { - __typename?: 'User', - clearanceLevel: string, - name: string, - phone: { __typename?: 'Phone', home: string } - } & { ' $fragmentRefs'?: { 'EmploymentFragmentFragment': EmploymentFragmentFragment } } - ) & ({ __typename?: 'User', email: string } | { __typename?: 'User', email?: never }) & ({ __typename?: 'User', address: { __typename?: 'Address', street1: string } } | { __typename?: 'User', address?: never }) & ( - { __typename?: 'User' } - & { ' $fragmentRefs'?: { 'WidgetFragmentFragment': Incremental } } - ) & ( - { __typename?: 'User' } - & { ' $fragmentRefs'?: { 'FoodFragmentFragment': Incremental } } - ) }; - `); + + export type UserQuery = { user: ( + { clearanceLevel: string, name: string, phone: { home: string } } + & { ' $fragmentRefs'?: { 'EmploymentFragmentFragment': EmploymentFragmentFragment } } + ) & ({ email: string } | { email?: never }) & ({ address: { street1: string } } | { address?: never }) & { ' $fragmentRefs'?: { 'WidgetFragmentFragment': Incremental } } & { ' $fragmentRefs'?: { 'FoodFragmentFragment': Incremental } } }; + " + `); }); }); @@ -7570,19 +7629,15 @@ function test(q: GetEntityBrandDataQuery): void { { preResolveTypes: false }, { outputFile: '' }, ); - expect(result.content).toBeSimilarStringTo(` - export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + expect(result.content).toMatchInlineSnapshot(` + "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = ( - { __typename?: 'Query' } - & { notifications: Array<( - { __typename?: 'TextNotification' } - & Pick - ) | ( - { __typename?: 'ImageNotification' } - & Pick - )> } - ); + + export type Unnamed_1_Query = { notifications: Array< + | Pick + | Pick + > }; + " `); }); @@ -7604,16 +7659,14 @@ function test(q: GetEntityBrandDataQuery): void { { inlineFragmentTypes: 'combine' }, { outputFile: '' }, ); - expect(result.content).toBeSimilarStringTo(` - export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + expect(result.content).toMatchInlineSnapshot(` + "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { __typename?: 'Query', me: ( - { __typename?: 'User' } - & UserFragmentFragment - ) | null }; + export type Unnamed_1_Query = { me: UserFragmentFragment | null }; - export type UserFragmentFragment = { __typename?: 'User', id: string }; + export type UserFragmentFragment = { id: string }; + " `); }); @@ -7634,13 +7687,14 @@ function test(q: GetEntityBrandDataQuery): void { { inlineFragmentTypes: 'inline' }, { outputFile: '' }, ); - expect(result.content).toBeSimilarStringTo(` - export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + expect(result.content).toMatchInlineSnapshot(` + "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type Unnamed_1_Query = { me: { id: string } | null }; - export type UserFragmentFragment = { __typename?: 'User', id: string }; + export type UserFragmentFragment = { id: string }; + " `); }); @@ -7661,16 +7715,14 @@ function test(q: GetEntityBrandDataQuery): void { { inlineFragmentTypes: 'mask' }, { outputFile: '' }, ); - expect(result.content).toBeSimilarStringTo(` - export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + expect(result.content).toMatchInlineSnapshot(` + "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { __typename?: 'Query', me: ( - { __typename?: 'User' } - & { ' $fragmentRefs'?: { 'UserFragmentFragment': UserFragmentFragment } } - ) | null }; + export type Unnamed_1_Query = { me: { ' $fragmentRefs'?: { 'UserFragmentFragment': UserFragmentFragment } } | null }; - export type UserFragmentFragment = { __typename?: 'User', id: string } & { ' $fragmentName'?: 'UserFragmentFragment' }; + export type UserFragmentFragment = { id: string } & { ' $fragmentName'?: 'UserFragmentFragment' }; + " `); }); }); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts index 5bea74e94db..cc0bcb97a89 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts @@ -40,7 +40,7 @@ describe('TypeScript Operations Plugin - Enum', () => { export type MeQueryVariables = Exact<{ [key: string]: never; }>; - export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type MeQuery = { me: { id: string } | null }; " `); @@ -92,7 +92,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type MeQuery = { me: { id: string } | null }; " `); @@ -149,7 +149,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type MeQuery = { me: { id: string } | null }; " `); @@ -206,7 +206,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type MeQuery = { me: { id: string } | null }; " `); @@ -256,7 +256,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type MeQuery = { me: { id: string } | null }; " `); @@ -326,7 +326,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type MeQuery = { me: { id: string } | null }; " `); @@ -398,7 +398,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type MeQuery = { me: { id: string } | null }; " `); @@ -463,7 +463,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type MeQuery = { me: { id: string } | null }; " `); @@ -523,7 +523,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type MeQuery = { me: { id: string } | null }; " `); @@ -578,7 +578,7 @@ describe('TypeScript Operations Plugin - Enum', () => { export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type Unnamed_1_Query = { me: { id: string } | null }; " `); @@ -639,7 +639,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type MeQuery = { me: { id: string } | null }; " `); @@ -700,7 +700,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type MeQuery = { me: { id: string } | null }; " `); @@ -768,7 +768,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type MeQuery = { me: { id: string } | null }; " `); @@ -836,7 +836,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type MeQuery = { me: { id: string } | null }; " `); @@ -891,7 +891,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type MeQuery = { me: { id: string } | null }; " `); @@ -944,7 +944,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type MeQuery = { me: { id: string } | null }; " `); @@ -995,7 +995,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type IMeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type IMeQuery = { me: { id: string } | null }; " `); @@ -1046,7 +1046,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type IMeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type IMeQuery = { me: { id: string } | null }; " `); @@ -1097,7 +1097,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQueryZ = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type MeQueryZ = { me: { id: string } | null }; " `); @@ -1148,7 +1148,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQueryZ = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type MeQueryZ = { me: { id: string } | null }; " `); @@ -1209,7 +1209,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type mequery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type mequery = { me: { id: string } | null }; " `); @@ -1272,7 +1272,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type MeQuery = { me: { id: string } | null }; " `); @@ -1330,7 +1330,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + type MeQuery = { me: { id: string } | null }; " `); @@ -1392,7 +1392,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type IMeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type IMeQuery = { me: { id: string } | null }; " `); }); @@ -1443,7 +1443,7 @@ describe('TypeScript Operations Plugin - Enum', () => { }>; - export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type MeQuery = { me: { id: string } | null }; " `); }); @@ -1493,7 +1493,7 @@ describe('TypeScript Operations Plugin - Enum `%future added value`', () => { }>; - export type MeQuery = { __typename?: 'Query', me: { __typename?: 'User', id: string } | null }; + export type MeQuery = { me: { id: string } | null }; " `); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts index 7063e9d09ff..782fc23d9ec 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts @@ -121,16 +121,16 @@ describe('TypeScript Operations Plugin - Import Types', () => { }>; - export type UserQuery = { __typename?: 'Query', user: { __typename?: 'User', id: string, name: string, role: TypeImport.UserRole, createdAt: any } | null }; + export type UserQuery = { user: { id: string, name: string, role: TypeImport.UserRole, createdAt: any } | null }; export type UsersQueryVariables = Exact<{ input: TypeImport.UsersInput; }>; - export type UsersQuery = { __typename?: 'Query', users: - | { __typename?: 'UsersResponseOk', result: Array<{ __typename?: 'User', id: string }> } - | { __typename?: 'ResponseError', error: TypeImport.ResponseErrorType } + export type UsersQuery = { users: + | { result: Array<{ id: string }> } + | { error: TypeImport.ResponseErrorType } }; export type UsersWithScalarInputQueryVariables = Exact<{ @@ -140,8 +140,8 @@ describe('TypeScript Operations Plugin - Import Types', () => { }>; - export type UsersWithScalarInputQuery = { __typename?: 'Query', users: - | { __typename?: 'UsersResponseOk', result: Array<{ __typename: 'User' }> } + export type UsersWithScalarInputQuery = { users: + | { result: Array<{ __typename: 'User' }> } | { __typename: 'ResponseError' } }; " @@ -265,16 +265,16 @@ describe('TypeScript Operations Plugin - Import Types', () => { }>; - export type UserQuery = { __typename?: 'Query', user: { __typename?: 'User', id: string, name: string, role: TypeImport.UserRole, createdAt: any } | null }; + export type UserQuery = { user: { id: string, name: string, role: TypeImport.UserRole, createdAt: any } | null }; export type UsersQueryVariables = Exact<{ input: TypeImport.UsersInput; }>; - export type UsersQuery = { __typename?: 'Query', users: - | { __typename?: 'UsersResponseOk', result: Array<{ __typename?: 'User', id: string }> } - | { __typename?: 'ResponseError', error: TypeImport.ResponseErrorType } + export type UsersQuery = { users: + | { result: Array<{ id: string }> } + | { error: TypeImport.ResponseErrorType } }; export type UsersWithScalarInputQueryVariables = Exact<{ @@ -284,8 +284,8 @@ describe('TypeScript Operations Plugin - Import Types', () => { }>; - export type UsersWithScalarInputQuery = { __typename?: 'Query', users: - | { __typename?: 'UsersResponseOk', result: Array<{ __typename: 'User' }> } + export type UsersWithScalarInputQuery = { users: + | { result: Array<{ __typename: 'User' }> } | { __typename: 'ResponseError' } }; " @@ -383,7 +383,7 @@ describe('TypeScript Operations Plugin - Import Types', () => { }>; - export type UserQuery = { __typename?: 'Query', user: { __typename?: 'User', id: string, name: string, isOld: boolean, ageInt: number, ageFloat: number } | null }; + export type UserQuery = { user: { id: string, name: string, isOld: boolean, ageInt: number, ageFloat: number } | null }; " `); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts index 2071c3adf0e..03d33e1d2ec 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts @@ -120,7 +120,7 @@ describe('TypeScript Operations Plugin - Input', () => { }>; - export type UsersWithScalarInputQuery = { __typename?: 'Query', users: Array<{ __typename?: 'User', ageRange1: Array | null, ageRange2: Array, ageRange3: Array | null, ageRange4: Array }> }; + export type UsersWithScalarInputQuery = { users: Array<{ ageRange1: Array | null, ageRange2: Array, ageRange3: Array | null, ageRange4: Array }> }; " `); @@ -244,7 +244,7 @@ describe('TypeScript Operations Plugin - Input', () => { }>; - export type UsersWithScalarInputQuery = { readonly __typename?: 'Query', readonly users: ReadonlyArray<{ readonly __typename?: 'User', readonly ageRange1: ReadonlyArray | null, readonly ageRange2: ReadonlyArray, readonly ageRange3: ReadonlyArray | null, readonly ageRange4: ReadonlyArray }> }; + export type UsersWithScalarInputQuery = { readonly users: ReadonlyArray<{ readonly ageRange1: ReadonlyArray | null, readonly ageRange2: ReadonlyArray, readonly ageRange3: ReadonlyArray | null, readonly ageRange4: ReadonlyArray }> }; " `); @@ -361,7 +361,7 @@ describe('TypeScript Operations Plugin - Input', () => { }>; - export type UsersQuery = { __typename?: 'Query', users: Array<{ __typename: 'User' }> }; + export type UsersQuery = { users: Array<{ __typename: 'User' }> }; " `); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts index c2d4c58e33c..466b11ce8fd 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -124,16 +124,16 @@ describe('TypeScript Operations Plugin - Standalone', () => { }>; - export type UserQuery = { __typename?: 'Query', user: { __typename?: 'User', id: string, name: string, role: UserRole, createdAt: any, nickname: string | null } | null }; + export type UserQuery = { user: { id: string, name: string, role: UserRole, createdAt: any, nickname: string | null } | null }; export type UsersQueryVariables = Exact<{ input: UsersInput; }>; - export type UsersQuery = { __typename?: 'Query', users: - | { __typename?: 'UsersResponseOk', result: Array<{ __typename?: 'User', id: string }> } - | { __typename?: 'ResponseError', error: ResponseErrorType } + export type UsersQuery = { users: + | { result: Array<{ id: string }> } + | { error: ResponseErrorType } }; export type UsersWithScalarInputQueryVariables = Exact<{ @@ -143,8 +143,8 @@ describe('TypeScript Operations Plugin - Standalone', () => { }>; - export type UsersWithScalarInputQuery = { __typename?: 'Query', users: - | { __typename?: 'UsersResponseOk', result: Array<{ __typename: 'User' }> } + export type UsersWithScalarInputQuery = { users: + | { result: Array<{ __typename: 'User' }> } | { __typename: 'ResponseError' } }; " @@ -229,7 +229,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { }>; - export type UsersQuery = { __typename?: 'Query', users: Array<{ __typename?: 'User', id: string }> }; + export type UsersQuery = { users: Array<{ id: string }> }; " `); }); @@ -307,19 +307,16 @@ describe('TypeScript Operations Plugin - Standalone', () => { | 'ENUM_F'; export type UserQuery_user_User_innerEnums_EnumsInner = { - __typename?: 'EnumsInner', enumsDeep: Array }; export type UserQuery_user_User = { - __typename?: 'User', enum: EnumRoot, enums: Array, innerEnums: UserQuery_user_User_innerEnums_EnumsInner }; export type UserQuery_Query = { - __typename?: 'Query', user: UserQuery_user_User }; @@ -366,7 +363,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { }>; - export type UserQuery = { __typename?: 'Query', user: { __typename?: 'User', id: string | number | boolean, name: string } | null }; + export type UserQuery = { user: { id: string | number | boolean, name: string } | null }; " `); }); @@ -416,12 +413,12 @@ describe('TypeScript Operations Plugin - Standalone', () => { | 'ROLE_A' | 'ROLE_B'; - export type UserBasicFragment = { __typename?: 'User', id: string, name: string, role: RoleType | null }; + export type UserBasicFragment = { id: string, name: string, role: RoleType | null }; export type GetUsersAndViewerQueryVariables = Exact<{ [key: string]: never; }>; - export type GetUsersAndViewerQuery = { __typename?: 'Query', users: Array<{ __typename?: 'User', id: string, name: string, role: RoleType | null }>, viewer: { __typename?: 'User', id: string, name: string, role: RoleType | null } }; + export type GetUsersAndViewerQuery = { users: Array<{ id: string, name: string, role: RoleType | null }>, viewer: { id: string, name: string, role: RoleType | null } }; " `); }); @@ -479,9 +476,9 @@ describe('TypeScript Operations Plugin - Standalone', () => { export type GetUsersAndViewerQueryVariables = Exact<{ [key: string]: never; }>; - export type GetUsersAndViewerQuery = { __typename?: 'Query', users: Array<{ __typename?: 'User', id: string, name: string, role: RoleType | null }>, viewer: { __typename?: 'User', id: string, name: string, role: RoleType | null } }; + export type GetUsersAndViewerQuery = { users: Array<{ id: string, name: string, role: RoleType | null }>, viewer: { id: string, name: string, role: RoleType | null } }; - export type UserBasicFragment = { __typename?: 'User', id: string, name: string, role: RoleType | null }; + export type UserBasicFragment = { id: string, name: string, role: RoleType | null }; " `); }); @@ -708,4 +705,81 @@ describe('TypeScript Operations Plugin - Standalone', () => { validateTs(result, undefined, undefined, undefined, undefined, true); }); + + it('adds __typename correctly for Apollo Client when skipTypeNameForRoot:true, nonOptionalTypename:true are used', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + } + + type ResponseError { + error: ResponseErrorType! + } + + enum ResponseErrorType { + NOT_FOUND + INPUT_VALIDATION_ERROR + FORBIDDEN_ERROR + UNEXPECTED_ERROR + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + bestFriend: User + goodFriends: [User!]! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User($id: ID!) { + user(id: $id) { + id + name + createdAt + bestFriend { + name + } + goodFriends { + id + __typename + } + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + skipTypeNameForRoot: true, + nonOptionalTypename: true, + }, + { outputFile: '' } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserQueryVariables = Exact<{ + id: string; + }>; + + + export type UserQuery = { user: { __typename: 'User', id: string, name: string, createdAt: any, bestFriend: { __typename: 'User', name: string } | null, goodFriends: Array<{ __typename: 'User', id: string }> } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); }); diff --git a/packages/presets/client/src/index.ts b/packages/presets/client/src/index.ts index bc986b45e3b..939d8dd8031 100644 --- a/packages/presets/client/src/index.ts +++ b/packages/presets/client/src/index.ts @@ -137,7 +137,6 @@ export const preset: Types.OutputPreset = { strictScalars: options.config.strictScalars, namingConvention: options.config.namingConvention, useTypeImports: options.config.useTypeImports, - skipTypename: options.config.skipTypename, arrayInputCoercion: options.config.arrayInputCoercion, enumType: options.config.enumType, enumValues: options.config.enumValues, diff --git a/packages/presets/client/tests/client-preset.enum.spec.ts b/packages/presets/client/tests/client-preset.enum.spec.ts index 58ac2f6f67f..c6dcc1897a0 100644 --- a/packages/presets/client/tests/client-preset.enum.spec.ts +++ b/packages/presets/client/tests/client-preset.enum.spec.ts @@ -82,7 +82,7 @@ describe('client-preset - Enum', () => { }>; - export type ShapeQuery = { __typename?: 'Query', shape: { __typename?: 'ShapeObj', id: string } }; + export type ShapeQuery = { shape: { id: string } }; export const ShapeDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Shape"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"shape"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Shape"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"shape"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"shape"},"value":{"kind":"Variable","name":{"kind":"Name","value":"shape"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode;" @@ -142,7 +142,7 @@ describe('client-preset - Enum', () => { export type ShapeQueryVariables = Exact<{ [key: string]: never; }>; - export type ShapeQuery = { __typename?: 'Query', shape: { __typename?: 'ShapeObj', id: string, shape: Shape } }; + export type ShapeQuery = { shape: { id: string, shape: Shape } }; export const ShapeDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Shape"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"shape"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"shape"}}]}}]}}]} as unknown as DocumentNode;" @@ -203,7 +203,7 @@ describe('client-preset - Enum', () => { }>; - export type ShapeQuery = { __typename?: 'Query', shape: { __typename?: 'ShapeObj', id: string } }; + export type ShapeQuery = { shape: { id: string } }; export const ShapeDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Shape"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"shape"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Shape"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"shape"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"shape"},"value":{"kind":"Variable","name":{"kind":"Name","value":"shape"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode;" diff --git a/packages/presets/client/tests/client-preset.nullability.spec.ts b/packages/presets/client/tests/client-preset.nullability.spec.ts index 8da8fae16bc..3d081a1d731 100644 --- a/packages/presets/client/tests/client-preset.nullability.spec.ts +++ b/packages/presets/client/tests/client-preset.nullability.spec.ts @@ -85,9 +85,7 @@ describe('client-preset - nullability', () => { expect(formattedContent).toBeSimilarStringTo(` export type TestQuery = { - __typename?: "Query"; me: { - __typename?: "User"; field: string; fieldLevel0: string; fieldLevel1: string | null; @@ -136,9 +134,7 @@ describe('client-preset - nullability', () => { expect(formattedContent).toBeSimilarStringTo(` export type TestQuery = { - __typename?: "Query"; me: { - __typename?: "User"; field: string | null; fieldLevel0: string | null; fieldLevel1: string | null; diff --git a/packages/presets/client/tests/client-preset.spec.ts b/packages/presets/client/tests/client-preset.spec.ts index 129dc8613ec..5594f5ed2b3 100644 --- a/packages/presets/client/tests/client-preset.spec.ts +++ b/packages/presets/client/tests/client-preset.spec.ts @@ -368,14 +368,14 @@ export * from "./gql";`); export type AQueryVariables = Exact<{ [key: string]: never; }>; - export type AQuery = { __typename?: 'Query', a: string | null }; + export type AQuery = { a: string | null }; export type BQueryVariables = Exact<{ [key: string]: never; }>; - export type BQuery = { __typename?: 'Query', b: string | null }; + export type BQuery = { b: string | null }; - export type CFragment = { __typename?: 'Query', c: string | null } & { ' $fragmentName'?: 'CFragment' }; + export type CFragment = { c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; export const ADocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; @@ -549,12 +549,12 @@ export * from "./gql";`); export type MeQueryVariables = Exact<{ [key: string]: never; }>; - export type MeQuery = { __typename?: 'Query', unmasked: { __typename?: 'User', id: string, name: string, age: number } | null, masked: ( - { __typename?: 'User', id: string } + export type MeQuery = { unmasked: { id: string, name: string, age: number } | null, masked: ( + { id: string } & { ' $fragmentRefs'?: { 'User_MeFragment': User_MeFragment } } ) | null }; - export type User_MeFragment = { __typename?: 'User', name: string, age: number } & { ' $fragmentName'?: 'User_MeFragment' }; + export type User_MeFragment = { name: string, age: number } & { ' $fragmentName'?: 'User_MeFragment' }; export const User_MeFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"User_Me"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"User"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"age"}}]}}]} as unknown as DocumentNode; export const MeDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Me"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"unmasked"},"name":{"kind":"Name","value":"me"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"User_Me"},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"unmask"}}]}]}},{"kind":"Field","alias":{"kind":"Name","value":"masked"},"name":{"kind":"Name","value":"me"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"User_Me"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"User_Me"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"User"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"age"}}]}}]} as unknown as DocumentNode;" @@ -640,7 +640,7 @@ export * from "./gql";`); export type AQueryVariables = Exact<{ [key: string]: never; }>; - export type AQuery = { __typename?: 'Query', a: string | null }; + export type AQuery = { a: string | null }; export const ADocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"a"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode;" @@ -1478,12 +1478,12 @@ export * from "./gql.cjs";`); export type BbbQueryVariables = Exact<{ [key: string]: never; }>; - export type BbbQuery = { __typename?: 'Query', b: string | null }; + export type BbbQuery = { b: string | null }; export type AaaQueryVariables = Exact<{ [key: string]: never; }>; - export type AaaQuery = { __typename?: 'Query', a: string | null }; + export type AaaQuery = { a: string | null }; export const BbbDocument = {"__meta__":{"cacheKeys":["bbb"]},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"bbb"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"b"}}]}}]} as unknown as DocumentNode; @@ -1537,14 +1537,14 @@ export * from "./gql.cjs";`); export type AQueryVariables = Exact<{ [key: string]: never; }>; - export type AQuery = { __typename?: 'Query', a: string | null }; + export type AQuery = { a: string | null }; export type BQueryVariables = Exact<{ [key: string]: never; }>; - export type BQuery = { __typename?: 'Query', b: string | null }; + export type BQuery = { b: string | null }; - export type CFragment = { __typename?: 'Query', c: string | null } & { ' $fragmentName'?: 'CFragment' }; + export type CFragment = { c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; export const ADocument = {"__meta__":{"hash":"b61b879c1eb0040bce65d70c8adfb1ae9360f52f"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; @@ -1599,14 +1599,14 @@ export * from "./gql.cjs";`); export type AQueryVariables = Exact<{ [key: string]: never; }>; - export type AQuery = { __typename?: 'Query', a: string | null }; + export type AQuery = { a: string | null }; export type BQueryVariables = Exact<{ [key: string]: never; }>; - export type BQuery = { __typename?: 'Query', b: string | null }; + export type BQuery = { b: string | null }; - export type CFragment = { __typename?: 'Query', c: string | null } & { ' $fragmentName'?: 'CFragment' }; + export type CFragment = { c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; export const ADocument = {"__meta__":{"hash":"b61b879c1eb0040bce65d70c8adfb1ae9360f52f"}} as unknown as DocumentNode; @@ -1661,14 +1661,14 @@ export * from "./gql.cjs";`); export type AQueryVariables = Exact<{ [key: string]: never; }>; - export type AQuery = { __typename?: 'Query', a: string | null }; + export type AQuery = { a: string | null }; export type BQueryVariables = Exact<{ [key: string]: never; }>; - export type BQuery = { __typename?: 'Query', b: string | null }; + export type BQuery = { b: string | null }; - export type CFragment = { __typename?: 'Query', c: string | null } & { ' $fragmentName'?: 'CFragment' }; + export type CFragment = { c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; export const ADocument = {"__meta__":{"custom_property_name":"b61b879c1eb0040bce65d70c8adfb1ae9360f52f"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; @@ -1723,12 +1723,12 @@ export * from "./gql.cjs";`); export type AaaQueryVariables = Exact<{ [key: string]: never; }>; - export type AaaQuery = { __typename?: 'Query', a: string | null }; + export type AaaQuery = { a: string | null }; export type BbbQueryVariables = Exact<{ [key: string]: never; }>; - export type BbbQuery = { __typename?: 'Query', b: string | null }; + export type BbbQuery = { b: string | null }; export const AaaDocument = {"__meta__":{"cacheKeys":["aaa"],"hash":"682f60dea844320c05fcb4fb6c4118015902c9a8"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"aaa"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; @@ -1783,14 +1783,14 @@ export * from "./gql.cjs";`); export type AQueryVariables = Exact<{ [key: string]: never; }>; - export type AQuery = { __typename?: 'Query', a: string | null }; + export type AQuery = { a: string | null }; export type BQueryVariables = Exact<{ [key: string]: never; }>; - export type BQuery = { __typename?: 'Query', b: string | null }; + export type BQuery = { b: string | null }; - export type CFragment = { __typename?: 'Query', c: string | null } & { ' $fragmentName'?: 'CFragment' }; + export type CFragment = { c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; export const ADocument = {"__meta__":{"hash":"7d0eedabb966107835cf307a0ebaf93b5d2cb8c30228611ffe3d27a53c211a0c"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; @@ -1849,14 +1849,14 @@ export * from "./gql.cjs";`); export type AQueryVariables = Exact<{ [key: string]: never; }>; - export type AQuery = { __typename?: 'Query', a: string | null }; + export type AQuery = { a: string | null }; export type BQueryVariables = Exact<{ [key: string]: never; }>; - export type BQuery = { __typename?: 'Query', b: string | null }; + export type BQuery = { b: string | null }; - export type CFragment = { __typename?: 'Query', c: string | null } & { ' $fragmentName'?: 'CFragment' }; + export type CFragment = { c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; export const ADocument = {"__meta__":{"hash":"queryA{a}"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; @@ -1916,14 +1916,14 @@ export * from "./gql.cjs";`); export type AQueryVariables = Exact<{ [key: string]: never; }>; - export type AQuery = { __typename?: 'Query', a: string | null }; + export type AQuery = { a: string | null }; export type BQueryVariables = Exact<{ [key: string]: never; }>; - export type BQuery = { __typename?: 'Query', b: string | null }; + export type BQuery = { b: string | null }; - export type CFragment = { __typename?: 'Query', c: string | null } & { ' $fragmentName'?: 'CFragment' }; + export type CFragment = { c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; export const ADocument = {"__meta__":{"hash":"7d0eedabb966107835cf307a0ebaf93b5d2cb8c30228611ffe3d27a53c211a0c"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; @@ -1983,14 +1983,14 @@ export * from "./gql.cjs";`); export type AQueryVariables = Exact<{ [key: string]: never; }>; - export type AQuery = { __typename?: 'Query', a: string | null }; + export type AQuery = { a: string | null }; export type BQueryVariables = Exact<{ [key: string]: never; }>; - export type BQuery = { __typename?: 'Query', b: string | null }; + export type BQuery = { b: string | null }; - export type CFragment = { __typename?: 'Query', c: string | null } & { ' $fragmentName'?: 'CFragment' }; + export type CFragment = { c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; export const ADocument = {"__meta__":{"hash":"a82d8b22f2bf805563146dc8ad80b2eb054845441539e3a5a69d1f534bb5bc0bd4f9470053b9f61b6aa1966cfc2f67406258102e5ee3a356a5d171506f3ede50"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; @@ -2052,21 +2052,18 @@ export * from "./gql.cjs";`); type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type AbFragment = ( - { __typename?: 'A', b: string } + { b: string } & { ' $fragmentRefs'?: { 'AcFragment': AcFragment;'AaFragment': AaFragment } } ) & { ' $fragmentName'?: 'AbFragment' }; - export type AaFragment = { __typename?: 'A', b: string } & { ' $fragmentName'?: 'AaFragment' }; + export type AaFragment = { b: string } & { ' $fragmentName'?: 'AaFragment' }; export type OiQueryVariables = Exact<{ [key: string]: never; }>; - export type OiQuery = { __typename?: 'Query', a: ( - { __typename?: 'A' } - & { ' $fragmentRefs'?: { 'AbFragment': AbFragment;'AcFragment': AcFragment } } - ) }; + export type OiQuery = { a: { ' $fragmentRefs'?: { 'AbFragment': AbFragment;'AcFragment': AcFragment } } }; - export type AcFragment = { __typename?: 'A', b: string } & { ' $fragmentName'?: 'AcFragment' }; + export type AcFragment = { b: string } & { ' $fragmentName'?: 'AcFragment' }; export const AcFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AC"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"A"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"b"}}]}}]} as unknown as DocumentNode; export const AaFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AA"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"A"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"b"}}]}}]} as unknown as DocumentNode; @@ -2075,6 +2072,87 @@ export * from "./gql.cjs";`); `); }); + it('correctly handle fragment references with explicit __typename', async () => { + const { result } = await executeCodegen({ + schema: /* GraphQL */ ` + type Query { + a: A! + } + + type A { + b: String! + a: A! + } + `, + documents: [ + /* GraphQL */ ` + fragment AC on A { + __typename + b + } + `, + /* GraphQL */ ` + fragment AA on A { + __typename + b + } + `, + /* GraphQL */ ` + fragment AB on A { + __typename + b + ...AC + ...AA + } + `, + /* GraphQL */ ` + query OI { + __typename + a { + __typename + ...AB + ...AC + } + } + `, + ], + generates: { + 'out1/': { + preset, + plugins: [], + }, + }, + }); + const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); + expect(graphqlFile.content).toMatchInlineSnapshot(` + "/* eslint-disable */ + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type AcFragment = { __typename: 'A', b: string } & { ' $fragmentName'?: 'AcFragment' }; + + export type AaFragment = { __typename: 'A', b: string } & { ' $fragmentName'?: 'AaFragment' }; + + export type AbFragment = ( + { __typename: 'A', b: string } + & { ' $fragmentRefs'?: { 'AcFragment': AcFragment;'AaFragment': AaFragment } } + ) & { ' $fragmentName'?: 'AbFragment' }; + + export type OiQueryVariables = Exact<{ [key: string]: never; }>; + + + export type OiQuery = { __typename: 'Query', a: ( + { __typename: 'A' } + & { ' $fragmentRefs'?: { 'AbFragment': AbFragment;'AcFragment': AcFragment } } + ) }; + + export const AcFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AC"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"A"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"b"}}]}}]} as unknown as DocumentNode; + export const AaFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AA"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"A"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"b"}}]}}]} as unknown as DocumentNode; + export const AbFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AB"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"A"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"b"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AC"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AA"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AC"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"A"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"b"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AA"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"A"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"b"}}]}}]} as unknown as DocumentNode; + export const OiDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"OI"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"a"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AB"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AC"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AC"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"A"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"b"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AA"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"A"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"b"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AB"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"A"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"__typename"}},{"kind":"Field","name":{"kind":"Name","value":"b"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AC"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"AA"}}]}}]} as unknown as DocumentNode;" + `); + }); + describe('handles @defer directive', () => { it('generates correct types and metadata', async () => { const { result } = await executeCodegen({ @@ -2108,27 +2186,24 @@ export * from "./gql.cjs";`); export type FooQueryVariables = Exact<{ [key: string]: never; }>; - export type FooQuery = { __typename?: 'Query', foo: { __typename?: 'Foo' } & ( - { __typename?: 'Foo' } - & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } - ) | null }; + export type FooQuery = { foo: + | { ' $fragmentRefs'?: { 'FooFragment': Incremental } } + | Record + | null }; export type FoosQueryVariables = Exact<{ [key: string]: never; }>; - export type FoosQuery = { __typename?: 'Query', foos: Array<{ __typename?: 'Foo' } & ( - { __typename?: 'Foo' } - & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } - ) | null> | null }; + export type FoosQuery = { foos: Array< + | { ' $fragmentRefs'?: { 'FooFragment': Incremental } } + | Record + | null> | null }; - export type FooFragment = { __typename?: 'Foo', value: string | null } & { ' $fragmentName'?: 'FooFragment' }; + export type FooFragment = { value: string | null } & { ' $fragmentName'?: 'FooFragment' }; - export type FooFragment = { __typename?: 'Foo', id: string | null } & ({ __typename?: 'Foo', value: string | null } | { __typename?: 'Foo', value?: never }) & { ' $fragmentName'?: 'FooFragment' }; + export type FooFragment = { id: string | null } & ({ value: string | null } | { value?: never }) & { ' $fragmentName'?: 'FooFragment' }; - export type FooNestedFragment = { __typename?: 'Foo', id: string | null } & ( - { __typename?: 'Foo' } - & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } - ) & { ' $fragmentName'?: 'FooNestedFragment' }; + export type FooNestedFragment = { id: string | null } & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } & { ' $fragmentName'?: 'FooNestedFragment' }; export const FooFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]} as unknown as DocumentNode; export const FooFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}}]} as unknown as DocumentNode; @@ -2173,27 +2248,24 @@ export * from "./gql.cjs";`); export type FooQueryVariables = Exact<{ [key: string]: never; }>; - export type FooQuery = { __typename?: 'Query', foo: { __typename?: 'Foo' } & ( - { __typename?: 'Foo' } - & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } - ) | null }; + export type FooQuery = { foo: + | { ' $fragmentRefs'?: { 'FooFragment': Incremental } } + | Record + | null }; export type FoosQueryVariables = Exact<{ [key: string]: never; }>; - export type FoosQuery = { __typename?: 'Query', foos: Array<{ __typename?: 'Foo' } & ( - { __typename?: 'Foo' } - & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } - ) | null> | null }; + export type FoosQuery = { foos: Array< + | { ' $fragmentRefs'?: { 'FooFragment': Incremental } } + | Record + | null> | null }; - export type FooFragment = { __typename?: 'Foo', value: string | null } & { ' $fragmentName'?: 'FooFragment' }; + export type FooFragment = { value: string | null } & { ' $fragmentName'?: 'FooFragment' }; - export type FooFragment = { __typename?: 'Foo', id: string | null } & ({ __typename?: 'Foo', value: string | null } | { __typename?: 'Foo', value?: never }) & { ' $fragmentName'?: 'FooFragment' }; + export type FooFragment = { id: string | null } & ({ value: string | null } | { value?: never }) & { ' $fragmentName'?: 'FooFragment' }; - export type FooNestedFragment = { __typename?: 'Foo', id: string | null } & ( - { __typename?: 'Foo' } - & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } - ) & { ' $fragmentName'?: 'FooNestedFragment' }; + export type FooNestedFragment = { id: string | null } & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } & { ' $fragmentName'?: 'FooNestedFragment' }; export const FooFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]} as unknown as DocumentNode; export const FooFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}}]} as unknown as DocumentNode; @@ -2238,27 +2310,24 @@ export * from "./gql.cjs";`); export type FooQueryVariables = Exact<{ [key: string]: never; }>; - export type FooQuery = { __typename?: 'Query', foo: { __typename?: 'Foo' } & ( - { __typename?: 'Foo' } - & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } - ) | null }; + export type FooQuery = { foo: + | { ' $fragmentRefs'?: { 'FooFragment': Incremental } } + | Record + | null }; export type FoosQueryVariables = Exact<{ [key: string]: never; }>; - export type FoosQuery = { __typename?: 'Query', foos: Array<{ __typename?: 'Foo' } & ( - { __typename?: 'Foo' } - & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } - ) | null> | null }; + export type FoosQuery = { foos: Array< + | { ' $fragmentRefs'?: { 'FooFragment': Incremental } } + | Record + | null> | null }; - export type FooFragment = { __typename?: 'Foo', value: string | null } & { ' $fragmentName'?: 'FooFragment' }; + export type FooFragment = { value: string | null } & { ' $fragmentName'?: 'FooFragment' }; - export type FooFragment = { __typename?: 'Foo', id: string | null } & ({ __typename?: 'Foo', value: string | null } | { __typename?: 'Foo', value?: never }) & { ' $fragmentName'?: 'FooFragment' }; + export type FooFragment = { id: string | null } & ({ value: string | null } | { value?: never }) & { ' $fragmentName'?: 'FooFragment' }; - export type FooNestedFragment = { __typename?: 'Foo', id: string | null } & ( - { __typename?: 'Foo' } - & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } - ) & { ' $fragmentName'?: 'FooNestedFragment' }; + export type FooNestedFragment = { id: string | null } & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } & { ' $fragmentName'?: 'FooNestedFragment' }; export class TypedDocumentString extends String @@ -2376,27 +2445,24 @@ export * from "./gql.cjs";`); export type FooQueryVariables = Exact<{ [key: string]: never; }>; - export type FooQuery = { __typename?: 'Query', foo: { __typename?: 'Foo' } & ( - { __typename?: 'Foo' } - & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } - ) | null }; + export type FooQuery = { foo: + | { ' $fragmentRefs'?: { 'FooFragment': Incremental } } + | Record + | null }; export type FoosQueryVariables = Exact<{ [key: string]: never; }>; - export type FoosQuery = { __typename?: 'Query', foos: Array<{ __typename?: 'Foo' } & ( - { __typename?: 'Foo' } - & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } - ) | null> | null }; + export type FoosQuery = { foos: Array< + | { ' $fragmentRefs'?: { 'FooFragment': Incremental } } + | Record + | null> | null }; - export type FooFragment = { __typename?: 'Foo', value: string | null } & { ' $fragmentName'?: 'FooFragment' }; + export type FooFragment = { value: string | null } & { ' $fragmentName'?: 'FooFragment' }; - export type FooFragment = { __typename?: 'Foo', id: string | null } & ({ __typename?: 'Foo', value: string | null } | { __typename?: 'Foo', value?: never }) & { ' $fragmentName'?: 'FooFragment' }; + export type FooFragment = { id: string | null } & ({ value: string | null } | { value?: never }) & { ' $fragmentName'?: 'FooFragment' }; - export type FooNestedFragment = { __typename?: 'Foo', id: string | null } & ( - { __typename?: 'Foo' } - & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } - ) & { ' $fragmentName'?: 'FooNestedFragment' }; + export type FooNestedFragment = { id: string | null } & { ' $fragmentRefs'?: { 'FooFragment': Incremental } } & { ' $fragmentName'?: 'FooNestedFragment' }; export class TypedDocumentString extends String @@ -2512,20 +2578,14 @@ export * from "./gql.cjs";`); export type FooQueryVariables = Exact<{ [key: string]: never; }>; - export type FooQuery = { __typename?: 'Query', foo: ( - { __typename?: 'Foo' } - & { ' $fragmentRefs'?: { 'FooFragment': FooFragment } } - ) | null }; + export type FooQuery = { foo: { ' $fragmentRefs'?: { 'FooFragment': FooFragment } } | null }; export type FoosQueryVariables = Exact<{ [key: string]: never; }>; - export type FoosQuery = { __typename?: 'Query', foos: Array<( - { __typename?: 'Foo' } - & { ' $fragmentRefs'?: { 'FooFragment': FooFragment } } - ) | null> | null }; + export type FoosQuery = { foos: Array<{ ' $fragmentRefs'?: { 'FooFragment': FooFragment } } | null> | null }; - export type FooFragment = { __typename?: 'Foo', value: string | null } & { ' $fragmentName'?: 'FooFragment' }; + export type FooFragment = { value: string | null } & { ' $fragmentName'?: 'FooFragment' }; export class TypedDocumentString extends String @@ -2784,7 +2844,7 @@ export * from "./gql.cjs";`); export type OnRegionCreatedSubscriptionVariables = Exact<{ [key: string]: never; }>; - export type OnRegionCreatedSubscription = { __typename?: 'Subscription', onRegionCreated: { __typename: 'Region', regionId: number, regionDescription: string } }; + export type OnRegionCreatedSubscription = { onRegionCreated: { __typename: 'Region', regionId: number, regionDescription: string } }; export class TypedDocumentString extends String @@ -2861,7 +2921,7 @@ export * from "./gql.cjs";`); export type Test_UserQueryVariables = Exact<{ [key: string]: never; }>; - export type Test_UserQuery = { readonly __typename?: 'Query', readonly user: { readonly __typename?: 'User', readonly id: string, readonly name: string } | null }; + export type Test_UserQuery = { readonly user: { readonly id: string, readonly name: string } | null }; export const Test_UserDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Test_User"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"user"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"StringValue","value":"user-001","block":false}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]} as unknown as DocumentNode;" From 4ce7cde55f1d6e8b1d6cbee7a93c3cec0ebba6f7 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Fri, 2 Jan 2026 00:51:54 +1100 Subject: [PATCH 17/69] [typescript-operations] Clean up selection set processor that depends on `typescript` plugin (`preResolveTypes: false`) (#10556) * Remove legacy selection set proccessor that depends on typescript plugin * Remove obsolete tests * Improve tests to be explicit --- .../src/base-documents-visitor.ts | 26 - .../typescript/operations/src/visitor.ts | 28 +- .../__snapshots__/ts-documents.spec.ts.snap | 267 +- .../tests/extract-all-types.spec.ts | 284 -- .../operations/tests/ts-documents.spec.ts | 2469 ++++------------- 5 files changed, 638 insertions(+), 2436 deletions(-) diff --git a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts index f529298abd4..a8281eabf00 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts @@ -33,7 +33,6 @@ function getRootType(operation: OperationTypeNode, schema: GraphQLSchema) { } export interface ParsedDocumentsConfig extends ParsedTypesConfig { - preResolveTypes: boolean; extractAllFieldsToTypes: boolean; globalNamespace: boolean; operationResultSuffix: string; @@ -50,30 +49,6 @@ export interface ParsedDocumentsConfig extends ParsedTypesConfig { } export interface RawDocumentsConfig extends RawTypesConfig { - /** - * @default true - * @description Uses primitive types where possible. - * Set to `false` in order to use `Pick` and take use the types generated by `typescript` plugin. - * - * @exampleMarkdown - * ```ts filename="codegen.ts" - * import type { CodegenConfig } from '@graphql-codegen/cli'; - * - * const config: CodegenConfig = { - * // ... - * generates: { - * 'path/to/file': { - * // plugins... - * config: { - * preResolveTypes: false - * }, - * }, - * }, - * }; - * export default config; - * ``` - */ - preResolveTypes?: boolean; /** * @default false * @description Avoid adding `__typename` for root types. This is ignored when a selection explicitly specifies `__typename`. @@ -250,7 +225,6 @@ export class BaseDocumentsVisitor< exportFragmentSpreadSubTypes: getConfigValue(rawConfig.exportFragmentSpreadSubTypes, false), enumPrefix: getConfigValue(rawConfig.enumPrefix, true), enumSuffix: getConfigValue(rawConfig.enumSuffix, true), - preResolveTypes: getConfigValue(rawConfig.preResolveTypes, true), dedupeOperationSuffix: getConfigValue(rawConfig.dedupeOperationSuffix, false), omitOperationSuffix: getConfigValue(rawConfig.omitOperationSuffix, false), skipTypeNameForRoot: getConfigValue(rawConfig.skipTypeNameForRoot, false), diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 6835cbbd73e..4facfc4daa8 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -50,7 +50,6 @@ import { SCALARS, TypeScriptOperationVariablesToObject, } from './ts-operation-variables-to-object.js'; -import { TypeScriptSelectionSetProcessor } from './ts-selection-set-processor.js'; export interface TypeScriptDocumentsParsedConfig extends ParsedDocumentsConfig { arrayInputCoercion: boolean; @@ -92,7 +91,6 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< avoidOptionals: normalizeAvoidOptionals(getConfigValue(config.avoidOptionals, false)), immutableTypes: getConfigValue(config.immutableTypes, false), nonOptionalTypename: getConfigValue(config.nonOptionalTypename, false), - preResolveTypes: getConfigValue(config.preResolveTypes, true), mergeFragmentTypes: getConfigValue(config.mergeFragmentTypes, false), allowUndefinedQueryVariables: getConfigValue(config.allowUndefinedQueryVariables, false), enumType: getConfigValue(config.enumType, 'string-literal'), @@ -109,22 +107,9 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< this._outputPath = outputPath; autoBind(this); - const preResolveTypes = getConfigValue(config.preResolveTypes, true); const defaultMaybeValue = 'T | null'; const maybeValue = getConfigValue(config.maybeValue, defaultMaybeValue); - const wrapOptional = (type: string) => { - if (preResolveTypes === true) { - return maybeValue.replace('T', type); - } - const prefix = this.config.namespacedImportName ? `${this.config.namespacedImportName}.` : ''; - return `${prefix}Maybe<${type}>`; - }; - const wrapArray = (type: string) => { - const listModifier = this.config.immutableTypes ? 'ReadonlyArray' : 'Array'; - return `${listModifier}<${type}>`; - }; - const allFragments: LoadedFragment[] = [ ...( documentNode.definitions.filter( @@ -150,17 +135,18 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< formatNamedField: ({ name, isOptional }) => { return (this.config.immutableTypes ? `readonly ${name}` : name) + (isOptional ? '?' : ''); }, - wrapTypeWithModifiers(baseType, type) { + wrapTypeWithModifiers: (baseType, type) => { return wrapTypeWithModifiers(baseType, type, { - wrapOptional, - wrapArray, + wrapOptional: type => maybeValue.replace('T', type), + wrapArray: type => { + const listModifier = this.config.immutableTypes ? 'ReadonlyArray' : 'Array'; + return `${listModifier}<${type}>`; + }, }); }, printFieldsOnNewLines: this.config.printFieldsOnNewLines, }; - const processor = new ( - preResolveTypes ? PreResolveTypesProcessor : TypeScriptSelectionSetProcessor - )(processorConfig); + const processor = new PreResolveTypesProcessor(processorConfig); this.setSelectionSetHandler( new SelectionSetToObject( processor, diff --git a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap index 210cac2e1a8..760b49909be 100644 --- a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap +++ b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap @@ -56,7 +56,7 @@ export type ElementMetadataFragment = " `; -exports[`TypeScript Operations Plugin > Issues > #2916 - Missing import prefix with preResolveTypes: true and near-operation-file preset 1`] = ` +exports[`TypeScript Operations Plugin > Issues > #2916 - Missing import prefix with near-operation-file preset 1`] = ` "export type Department = | 'Direction' | 'Development'; @@ -81,23 +81,6 @@ export type VenueFragment = export type QQueryVariables = Exact<{ [key: string]: never; }>; -export type QQuery = { hotel: { id: string, gpsPosition: { lat: number, lng: number } }, transport: { id: string } }; -" -`; - -exports[`TypeScript Operations Plugin > Issues > #3064 - fragments over interfaces causes issues with fields 2`] = ` -"type Venue_Hotel_Fragment = { id: string, gpsPosition: { lat: number, lng: number } }; - -type Venue_Transport_Fragment = { id: string }; - -export type VenueFragment = - | Venue_Hotel_Fragment - | Venue_Transport_Fragment -; - -export type QQueryVariables = Exact<{ [key: string]: never; }>; - - export type QQuery = { hotel: { id: string, gpsPosition: { lat: number, lng: number } }, transport: { id: string } }; function test(q: QQuery) { if (q.hotel) { @@ -110,7 +93,7 @@ function test(q: QQuery) { }" `; -exports[`TypeScript Operations Plugin > Issues > #6874 - generates types when parent type differs from spread fragment member types and preResolveTypes=true 1`] = ` +exports[`TypeScript Operations Plugin > Issues > #6874 - generates types when parent type differs from spread fragment member types 1`] = ` "export type SnakeQueryQueryVariables = Exact<{ [key: string]: never; }>; @@ -130,24 +113,13 @@ export type AnimalFragmentFragment = " `; -exports[`TypeScript Operations Plugin > Issues > #8793 selecting __typename should not be optional 1`] = ` -"export type SnakeQueryQueryVariables = Exact<{ [key: string]: never; }>; - - -export type SnakeQueryQuery = { __typename: 'Query', snake: - | { __typename: 'Snake' } - | { __typename: 'Error' } - }; -" -`; - exports[`TypeScript Operations Plugin > Selection Set > Should generate the correct __typename when using both inline fragment and spread over type 1`] = ` "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; -export type UserQueryQuery = { user: Maybe> }; +export type UserQueryQuery = { user: { id: string, name: string | null } | null }; -export type UserFragment = Pick; +export type UserFragment = { id: string, name: string | null }; " `; @@ -155,7 +127,7 @@ exports[`TypeScript Operations Plugin > Selection Set > Should generate the corr "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; -export type UserQueryQuery = { user: Maybe> }; +export type UserQueryQuery = { user: { id: string, name: string | null } | null }; " `; @@ -163,56 +135,29 @@ exports[`TypeScript Operations Plugin > Selection Set > Should generate the corr "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; -export type UserQueryQuery = { user: Maybe> }; +export type UserQueryQuery = { user: { id: string, name: string | null } | null }; -export type UserFragment = Pick; +export type UserFragment = { id: string, name: string | null }; " `; exports[`TypeScript Operations Plugin > Selection Set > Should generate the correct __typename when using fragment spread over union 1`] = ` -"export type UserFragmentFragment = Pick; +"export type UserFragmentFragment = { id: string }; export type AaaQueryVariables = Exact<{ [key: string]: never; }>; export type AaaQuery = { user: - | Pick + | { id: string } | Record }; " `; -exports[`TypeScript Operations Plugin > Selection Set > Should generate the correct intersection for fragments when using with interfaces with same type 2`] = ` -"export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - - -export type Unnamed_1_Query = { b: Maybe< - | Pick - | Record - > }; - -export type AFragment = Pick; - -export type BFragment = Pick; -" -`; - exports[`TypeScript Operations Plugin > Selection Set > Should have valid __typename usage and split types according to that (with usage) 1`] = ` -"type NetRoute_Ipv4Route_Fragment = ( - { __typename: 'IPV4Route' } - & { - ipv4Address: Ipv4Route['address'], - ipv4Gateway: Ipv4Route['gateway'], - } -); - -type NetRoute_Ipv6Route_Fragment = ( - { __typename: 'IPV6Route' } - & { - ipv6Address: Ipv6Route['address'], - ipv6Gateway: Ipv6Route['gateway'], - } -); +"type NetRoute_Ipv4Route_Fragment = { __typename: 'IPV4Route', ipv4Address: any | null, ipv4Gateway: any | null }; + +type NetRoute_Ipv6Route_Fragment = { __typename: 'IPV6Route', ipv6Address: any | null, ipv6Gateway: any | null }; export type NetRouteFragment = | NetRoute_Ipv4Route_Fragment @@ -223,81 +168,42 @@ export type QqQueryVariables = Exact<{ [key: string]: never; }>; export type QqQuery = { routes: Array< - | ( - { __typename: 'IPV4Route' } - & { - ipv4Address: Ipv4Route['address'], - ipv4Gateway: Ipv4Route['gateway'], - } - ) - | ( - { __typename: 'IPV6Route' } - & { - ipv6Address: Ipv6Route['address'], - ipv6Gateway: Ipv6Route['gateway'], - } - ) + | { __typename: 'IPV4Route', ipv4Address: any | null, ipv4Gateway: any | null } + | { __typename: 'IPV6Route', ipv6Address: any | null, ipv6Gateway: any | null } > }; " `; exports[`TypeScript Operations Plugin > Selection Set > Should have valid __typename usage and split types according to that (with usage) 2`] = ` -"type NetRoute_Ipv4Route_Fragment = ( - { __typename: 'IPV4Route' } - & { - ipv4Address: Ipv4Route['address'], - ipv4Gateway: Ipv4Route['gateway'], - } -); - -type NetRoute_Ipv6Route_Fragment = ( - { __typename: 'IPV6Route' } - & { - ipv6Address: Ipv6Route['address'], - ipv6Gateway: Ipv6Route['gateway'], - } -); +"type NetRoute_Ipv4Route_Fragment = { __typename: 'IPV4Route', ipv4Address: any | null, ipv4Gateway: any | null }; + +type NetRoute_Ipv6Route_Fragment = { __typename: 'IPV6Route', ipv6Address: any | null, ipv6Gateway: any | null }; export type NetRouteFragment = | NetRoute_Ipv4Route_Fragment | NetRoute_Ipv6Route_Fragment ; -export type TestFragment = { - ipv6Address: Ipv6Route['address'], - ipv6Gateway: Ipv6Route['gateway'], - }; +export type TestFragment = { ipv6Address: any | null, ipv6Gateway: any | null }; export type QqQueryVariables = Exact<{ [key: string]: never; }>; export type QqQuery = { routes: Array< - | ( - { __typename: 'IPV4Route' } - & { - ipv4Address: Ipv4Route['address'], - ipv4Gateway: Ipv4Route['gateway'], - } - ) - | ( - { __typename: 'IPV6Route' } - & { - ipv6Address: Ipv6Route['address'], - ipv6Gateway: Ipv6Route['gateway'], - } - ) + | { __typename: 'IPV4Route', ipv4Address: any | null, ipv4Gateway: any | null } + | { __typename: 'IPV6Route', ipv6Address: any | null, ipv6Gateway: any | null } > }; " `; exports[`TypeScript Operations Plugin > Selection Set > Should have valid fragments intersection on different types (with usage) #2498 1`] = ` -"export type TomFragment = Pick; +"export type TomFragment = { id: string, foo: string }; -export type JerryFragment = Pick; +export type JerryFragment = { id: string, bar: string }; -type User_Tom_Fragment = Pick; +type User_Tom_Fragment = { id: string, foo: string }; -type User_Jerry_Fragment = Pick; +type User_Jerry_Fragment = { id: string, bar: string }; export type UserFragment = | User_Tom_Fragment @@ -307,128 +213,9 @@ export type UserFragment = export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; -export type UserQueryQuery = { user: Maybe< - | Pick - | Pick - > }; -" -`; - -exports[`TypeScript Operations Plugin > Union & Interfaces > #4216 - handle fragments against unions and interfaces with flattenGeneratedTypes 1`] = ` -"export type SearchPopularQueryVariables = Exact<{ [key: string]: never; }>; - - -export type SearchPopularQuery = { search: Maybe - | ( - Pick - & { dimension: Maybe> } - ) - >> }; -" -`; - -exports[`TypeScript Operations Plugin > Union & Interfaces > Should handle union selection sets with both FragmentSpreads and InlineFragments 1`] = ` -"export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; - - export type UserQueryQuery = { user: - | Pick - | Pick - | ( - Pick - & { info: Maybe> } - ) - }; - -export type AdditionalInfoFragment = Pick; - -type UserResult1_User_Fragment = Pick; - -type UserResult1_Error3_Fragment = { info: Maybe> }; - -export type UserResult1Fragment = - | UserResult1_User_Fragment - | UserResult1_Error3_Fragment -; - -type UserResult_User_Fragment = Pick; - -type UserResult_Error2_Fragment = Pick; - -export type UserResultFragment = - | UserResult_User_Fragment - | UserResult_Error2_Fragment -; + | { id: string, foo: string } + | { id: string, bar: string } + | null }; " `; - -exports[`TypeScript Operations Plugin > Union & Interfaces > Should handle union selection sets with both FragmentSpreads and InlineFragments with flattenGeneratedTypes 1`] = ` -"export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; - - -export type UserQueryQuery = { user: - | Pick - | Pick - | ( - Pick - & { info: Maybe> } - ) - }; - - function t(q: UserQueryQuery) { - if (q.user) { - if (q.user.__typename === 'User') { - if (q.user.id) { - const u = q.user.login; - } - } - if (q.user.__typename === 'Error2') { - console.log(q.user.message); - } - if (q.user.__typename === 'Error3') { - if (q.user.info) { - console.log(q.user.info.__typename) - } - } - } - }" -`; - -exports[`TypeScript Operations Plugin > Union & Interfaces > Should handle union selection sets with both FragmentSpreads and InlineFragments with flattenGeneratedTypes and directives 1`] = ` -"export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; - - -export type UserQueryQuery = { user: - | Pick< - User, - | 'id' - | 'test2' - | 'login' - | 'test' - > - | Pick - | ( - Pick - & { info: Maybe> } - ) - }; - - function t(q: UserQueryQuery) { - if (q.user) { - if (q.user.__typename === 'User') { - if (q.user.id) { - const u = q.user.login; - } - } - if (q.user.__typename === 'Error2') { - console.log(q.user.message); - } - if (q.user.__typename === 'Error3') { - if (q.user.info) { - console.log(q.user.info.__typename) - } - } - } - }" -`; diff --git a/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts b/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts index d8cdf32c0ec..b3e18d517d8 100644 --- a/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts @@ -70,7 +70,6 @@ describe('extractAllFieldsToTypes: true', () => { it('should extract types from queries', async () => { const config: TypeScriptDocumentsPluginConfig = { - preResolveTypes: true, extractAllFieldsToTypes: true, printFieldsOnNewLines: true, nonOptionalTypename: true, @@ -389,7 +388,6 @@ describe('extractAllFieldsToTypes: true', () => { it('should extract types from multiple fragments', async () => { const config: TypeScriptDocumentsPluginConfig = { - preResolveTypes: true, extractAllFieldsToTypes: true, nonOptionalTypename: true, dedupeOperationSuffix: true, @@ -558,7 +556,6 @@ describe('extractAllFieldsToTypes: true', () => { it('should extract types from multiple fragments (mergeFragmentTypes: true)', async () => { const config: TypeScriptDocumentsPluginConfig = { - preResolveTypes: true, extractAllFieldsToTypes: true, nonOptionalTypename: true, dedupeOperationSuffix: true, @@ -733,7 +730,6 @@ describe('extractAllFieldsToTypes: true', () => { it("should extract types from multiple fragments (inlineFragmentTypes: 'combine')", async () => { const config: TypeScriptDocumentsPluginConfig = { - preResolveTypes: true, extractAllFieldsToTypes: true, nonOptionalTypename: true, dedupeOperationSuffix: true, @@ -977,7 +973,6 @@ describe('extractAllFieldsToTypes: true', () => { it("should extract types from multiple fragments (inlineFragmentTypes: 'mask')", async () => { const config: TypeScriptDocumentsPluginConfig = { - preResolveTypes: true, extractAllFieldsToTypes: true, nonOptionalTypename: true, dedupeOperationSuffix: true, @@ -1217,281 +1212,6 @@ describe('extractAllFieldsToTypes: true', () => { await validate(content, config, complexTestSchemaWithUnionsAndInterfaces); }); - it('should extract types from multiple fragments (preResolveTypes: false)', async () => { - const config: TypeScriptDocumentsPluginConfig = { - preResolveTypes: false, - extractAllFieldsToTypes: true, - nonOptionalTypename: true, - dedupeOperationSuffix: true, - }; - const { content } = await plugin( - complexTestSchemaWithUnionsAndInterfaces, - [{ location: 'test-file.ts', document: fragmentsOnComplexSchema }], - config, - { outputFile: '' }, - ); - expect(content).toMatchInlineSnapshot(` - "export type CallType = - | 'OUTGOING' - | 'INCOMING' - | 'VOICEMAIL' - | 'UNKNOWN'; - - export type ConversationBotSolutionFragment_BotSolution_article_ArchivedArticle = ( - { __typename: 'ArchivedArticle' } - & Pick< - ArchivedArticle, - | 'id' - | 'htmlUrl' - | 'title' - | 'url' - > - ); - - export type ConversationBotSolutionFragment_BotSolution_originatedFrom_EmailInteraction = ( - { __typename: 'EmailInteraction' } - & Pick - ); - - export type ConversationBotSolutionFragment_BotSolution_originatedFrom_CustomChannelInteraction = ( - { __typename: 'CustomChannelInteraction' } - & Pick - ); - - export type ConversationBotSolutionFragment_BotSolution_originatedFrom_TalkInteraction = { __typename: 'TalkInteraction' }; - - export type ConversationBotSolutionFragment_BotSolution_originatedFrom_NativeMessagingInteraction = ( - { __typename: 'NativeMessagingInteraction' } - & Pick - ); - - export type ConversationBotSolutionFragment_BotSolution_originatedFrom_WhatsAppInteraction = ( - { __typename: 'WhatsAppInteraction' } - & Pick - ); - - export type ConversationBotSolutionFragment_BotSolution_originatedFrom_WeChatInteraction = ( - { __typename: 'WeChatInteraction' } - & Pick - ); - - export type ConversationBotSolutionFragment_BotSolution_originatedFrom_NotImplementedOriginatedFrom = { __typename: 'NotImplementedOriginatedFrom' }; - - export type ConversationBotSolutionFragment_BotSolution_originatedFrom = - | ConversationBotSolutionFragment_BotSolution_originatedFrom_EmailInteraction - | ConversationBotSolutionFragment_BotSolution_originatedFrom_CustomChannelInteraction - | ConversationBotSolutionFragment_BotSolution_originatedFrom_TalkInteraction - | ConversationBotSolutionFragment_BotSolution_originatedFrom_NativeMessagingInteraction - | ConversationBotSolutionFragment_BotSolution_originatedFrom_WhatsAppInteraction - | ConversationBotSolutionFragment_BotSolution_originatedFrom_WeChatInteraction - | ConversationBotSolutionFragment_BotSolution_originatedFrom_NotImplementedOriginatedFrom - ; - - export type ConversationBotSolutionFragment = ( - { __typename: 'BotSolution' } - & Pick - & { - article: ConversationBotSolutionFragment_BotSolution_article_ArchivedArticle, - originatedFrom: ConversationBotSolutionFragment_BotSolution_originatedFrom, - } - ); - - export type ConversationGenericCallSummaryFragment = ( - { __typename: 'TalkPublicCallSummary' } - & Pick - ); - - export type ConversationTalkInteractionFragment = ( - { __typename: 'TalkInteraction' } - & Pick - ); - - export type ConversationConversationEventFragment_ConversationEvent_originatedFrom_EmailInteraction = ( - { __typename: 'EmailInteraction' } - & Pick - ); - - export type ConversationConversationEventFragment_ConversationEvent_originatedFrom_CustomChannelInteraction = ( - { __typename: 'CustomChannelInteraction' } - & Pick - ); - - export type ConversationConversationEventFragment_ConversationEvent_originatedFrom_TalkInteraction = { __typename: 'TalkInteraction' }; - - export type ConversationConversationEventFragment_ConversationEvent_originatedFrom_NativeMessagingInteraction = ( - { __typename: 'NativeMessagingInteraction' } - & Pick - ); - - export type ConversationConversationEventFragment_ConversationEvent_originatedFrom_WhatsAppInteraction = ( - { __typename: 'WhatsAppInteraction' } - & Pick - ); - - export type ConversationConversationEventFragment_ConversationEvent_originatedFrom_WeChatInteraction = ( - { __typename: 'WeChatInteraction' } - & Pick - ); - - export type ConversationConversationEventFragment_ConversationEvent_originatedFrom_NotImplementedOriginatedFrom = { __typename: 'NotImplementedOriginatedFrom' }; - - export type ConversationConversationEventFragment_ConversationEvent_originatedFrom = - | ConversationConversationEventFragment_ConversationEvent_originatedFrom_EmailInteraction - | ConversationConversationEventFragment_ConversationEvent_originatedFrom_CustomChannelInteraction - | ConversationConversationEventFragment_ConversationEvent_originatedFrom_TalkInteraction - | ConversationConversationEventFragment_ConversationEvent_originatedFrom_NativeMessagingInteraction - | ConversationConversationEventFragment_ConversationEvent_originatedFrom_WhatsAppInteraction - | ConversationConversationEventFragment_ConversationEvent_originatedFrom_WeChatInteraction - | ConversationConversationEventFragment_ConversationEvent_originatedFrom_NotImplementedOriginatedFrom - ; - - type ConversationConversationEvent_BrokenConversationEvent_Fragment = ( - { __typename: 'BrokenConversationEvent' } - & Pick - & { originatedFrom: ConversationConversationEventFragment_ConversationEvent_originatedFrom } - ); - - type ConversationConversationEvent_BotSolution_Fragment = ( - { __typename: 'BotSolution' } - & Pick - & { originatedFrom: ConversationConversationEventFragment_ConversationEvent_originatedFrom } - ); - - type ConversationConversationEvent_TalkPublicCallSummary_Fragment = ( - { __typename: 'TalkPublicCallSummary' } - & Pick - & { originatedFrom: ConversationConversationEventFragment_ConversationEvent_originatedFrom } - ); - - export type ConversationConversationEventFragment = - | ConversationConversationEvent_BrokenConversationEvent_Fragment - | ConversationConversationEvent_BotSolution_Fragment - | ConversationConversationEvent_TalkPublicCallSummary_Fragment - ; - - type MessageEnvelopeData_EmailInteraction_Fragment = ( - { __typename: 'EmailInteraction' } - & Pick - ); - - type MessageEnvelopeData_CustomChannelInteraction_Fragment = { __typename: 'CustomChannelInteraction' }; - - type MessageEnvelopeData_TalkInteraction_Fragment = { __typename: 'TalkInteraction' }; - - type MessageEnvelopeData_NativeMessagingInteraction_Fragment = { __typename: 'NativeMessagingInteraction' }; - - type MessageEnvelopeData_WhatsAppInteraction_Fragment = { __typename: 'WhatsAppInteraction' }; - - type MessageEnvelopeData_WeChatInteraction_Fragment = { __typename: 'WeChatInteraction' }; - - type MessageEnvelopeData_NotImplementedOriginatedFrom_Fragment = { __typename: 'NotImplementedOriginatedFrom' }; - - export type MessageEnvelopeDataFragment = - | MessageEnvelopeData_EmailInteraction_Fragment - | MessageEnvelopeData_CustomChannelInteraction_Fragment - | MessageEnvelopeData_TalkInteraction_Fragment - | MessageEnvelopeData_NativeMessagingInteraction_Fragment - | MessageEnvelopeData_WhatsAppInteraction_Fragment - | MessageEnvelopeData_WeChatInteraction_Fragment - | MessageEnvelopeData_NotImplementedOriginatedFrom_Fragment - ; - - export type AnyChannelOriginatedFromFragment = ( - { __typename: 'CustomChannelInteraction' } - & Pick - ); - - type ConversationOriginatedFrom_EmailInteraction_Fragment = ( - { __typename: 'EmailInteraction' } - & Pick - ); - - type ConversationOriginatedFrom_CustomChannelInteraction_Fragment = ( - { __typename: 'CustomChannelInteraction' } - & Pick - ); - - type ConversationOriginatedFrom_TalkInteraction_Fragment = { __typename: 'TalkInteraction' }; - - type ConversationOriginatedFrom_NativeMessagingInteraction_Fragment = ( - { __typename: 'NativeMessagingInteraction' } - & Pick - ); - - type ConversationOriginatedFrom_WhatsAppInteraction_Fragment = ( - { __typename: 'WhatsAppInteraction' } - & Pick - ); - - type ConversationOriginatedFrom_WeChatInteraction_Fragment = ( - { __typename: 'WeChatInteraction' } - & Pick - ); - - type ConversationOriginatedFrom_NotImplementedOriginatedFrom_Fragment = { __typename: 'NotImplementedOriginatedFrom' }; - - export type ConversationOriginatedFromFragment = - | ConversationOriginatedFrom_EmailInteraction_Fragment - | ConversationOriginatedFrom_CustomChannelInteraction_Fragment - | ConversationOriginatedFrom_TalkInteraction_Fragment - | ConversationOriginatedFrom_NativeMessagingInteraction_Fragment - | ConversationOriginatedFrom_WhatsAppInteraction_Fragment - | ConversationOriginatedFrom_WeChatInteraction_Fragment - | ConversationOriginatedFrom_NotImplementedOriginatedFrom_Fragment - ; - - export type ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_EmailInteraction = ( - { __typename: 'EmailInteraction' } - & Pick - ); - - export type ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_CustomChannelInteraction = ( - { __typename: 'CustomChannelInteraction' } - & Pick - ); - - export type ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_TalkInteraction = ( - { __typename: 'TalkInteraction' } - & Pick - ); - - export type ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_NativeMessagingInteraction = ( - { __typename: 'NativeMessagingInteraction' } - & Pick - ); - - export type ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_WhatsAppInteraction = ( - { __typename: 'WhatsAppInteraction' } - & Pick - ); - - export type ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_WeChatInteraction = ( - { __typename: 'WeChatInteraction' } - & Pick - ); - - export type ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_NotImplementedOriginatedFrom = { __typename: 'NotImplementedOriginatedFrom' }; - - export type ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom = - | ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_EmailInteraction - | ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_CustomChannelInteraction - | ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_TalkInteraction - | ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_NativeMessagingInteraction - | ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_WhatsAppInteraction - | ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_WeChatInteraction - | ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom_NotImplementedOriginatedFrom - ; - - export type ConversationTalkPublicCallSummaryFragment = ( - { __typename: 'TalkPublicCallSummary' } - & Pick - & { originatedFrom: ConversationTalkPublicCallSummaryFragment_TalkPublicCallSummary_originatedFrom } - ); - " - `); - - await validate(content, config, complexTestSchemaWithUnionsAndInterfaces); - }); it('fields with shared types and no fragments should use the shared type interface name', async () => { const nestedInterfacesSchema = buildSchema(/* GraphQL */ ` type Query { @@ -1538,7 +1258,6 @@ describe('extractAllFieldsToTypes: true', () => { `); const config: TypeScriptDocumentsPluginConfig = { - preResolveTypes: true, extractAllFieldsToTypes: true, nonOptionalTypename: true, dedupeOperationSuffix: true, @@ -1640,7 +1359,6 @@ describe('extractAllFieldsToTypes: true', () => { `); const config: TypeScriptDocumentsPluginConfig = { - preResolveTypes: true, extractAllFieldsToTypes: true, nonOptionalTypename: true, dedupeOperationSuffix: true, @@ -1750,7 +1468,6 @@ describe('extractAllFieldsToTypes: true', () => { `); const config: TypeScriptDocumentsPluginConfig = { - preResolveTypes: true, extractAllFieldsToTypes: true, nonOptionalTypename: true, dedupeOperationSuffix: true, @@ -1828,7 +1545,6 @@ describe('extractAllFieldsToTypes: true', () => { `); const config: TypeScriptDocumentsPluginConfig = { - preResolveTypes: true, extractAllFieldsToTypes: true, nonOptionalTypename: true, dedupeOperationSuffix: true, diff --git a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts index b0fa860ef10..2847de13cda 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts @@ -34,73 +34,17 @@ describe('TypeScript Operations Plugin', () => { } } `); - const config = { noExport: true, preResolveTypes: false }; const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { noExport: true }, + { outputFile: '' }, ); expect(content).not.toContain('export'); await validate(content); }); - it('Should handle "namespacedImportName" and add it when specified', async () => { - const ast = parse(/* GraphQL */ ` - query notifications { - notifications { - id - - ... on TextNotification { - text - textAlias: text - } - - ... on TextNotification { - text - } - - ... on ImageNotification { - imageUrl - metadata { - created: createdBy - } - } - } - } - `); - const config = { preResolveTypes: false, namespacedImportName: 'Types' }; - const { content } = await plugin( - schema, - [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, - ); - - expect(content).toMatchInlineSnapshot(` - "export type NotificationsQueryVariables = Exact<{ [key: string]: never; }>; - - - export type NotificationsQuery = { notifications: Array< - | ( - Pick - & { textAlias: Types.TextNotification['text'] } - ) - | ( - Pick - & { metadata: { created: Types.ImageMetadata['createdBy'] } } - ) - > }; - " - `); - await validate(content); - }); - it('Can merge an inline fragment with a spread', async () => { const testSchema = buildSchema(/* GraphQL */ ` interface Comment { @@ -148,9 +92,7 @@ describe('TypeScript Operations Plugin', () => { testSchema, [{ location: 'test-file.ts', document: ast }], {}, - { - outputFile: '', - }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type PostFragment = { id: string, comments: Array< @@ -166,67 +108,6 @@ describe('TypeScript Operations Plugin', () => { `); }); - it('Should handle "namespacedImportName" and "preResolveTypes" together', async () => { - const testSchema = buildSchema(/* GraphQL */ ` - type Query { - f: E - user: User! - } - - enum E { - A - B - } - - scalar JSON - - type User { - id: ID! - f: E - j: JSON - } - `); - const ast = parse(/* GraphQL */ ` - query test { - f - user { - id - f - j - } - } - `); - const config = { namespacedImportName: 'Types', preResolveTypes: true }; - const { content } = await plugin( - testSchema, - [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, - ); - - expect(content).toMatchInlineSnapshot( - ` - "export type E = - | 'A' - | 'B'; - - export type TestQueryVariables = Exact<{ [key: string]: never; }>; - - - export type TestQuery = { f: Types.E | null, user: { id: string, f: Types.E | null, j: any | null } }; - " - `, - ); - - expect(content).toBeSimilarStringTo( - `export type TestQuery = { __typename?: 'Query', f: Types.E | null, user: { __typename?: 'User', id: string, f: Types.E | null, j: any | null } };`, - ); - - await validate(content); - }); - it('Should generate the correct output when using immutableTypes config', async () => { const ast = parse(/* GraphQL */ ` query notifications { @@ -246,18 +127,15 @@ describe('TypeScript Operations Plugin', () => { } } `); - const config = { - preResolveTypes: false, - namingConvention: 'change-case-all#lowerCase', - immutableTypes: true, - }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, { - outputFile: '', + namingConvention: 'change-case-all#lowerCase', + immutableTypes: true, }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` @@ -265,11 +143,8 @@ describe('TypeScript Operations Plugin', () => { export type notificationsquery = { readonly notifications: ReadonlyArray< - | Pick - | ( - Pick - & { readonly metadata: Pick } - ) + | { readonly text: string, readonly id: string } + | { readonly imageUrl: string, readonly id: string, readonly metadata: { readonly createdBy: string } } > }; " `); @@ -332,7 +207,6 @@ describe('TypeScript Operations Plugin', () => { schema, [{ location: '', document: fragment }], { - preResolveTypes: true, maybeValue: "T | 'specialType'", }, { @@ -381,12 +255,9 @@ describe('TypeScript Operations Plugin', () => { schema, [{ location: '', document: fragment }], { - preResolveTypes: true, allowUndefinedQueryVariables: true, }, - { - outputFile: 'graphql.ts', - }, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` @@ -401,41 +272,6 @@ describe('TypeScript Operations Plugin', () => { }); }); - describe('Scalars', () => { - it('Should include scalars when doing pick', async () => { - const testSchema = buildSchema(/* GraphQL */ ` - scalar Date - type Query { - me: User - } - type User { - id: ID! - joinDate: Date! - } - `); - - const doc = parse(/* GraphQL */ ` - query { - me { - id - joinDate - } - } - `); - const config = { preResolveTypes: false }; - const { content } = await plugin( - testSchema, - [{ location: 'test-file.ts', document: doc }], - config, - { - outputFile: '', - }, - ); - expect(content).toContain(`Pick`); - await validate(content); - }); - }); - describe('Custom Operation Result Name Suffix', () => { it('Should generate custom operation result name', async () => { const ast = parse(/* GraphQL */ ` @@ -456,17 +292,25 @@ describe('TypeScript Operations Plugin', () => { } } `); - const config = { - operationResultSuffix: 'Result', - preResolveTypes: false, - }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { operationResultSuffix: 'Result' }, + { outputFile: '' }, + ); + + expect(content).toMatchInlineSnapshot( + ` + "export type NotificationsQueryVariables = Exact<{ [key: string]: never; }>; + + + export type NotificationsQueryResult = { notifications: Array< + | { text: string, id: string } + | { imageUrl: string, id: string, metadata: { createdBy: string } } + > }; + " + `, ); expect(content).toMatchInlineSnapshot(` @@ -474,11 +318,8 @@ describe('TypeScript Operations Plugin', () => { export type NotificationsQueryResult = { notifications: Array< - | Pick - | ( - Pick - & { metadata: Pick } - ) + | { text: string, id: string } + | { imageUrl: string, id: string, metadata: { createdBy: string } } > }; " `); @@ -507,17 +348,12 @@ describe('TypeScript Operations Plugin', () => { } } `); - const config = { - preResolveTypes: false, - namingConvention: 'change-case-all#lowerCase', - }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { namingConvention: 'change-case-all#lowerCase' }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` @@ -525,11 +361,8 @@ describe('TypeScript Operations Plugin', () => { export type notificationsquery = { notifications: Array< - | Pick - | ( - Pick - & { metadata: Pick } - ) + | { text: string, id: string } + | { imageUrl: string, id: string, metadata: { createdBy: string } } > }; " `); @@ -556,33 +389,26 @@ describe('TypeScript Operations Plugin', () => { } `); - const config = { - preResolveTypes: false, - typesPrefix: 'i', - namingConvention: 'change-case-all#lowerCase', - }; const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { typesPrefix: 'i', namingConvention: 'change-case-all#lowerCase' }, + { outputFile: '' }, ); - expect(content).toMatchInlineSnapshot(` + expect(content).toMatchInlineSnapshot( + ` "export type inotificationsqueryvariables = Exact<{ [key: string]: never; }>; export type inotificationsquery = { notifications: Array< - | Pick - | ( - Pick - & { metadata: Pick } - ) + | { text: string, id: string } + | { imageUrl: string, id: string, metadata: { createdBy: string } } > }; " - `); + `, + ); + await validate(content); }); @@ -710,7 +536,7 @@ describe('TypeScript Operations Plugin', () => { await plugin( schema, [{ location: 'test-file.ts', document: ast3 }], - { dedupeOperationSuffix: true, preResolveTypes: false }, + { dedupeOperationSuffix: true }, { outputFile: '' }, ) ).content; @@ -719,28 +545,13 @@ describe('TypeScript Operations Plugin', () => { export type NotificationsQuery = { notifications: Array< - | Pick - | Pick - > }; - - export type MyFragment = { notifications: Array< - | Pick - | Pick - > }; - " - `); - expect(withUsage).toMatchInlineSnapshot(` - "export type NotificationsQueryVariables = Exact<{ [key: string]: never; }>; - - - export type NotificationsQuery = { notifications: Array< - | Pick - | Pick + | { id: string } + | { id: string } > }; export type MyFragment = { notifications: Array< - | Pick - | Pick + | { id: string } + | { id: string } > }; " `); @@ -787,31 +598,19 @@ describe('TypeScript Operations Plugin', () => { `); expect( - ( - await plugin( - schema, - [{ location: 'test-file.ts', document: ast }], - { preResolveTypes: false }, - { outputFile: '' }, - ) - ).content, + (await plugin(schema, [{ location: 'test-file.ts', document: ast }], {}, { outputFile: '' })) + .content, ).toContain('export type NotificationsQueryQuery ='); expect( - ( - await plugin( - schema, - [{ location: 'test-file.ts', document: ast }], - { preResolveTypes: false }, - { outputFile: '' }, - ) - ).content, + (await plugin(schema, [{ location: 'test-file.ts', document: ast }], {}, { outputFile: '' })) + .content, ).toContain('export type MyFragmentFragment ='); expect( ( await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { omitOperationSuffix: true, preResolveTypes: false }, + { omitOperationSuffix: true }, { outputFile: '' }, ) ).content, @@ -821,7 +620,7 @@ describe('TypeScript Operations Plugin', () => { await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { omitOperationSuffix: true, preResolveTypes: false }, + { omitOperationSuffix: true }, { outputFile: '' }, ) ).content, @@ -831,7 +630,7 @@ describe('TypeScript Operations Plugin', () => { await plugin( schema, [{ location: 'test-file.ts', document: ast2 }], - { omitOperationSuffix: true, preResolveTypes: false }, + { omitOperationSuffix: true }, { outputFile: '' }, ) ).content, @@ -841,7 +640,7 @@ describe('TypeScript Operations Plugin', () => { await plugin( schema, [{ location: 'test-file.ts', document: ast2 }], - { omitOperationSuffix: true, preResolveTypes: false }, + { omitOperationSuffix: true }, { outputFile: '' }, ) ).content, @@ -851,7 +650,7 @@ describe('TypeScript Operations Plugin', () => { await plugin( schema, [{ location: 'test-file.ts', document: ast2 }], - { omitOperationSuffix: false, preResolveTypes: false }, + { omitOperationSuffix: false }, { outputFile: '' }, ) ).content, @@ -861,7 +660,7 @@ describe('TypeScript Operations Plugin', () => { await plugin( schema, [{ location: 'test-file.ts', document: ast2 }], - { omitOperationSuffix: false, preResolveTypes: false }, + { omitOperationSuffix: false }, { outputFile: '' }, ) ).content, @@ -871,7 +670,7 @@ describe('TypeScript Operations Plugin', () => { await plugin( schema, [{ location: 'test-file.ts', document: ast3 }], - { omitOperationSuffix: true, preResolveTypes: false }, + { omitOperationSuffix: true }, { outputFile: '' }, ) ).content; @@ -880,28 +679,13 @@ describe('TypeScript Operations Plugin', () => { export type Notifications = { notifications: Array< - | Pick - | Pick - > }; - - export type My = { notifications: Array< - | Pick - | Pick - > }; - " - `); - expect(withUsage).toMatchInlineSnapshot(` - "export type NotificationsVariables = Exact<{ [key: string]: never; }>; - - - export type Notifications = { notifications: Array< - | Pick - | Pick + | { id: string } + | { id: string } > }; export type My = { notifications: Array< - | Pick - | Pick + | { id: string } + | { id: string } > }; " `); @@ -925,17 +709,12 @@ describe('TypeScript Operations Plugin', () => { } } `); - const config = { - skipTypeNameForRoot: true, - preResolveTypes: false, - }; + const { content } = await plugin( testSchema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypeNameForRoot: true }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot( @@ -943,7 +722,7 @@ describe('TypeScript Operations Plugin', () => { "export type Q1QueryVariables = Exact<{ [key: string]: never; }>; - export type Q1Query = { test: Maybe> }; + export type Q1Query = { test: { foo: string | null } | null }; " `, ); @@ -967,18 +746,15 @@ describe('TypeScript Operations Plugin', () => { } } `); - const config = { - nonOptionalTypename: true, - skipTypeNameForRoot: true, - preResolveTypes: false, - }; + const { content } = await plugin( testSchema, [{ location: 'test-file.ts', document: ast }], - config, { - outputFile: '', + nonOptionalTypename: true, + skipTypeNameForRoot: true, }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot( @@ -986,10 +762,7 @@ describe('TypeScript Operations Plugin', () => { "export type Q1QueryVariables = Exact<{ [key: string]: never; }>; - export type Q1Query = { test: Maybe<( - { __typename: 'Test' } - & Pick - )> }; + export type Q1Query = { test: { __typename: 'Test', foo: string | null } | null }; " `, ); @@ -1014,18 +787,15 @@ describe('TypeScript Operations Plugin', () => { } } `); - const config = { - nonOptionalTypename: true, - skipTypeNameForRoot: true, - preResolveTypes: false, - }; + const { content } = await plugin( testSchema, [{ location: 'test-file.ts', document: ast }], - config, { - outputFile: '', + nonOptionalTypename: true, + skipTypeNameForRoot: true, }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot( @@ -1033,20 +803,14 @@ describe('TypeScript Operations Plugin', () => { "export type Q1QueryVariables = Exact<{ [key: string]: never; }>; - export type Q1Query = ( - { __typename: 'Query' } - & { test: Maybe<( - { __typename: 'Test' } - & Pick - )> } - ); + export type Q1Query = { __typename: 'Query', test: { __typename: 'Test', foo: string | null } | null }; " `, ); await validate(content); }); - it('Should add __typename correctly with nonOptionalTypename=false,skipTypename=true,preResolveTypes=true and explicit field', async () => { + it('Should add __typename correctly with nonOptionalTypename=false,skipTypename=true and explicit field', async () => { const testSchema = buildSchema(/* GraphQL */ ` type Search { search: [SearchResult!]! @@ -1097,17 +861,15 @@ describe('TypeScript Operations Plugin', () => { } } `); - const config = { - nonOptionalTypename: false, - skipTypename: true, - }; + const { content } = await plugin( testSchema, [{ location: 'test-file.ts', document: ast }], - config, { - outputFile: '', + nonOptionalTypename: false, + skipTypename: true, }, + { outputFile: '' }, ); expect(content).toContain( @@ -1133,14 +895,12 @@ export type Q2Query = { search: Array< dummy } `); - const config = { skipTypename: true, preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: true }, + { outputFile: '' }, ); expect(content).not.toContain(`__typename`); @@ -1179,25 +939,17 @@ export type Q2Query = { search: Array< } } `); - const config = { preResolveTypes: false }; + const { content } = await plugin( testSchema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` - "type Node_A_Fragment = ( - { __typename: 'A' } - & Pick - ); + "type Node_A_Fragment = { __typename: 'A', id: string }; - type Node_B_Fragment = ( - { __typename: 'B' } - & Pick - ); + type Node_B_Fragment = { __typename: 'B', id: string }; export type NodeFragment = | Node_A_Fragment @@ -1207,16 +959,10 @@ export type Q2Query = { search: Array< export type TestQueryVariables = Exact<{ [key: string]: never; }>; - export type TestQuery = { some: Maybe< - | ( - { __typename: 'A' } - & Pick - ) - | ( - { __typename: 'B' } - & Pick - ) - > }; + export type TestQuery = { some: + | { __typename: 'A', id: string } + | { __typename: 'B', id: string } + | null }; " `); await validate(content); @@ -1229,78 +975,42 @@ export type Q2Query = { search: Array< dummy } `); - const config = { preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = ( - Pick - & { type: 'Query' } - ); + export type Unnamed_1_Query = { dummy: string | null, type: 'Query' }; " `); await validate(content); }); - it('Should add aliased __typename correctly with preResovleTypes', async () => { + it('Should add __typename as non-optional when explicitly specified', async () => { const ast = parse(/* GraphQL */ ` query { - type: __typename + __typename dummy } `); - const config = { preResolveTypes: true }; - const { content } = await plugin( - schema, - [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, - ); - expect(content).toMatchInlineSnapshot(` - "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - - - export type Unnamed_1_Query = { dummy: string | null, type: 'Query' }; - " - `); - await validate(content); - }); - it('Should add __typename as non-optional when explicitly specified', async () => { - const ast = parse(/* GraphQL */ ` - query { - __typename - dummy - } - `); - const config = { preResolveTypes: false }; const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = ( - { __typename: 'Query' } - & Pick - ); + export type Unnamed_1_Query = { __typename: 'Query', dummy: string | null }; " `); await validate(content); @@ -1312,48 +1022,18 @@ export type Q2Query = { search: Array< dummy } `); - const config = { nonOptionalTypename: true, preResolveTypes: false }; - const { content } = await plugin( - schema, - [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, - ); - expect(content).toMatchInlineSnapshot(` - "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - - - export type Unnamed_1_Query = ( - { __typename: 'Query' } - & Pick - ); - " - `); - await validate(content); - }); - it('Should add __typename as optional when its not specified', async () => { - const ast = parse(/* GraphQL */ ` - query { - dummy - } - `); - const config = { preResolveTypes: false }; const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { nonOptionalTypename: true }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = Pick; + export type Unnamed_1_Query = { __typename: 'Query', dummy: string | null }; " `); await validate(content); @@ -1366,30 +1046,25 @@ export type Q2Query = { search: Array< dummy } `); - const config = { skipTypename: true, preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: true }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = ( - { __typename: 'Query' } - & Pick - ); + export type Unnamed_1_Query = { __typename: 'Query', dummy: string | null }; " `); await validate(content); }); - it('Should add __typename correctly when unions are in use', async () => { + it('Should add __typename correctly when unions are in use and nonOptionalTypename=true', async () => { const ast = parse(/* GraphQL */ ` query unionTest { unionTest { @@ -1403,29 +1078,27 @@ export type Q2Query = { search: Array< } } `); - const config = { preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { nonOptionalTypename: true }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type UnionTestQueryVariables = Exact<{ [key: string]: never; }>; - export type UnionTestQuery = { unionTest: Maybe< - | Pick - | Pick - > }; + export type UnionTestQuery = { __typename: 'Query', unionTest: + | { __typename: 'User', id: string } + | { __typename: 'Profile', age: number | null } + | null }; " `); await validate(content); }); - it('Should add __typename correctly when interfaces are in use', async () => { + it('Should add __typename correctly when interfaces are in use and nonOptionalTypename=true', async () => { const ast = parse(/* GraphQL */ ` query notifications { notifications { @@ -1444,25 +1117,20 @@ export type Q2Query = { search: Array< } } `); - const config = { preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { nonOptionalTypename: true }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type NotificationsQueryVariables = Exact<{ [key: string]: never; }>; - export type NotificationsQuery = { notifications: Array< - | Pick - | ( - Pick - & { metadata: Pick } - ) + export type NotificationsQuery = { __typename: 'Query', notifications: Array< + | { __typename: 'TextNotification', text: string, id: string } + | { __typename: 'ImageNotification', imageUrl: string, id: string, metadata: { __typename: 'ImageMetadata', createdBy: string } } > }; " `); @@ -1482,28 +1150,20 @@ export type Q2Query = { search: Array< } } `); - const config = { preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type NotificationsQueryVariables = Exact<{ [key: string]: never; }>; export type NotificationsQuery = { notifications: Array< - | ( - { __typename: 'TextNotification' } - & Pick - ) - | ( - { __typename: 'ImageNotification' } - & Pick - ) + | { __typename: 'TextNotification', text: string } + | { __typename: 'ImageNotification', imageUrl: string } > }; " `); @@ -1523,29 +1183,21 @@ export type Q2Query = { search: Array< } } `); - const config = { preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type UnionTestQueryVariables = Exact<{ [key: string]: never; }>; - export type UnionTestQuery = { unionTest: Maybe< - | ( - { __typename: 'User' } - & Pick - ) - | ( - { __typename: 'Profile' } - & Pick - ) - > }; + export type UnionTestQuery = { unionTest: + | { __typename: 'User', email: string } + | { __typename: 'Profile', firstName: string } + | null }; " `); await validate(content); @@ -1559,27 +1211,25 @@ export type Q2Query = { search: Array< dummy } `); - const config = { skipTypename: true, preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: true }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = Pick; + export type Unnamed_1_Query = { dummy: string | null }; " `); expect(content).toMatchInlineSnapshot(` "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = Pick; + export type Unnamed_1_Query = { dummy: string | null }; " `); await validate(content); @@ -1595,62 +1245,60 @@ export type Q2Query = { search: Array< dummy } `); - const config = { skipTypename: true, preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: true }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = Pick; + export type Unnamed_1_Query = { dummy: string | null }; export type Unnamed_2_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_2_Query = Pick; + export type Unnamed_2_Query = { dummy: string | null }; " `); expect(content).toMatchInlineSnapshot(` "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = Pick; + export type Unnamed_1_Query = { dummy: string | null }; export type Unnamed_2_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_2_Query = Pick; + export type Unnamed_2_Query = { dummy: string | null }; " `); expect(content).toMatchInlineSnapshot(` "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = Pick; + export type Unnamed_1_Query = { dummy: string | null }; export type Unnamed_2_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_2_Query = Pick; + export type Unnamed_2_Query = { dummy: string | null }; " `); expect(content).toMatchInlineSnapshot(` "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = Pick; + export type Unnamed_1_Query = { dummy: string | null }; export type Unnamed_2_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_2_Query = Pick; + export type Unnamed_2_Query = { dummy: string | null }; " `); await validate(content); @@ -1664,7 +1312,6 @@ export type Q2Query = { search: Array< test } `); - const config = { preResolveTypes: false }; try { await plugin( @@ -1674,7 +1321,7 @@ export type Q2Query = { search: Array< } `), [{ location: 'test-file.ts', document: ast }], - config, + {}, { outputFile: '' }, ); expect(true).toBeFalsy(); @@ -1723,14 +1370,12 @@ export type Q2Query = { search: Array< } } `); - const config = { preResolveTypes: false }; + const { content } = await plugin( testSchema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); const usage = ` @@ -1770,14 +1415,12 @@ export type Q2Query = { search: Array< } } `); - const config = { preResolveTypes: false }; + const { content } = await plugin( testSchema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); await validate(content); expect(mergeOutputs([content])).toMatchSnapshot(); @@ -1808,14 +1451,12 @@ export type Q2Query = { search: Array< name } `); - const config = { preResolveTypes: false }; + const { content } = await plugin( testSchema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); await validate(content); expect(mergeOutputs([content])).toMatchSnapshot(); @@ -1844,14 +1485,12 @@ export type Q2Query = { search: Array< name } `); - const config = { preResolveTypes: false }; + const { content } = await plugin( testSchema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); await validate(content); expect(mergeOutputs([content])).toMatchSnapshot(); @@ -1883,14 +1522,12 @@ export type Q2Query = { search: Array< } } `); - const config = { preResolveTypes: false }; + const { content } = await plugin( testSchema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); await validate( content, @@ -1944,14 +1581,12 @@ export type Q2Query = { search: Array< } } `); - const config = { preResolveTypes: false }; + const { content } = await plugin( testSchema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); await validate( @@ -2010,14 +1645,12 @@ export type Q2Query = { search: Array< } } `); - const config = { preResolveTypes: false }; + const { content } = await plugin( testSchema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); const usage = ` @@ -2053,32 +1686,24 @@ export type Q2Query = { search: Array< } } `); - const config = { skipTypename: true, preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: true }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type Role = | 'USER' | 'ADMIN'; - export type UserFieldsFragment = ( - Pick - & { profile: Maybe> } - ); + export type UserFieldsFragment = { id: string, username: string, role: Role | null, profile: { age: number | null } | null }; export type MeQueryVariables = Exact<{ [key: string]: never; }>; - export type MeQuery = { me: Maybe<( - Pick - & { profile: Maybe> } - )> }; + export type MeQuery = { me: { id: string, username: string, role: Role | null, profile: { age: number | null } | null } | null }; " `); await validate(content); @@ -2100,29 +1725,21 @@ export type Q2Query = { search: Array< } } `); - const config = { skipTypename: true, preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: true }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` - "export type UserFieldsFragment = ( - Pick - & { profile: Maybe> } - ); + "export type UserFieldsFragment = { id: string, profile: { age: number | null } | null }; export type MeQueryVariables = Exact<{ [key: string]: never; }>; - export type MeQuery = { me: Maybe<( - Pick - & { profile: Maybe> } - )> }; + export type MeQuery = { me: { username: string, id: string, profile: { age: number | null } | null } | null }; " `); await validate(content); @@ -2148,56 +1765,23 @@ export type Q2Query = { search: Array< } } `); - const config = { skipTypename: false, preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: false }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` - "export type UserFieldsFragment = Pick; - - export type UserProfileFragment = { profile: Maybe> }; - - export type MeQueryVariables = Exact<{ [key: string]: never; }>; - - - export type MeQuery = { me: Maybe<( - Pick - & { profile: Maybe> } - )> }; - " - `); - expect(content).toMatchInlineSnapshot(` - "export type UserFieldsFragment = Pick; - - export type UserProfileFragment = { profile: Maybe> }; - - export type MeQueryVariables = Exact<{ [key: string]: never; }>; - - - export type MeQuery = { me: Maybe<( - Pick - & { profile: Maybe> } - )> }; - " - `); - expect(content).toMatchInlineSnapshot(` - "export type UserFieldsFragment = Pick; + "export type UserFieldsFragment = { id: string }; - export type UserProfileFragment = { profile: Maybe> }; + export type UserProfileFragment = { profile: { age: number | null } | null }; export type MeQueryVariables = Exact<{ [key: string]: never; }>; - export type MeQuery = { me: Maybe<( - Pick - & { profile: Maybe> } - )> }; + export type MeQuery = { me: { username: string, id: string, profile: { age: number | null } | null } | null }; " `); await validate(content); @@ -2242,28 +1826,26 @@ export type Q2Query = { search: Array< y } `); - const config = { preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { b: Maybe< - | Pick - | Pick - > }; + export type Unnamed_1_Query = { b: + | { id: string, x: number } + | { id: string, y: number } + | null }; - export type AFragment = Pick; + export type AFragment = { id: string, x: number }; - export type BFragment = Pick; + export type BFragment = { id: string, y: number }; " `); await validate(content); @@ -2311,26 +1893,24 @@ export type Q2Query = { search: Array< bar } `); - const config = { preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { myType: Pick }; + export type Unnamed_1_Query = { myType: { foo: string, bar: string, test: string } }; - export type CFragment = Pick; + export type CFragment = { test: string }; - export type AFragment = Pick; + export type AFragment = { foo: string }; - export type BFragment = Pick; + export type BFragment = { bar: string }; " `); await validate(content); @@ -2373,32 +1953,29 @@ export type Q2Query = { search: Array< x } `); - const config = { preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { b: Maybe< - | Pick + export type Unnamed_1_Query = { b: + | { id: string, x: number } | Record - > }; + | null }; - export type AFragment = Pick; + export type AFragment = { id: string }; - export type BFragment = Pick; + export type BFragment = { x: number }; " `); - validateTs(mergeOutputs([content]), config); - expect(mergeOutputs([content])).toMatchSnapshot(); + validateTs(mergeOutputs([content]), {}); }); it('Should support interfaces correctly when used with inline fragments', async () => { @@ -2421,25 +1998,19 @@ export type Q2Query = { search: Array< } `); - const config = { preResolveTypes: false }; const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type NotificationsQueryVariables = Exact<{ [key: string]: never; }>; export type NotificationsQuery = { notifications: Array< - | Pick - | ( - Pick - & { metadata: Pick } - ) + | { text: string, id: string } + | { imageUrl: string, id: string, metadata: { createdBy: string } } > }; " `); @@ -2460,24 +2031,22 @@ export type Q2Query = { search: Array< } } `); - const config = { preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type UnionTestQueryVariables = Exact<{ [key: string]: never; }>; - export type UnionTestQuery = { unionTest: Maybe< - | Pick - | Pick - > }; + export type UnionTestQuery = { unionTest: + | { id: string } + | { age: number | null } + | null }; " `); await validate(content); @@ -2501,14 +2070,12 @@ export type Q2Query = { search: Array< } } `); - const config = { preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` @@ -2516,8 +2083,8 @@ export type Q2Query = { search: Array< export type UnionTestQuery = { mixedNotifications: Array< - | Pick - | Pick + | { id: string, text: string } + | { id: string, imageUrl: string } > }; " `); @@ -2546,14 +2113,12 @@ export type Q2Query = { search: Array< } } `); - const config = { preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` @@ -2561,9 +2126,9 @@ export type Q2Query = { search: Array< export type UnionTestQuery = { search: Array< - | Pick - | Pick - | Pick + | { id: string, text: string } + | { id: string, imageUrl: string } + | { id: string } > }; " `); @@ -2582,18 +2147,12 @@ export type Q2Query = { search: Array< id } `); - const config = { - preResolveTypes: true, - mergeFragmentTypes: true, - namingConvention: 'keep', - }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { mergeFragmentTypes: true, namingConvention: 'keep' }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` @@ -2617,18 +2176,12 @@ export type Q2Query = { search: Array< } } `); - const config = { - preResolveTypes: true, - mergeFragmentTypes: true, - namingConvention: 'keep', - }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { mergeFragmentTypes: true, namingConvention: 'keep' }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` @@ -2685,18 +2238,12 @@ export type Q2Query = { search: Array< } } `); - const config = { - preResolveTypes: true, - mergeFragmentTypes: true, - namingConvention: 'keep', - }; + const { content } = await plugin( testSchema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { mergeFragmentTypes: true, namingConvention: 'keep' }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` @@ -2723,18 +2270,12 @@ export type Q2Query = { search: Array< } } `); - const config = { - preResolveTypes: true, - mergeFragmentTypes: true, - namingConvention: 'keep', - }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { mergeFragmentTypes: true, namingConvention: 'keep' }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` @@ -2756,19 +2297,12 @@ export type Q2Query = { search: Array< id } `); - const config = { - preResolveTypes: true, - skipTypename: true, - mergeFragmentTypes: true, - namingConvention: 'keep', - }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: true, mergeFragmentTypes: true, namingConvention: 'keep' }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` @@ -2792,19 +2326,12 @@ export type Q2Query = { search: Array< } } `); - const config = { - preResolveTypes: true, - skipTypename: true, - mergeFragmentTypes: true, - namingConvention: 'keep', - }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: true, mergeFragmentTypes: true, namingConvention: 'keep' }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` @@ -2833,18 +2360,12 @@ export type Q2Query = { search: Array< id } `); - const config = { - preResolveTypes: true, - mergeFragmentTypes: true, - inlineFragmentTypes: 'mask', - } as const; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { mergeFragmentTypes: true, inlineFragmentTypes: 'mask' }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` @@ -2883,23 +2404,18 @@ export type Q2Query = { search: Array< } } `); - const config = { skipTypename: true, preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: true }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type CurrentUserQueryVariables = Exact<{ [key: string]: never; }>; - export type CurrentUserQuery = { me: Maybe<( - Pick - & { profile: Maybe> } - )> }; + export type CurrentUserQuery = { me: { username: string, id: string, profile: { age: number | null } | null } | null }; " `); @@ -2923,14 +2439,24 @@ export type Q2Query = { search: Array< } } `); - const config = { skipTypename: true, preResolveTypes: false }; + const { content } = await plugin( gitHuntSchema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: true }, + { outputFile: '' }, + ); + + expect(content).toMatchInlineSnapshot( + ` + "export type MeQueryVariables = Exact<{ + repoFullName: string; + }>; + + + export type MeQuery = { currentUser: { login: string, html_url: string } | null, entry: { id: number, createdAt: number, postedBy: { login: string, html_url: string } } | null }; + " + `, ); expect(content).toMatchInlineSnapshot(` @@ -2939,19 +2465,13 @@ export type Q2Query = { search: Array< }>; - export type MeQuery = { - currentUser: Maybe>, - entry: Maybe<( - Pick - & { postedBy: Pick } - )>, - }; + export type MeQuery = { currentUser: { login: string, html_url: string } | null, entry: { id: number, createdAt: number, postedBy: { login: string, html_url: string } } | null }; " `); await validate(content); }); - it('Should build a basic selection set based on basic query on GitHub schema with preResolveTypes=true', async () => { + it('Should build a basic selection set based on basic query on GitHub schema', async () => { const ast = parse(/* GraphQL */ ` query me($repoFullName: String!) { currentUser { @@ -2968,14 +2488,12 @@ export type Q2Query = { search: Array< } } `); - const config = { preResolveTypes: true }; + const { content } = await plugin( gitHuntSchema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` @@ -2990,7 +2508,7 @@ export type Q2Query = { search: Array< await validate(content); }); - it('Should produce valid output with preResolveTypes=true and enums', async () => { + it('Should produce valid output with enums', async () => { const ast = parse(/* GraphQL */ ` query test { info { @@ -3024,14 +2542,12 @@ export type Q2Query = { search: Array< info: Information } `); - const config = { preResolveTypes: true }; + const { content } = await plugin( testSchema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + {}, + { outputFile: '' }, ); const o = await validate(content); @@ -3050,7 +2566,7 @@ export type Q2Query = { search: Array< `); }); - it('Should produce valid output with preResolveTypes=true and enums with prefixes set', async () => { + it('Should produce valid output with enums with prefixes set', async () => { const ast = parse(/* GraphQL */ ` query test($e: Information_EntryType!) { info { @@ -3088,18 +2604,12 @@ export type Q2Query = { search: Array< info: Information } `); - const config = { - preResolveTypes: true, - typesPrefix: 'I', - enumPrefix: false, - }; + const { content } = await plugin( testSchema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { typesPrefix: 'I', enumPrefix: false }, + { outputFile: '' }, ); const o = await validate(content); @@ -3120,7 +2630,7 @@ export type Q2Query = { search: Array< `); }); - it('Should produce valid output with preResolveTypes=true and enums with no suffixes', async () => { + it('Should produce valid output with enums with no suffixes', async () => { const ast = parse(/* GraphQL */ ` query test($e: Information_EntryType!) { info { @@ -3158,18 +2668,12 @@ export type Q2Query = { search: Array< info: Information } `); - const config = { - preResolveTypes: true, - typesSuffix: 'I', - enumSuffix: false, - }; + const { content } = await plugin( testSchema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { typesSuffix: 'I', enumSuffix: false }, + { outputFile: '' }, ); const o = await validate(content); @@ -3196,21 +2700,19 @@ export type Q2Query = { search: Array< dummy } `); - const config = { skipTypename: true, preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: true }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type DummyQueryVariables = Exact<{ [key: string]: never; }>; - export type DummyQuery = Pick; + export type DummyQuery = { dummy: string | null }; " `); await validate(content); @@ -3225,24 +2727,19 @@ export type Q2Query = { search: Array< } } `); - const config = { skipTypename: true, preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: true }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type DummyQueryVariables = Exact<{ [key: string]: never; }>; - export type DummyQuery = ( - { customName: Query['dummy'] } - & { customName2: Maybe> } - ); + export type DummyQuery = { customName: string | null, customName2: { age: number | null } | null }; " `); await validate(content); @@ -3261,14 +2758,12 @@ export type Q2Query = { search: Array< } } `); - const config = { skipTypename: true, preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: true }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` @@ -3279,10 +2774,7 @@ export type Q2Query = { search: Array< export type CurrentUserQueryVariables = Exact<{ [key: string]: never; }>; - export type CurrentUserQuery = { me: Maybe<( - Pick - & { profile: Maybe> } - )> }; + export type CurrentUserQuery = { me: { id: string, username: string, role: Role | null, profile: { age: number | null } | null } | null }; " `); await validate(content); @@ -3300,21 +2792,16 @@ export type Q2Query = { search: Array< } } `); - const config = { skipTypename: true, preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: true }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` - "export type UserFieldsFragment = ( - Pick - & { profile: Maybe> } - ); + "export type UserFieldsFragment = { id: string, username: string, profile: { age: number | null } | null }; " `); await validate(content); @@ -3334,24 +2821,19 @@ export type Q2Query = { search: Array< } } `); - const config = { skipTypename: true, preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: true }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type LoginMutationVariables = Exact<{ [key: string]: never; }>; - export type LoginMutation = { login: Maybe<( - Pick - & { profile: Maybe> } - )> }; + export type LoginMutation = { login: { id: string, username: string, profile: { age: number | null } | null } | null }; " `); await validate(content); @@ -3363,21 +2845,19 @@ export type Q2Query = { search: Array< dummy } `); - const config = { skipTypename: true, preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: false }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type TestQueryVariables = Exact<{ [key: string]: never; }>; - export type TestQuery = Pick; + export type TestQuery = { dummy: string | null }; " `); await validate(content); @@ -3391,21 +2871,19 @@ export type Q2Query = { search: Array< } } `); - const config = { skipTypename: true, preResolveTypes: false }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: true }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` "export type TestSubscriptionVariables = Exact<{ [key: string]: never; }>; - export type TestSubscription = { userCreated: Maybe> }; + export type TestSubscription = { userCreated: { id: string } | null }; " `); await validate(content); @@ -3426,14 +2904,12 @@ export type Q2Query = { search: Array< dummy } `); - const config = { skipTypename: true }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: true }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot( @@ -3467,14 +2943,12 @@ export type Q2Query = { search: Array< dummy } `); - const config = { skipTypename: true }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: true }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot( @@ -3497,14 +2971,12 @@ export type Q2Query = { search: Array< dummy } `); - const config = { skipTypename: true }; + const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, + { skipTypename: true }, + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` @@ -3549,10 +3021,8 @@ export type Q2Query = { search: Array< const { content } = await plugin( testSchema, [{ location: '', document: query }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` @@ -3562,8 +3032,8 @@ export type Q2Query = { search: Array< export type SubmitMessageMutation = { mutation: - | Pick - | Pick + | { deleted: boolean } + | { updated: boolean } }; " `); @@ -3591,10 +3061,8 @@ export type Q2Query = { search: Array< const { content } = await plugin( testSchema, [{ location: '', document: query }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` @@ -3630,17 +3098,15 @@ export type Q2Query = { search: Array< const { content } = await plugin( testSchema, [{ location: '', document: query }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` "export type InfoQueryVariables = Exact<{ [key: string]: never; }>; - export type InfoQuery = { __schema: { queryType: { fields: Maybe>> } } }; + export type InfoQuery = { __schema: { queryType: { fields: Array<{ name: string }> | null } } }; " `); }); @@ -3672,23 +3138,15 @@ export type Q2Query = { search: Array< const { content } = await plugin( testSchema, [{ location: '', document: query }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` "export type InfoQueryVariables = Exact<{ [key: string]: never; }>; - export type InfoQuery = { __type: Maybe<( - Pick<__Type, 'name'> - & { fields: Maybe - & { type: Pick<__Type, 'name' | 'kind'> } - )>> } - )> }; + export type InfoQuery = { __type: { name: string | null, fields: Array<{ name: string, type: { name: string | null, kind: __TypeKind } }> | null } | null }; " `); }); @@ -3721,10 +3179,8 @@ export type Q2Query = { search: Array< const { content } = await plugin( testSchema, [{ location: '', document: query }], - { typesPrefix: 'PREFIX_', preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + { typesPrefix: 'PREFIX_' }, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` @@ -3742,25 +3198,7 @@ export type Q2Query = { search: Array< }>; - export type PREFIX_UsersQuery = { users: Maybe>>> }; - " - `); - expect(content).toMatchInlineSnapshot(` - "export type PREFIX_Access = - | 'Read' - | 'Write' - | 'All'; - - type PREFIX_Filter = { - match: string; - }; - - export type PREFIX_UsersQueryVariables = Exact<{ - filter: PREFIX_Filter; - }>; - - - export type PREFIX_UsersQuery = { users: Maybe>>> }; + export type PREFIX_UsersQuery = { users: Array<{ access: PREFIX_Access | null } | null> | null }; " `); }); @@ -3786,9 +3224,7 @@ export type Q2Query = { search: Array< testSchema, [{ location: '', document: query }], {}, - { - outputFile: 'graphql.ts', - }, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` @@ -3854,32 +3290,18 @@ export type Q2Query = { search: Array< const { content } = await plugin( schema, [{ location: '', document: query }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` "export type FieldQueryVariables = Exact<{ [key: string]: never; }>; export type FieldQuery = { field: - | ( - { __typename: 'Error1' } - & Pick - ) - | ( - { __typename: 'Error2' } - & Pick - ) - | ( - { __typename: 'ComplexError' } - & Pick - ) - | ( - { __typename: 'FieldResultSuccess' } - & Pick - ) + | { __typename: 'Error1', message: string } + | { __typename: 'Error2', message: string } + | { __typename: 'ComplexError', message: string, additionalInfo: string } + | { __typename: 'FieldResultSuccess', someValue: boolean } }; " `); @@ -3935,29 +3357,18 @@ export type Q2Query = { search: Array< const { content } = await plugin( schema, [{ location: '', document: query }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` "export type FieldQueryVariables = Exact<{ [key: string]: never; }>; export type FieldQuery = { field: - | ( - { __typename: 'Error1' } - & Pick - ) - | ( - { __typename: 'Error2' } - & Pick - ) - | ( - { __typename: 'ComplexError' } - & Pick - ) - | Pick + | { __typename: 'Error1', message: string } + | { __typename: 'Error2', message: string } + | { __typename: 'ComplexError', message: string, additionalInfo: string } + | { someValue: boolean } }; " `); @@ -4000,20 +3411,18 @@ export type Q2Query = { search: Array< const { content } = await plugin( testSchema, [{ location: '', document: query }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` "export type SomethingQueryVariables = Exact<{ [key: string]: never; }>; - export type SomethingQuery = { node: Maybe< - | Pick - | Pick - > }; + export type SomethingQuery = { node: + | { a: string | null } + | { a: boolean | null } + | null }; " `); }); @@ -4068,24 +3477,19 @@ export type Q2Query = { search: Array< const { content } = await plugin( testSchema, [{ location: '', document: query }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` "export type UserQueryVariables = Exact<{ [key: string]: never; }>; - export type UserQuery = { user: Maybe< - | Pick - | Pick - | ( - Pick - & { info: Maybe> } - ) - > }; + export type UserQuery = { user: + | { id: string, login: string } + | { message: string } + | { message: string, info: { message: string } | null } + | null }; " `); }); @@ -4156,24 +3560,19 @@ export type Q2Query = { search: Array< const { content } = await plugin( testSchema, [{ location: '', document: query }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` "export type UserQueryVariables = Exact<{ [key: string]: never; }>; - export type UserQuery = { user: Maybe< - | Pick - | Pick - | ( - Pick - & { info: Maybe> } - ) - > }; + export type UserQuery = { user: + | { id: string, login: string } + | { message: string } + | { message: string, info: { message: string, message2: string } | null } + | null }; " `); }); @@ -4207,10 +3606,8 @@ export type Q2Query = { search: Array< const { content } = await plugin( testSchema, [{ location: '', document: query }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); const o = await validate(content); @@ -4219,7 +3616,7 @@ export type Q2Query = { search: Array< "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; - export type UserQueryQuery = { user: Pick }; + export type UserQueryQuery = { user: { id: string, login: string } }; " `); }); @@ -4255,10 +3652,8 @@ export type Q2Query = { search: Array< const { content } = await plugin( testSchema, [{ location: '', document: query }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); const o = await validate(content); @@ -4267,19 +3662,9 @@ export type Q2Query = { search: Array< "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; - export type UserQueryQuery = { user: Pick }; - - export type TestFragment = Pick; - " - `); - - expect(o).toMatchInlineSnapshot(` - "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; - - - export type UserQueryQuery = { user: Pick }; + export type UserQueryQuery = { user: { id: string, login: string } }; - export type TestFragment = Pick; + export type TestFragment = { login: string }; " `); }); @@ -4360,10 +3745,8 @@ export type Q2Query = { search: Array< const { content } = await plugin( testSchema, [{ location: '', document: query }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); const output = await validate( @@ -4387,35 +3770,31 @@ export type Q2Query = { search: Array< } }`, ); - expect(mergeOutputs([content])).toMatchSnapshot(); expect(output).toMatchInlineSnapshot(` "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; export type UserQueryQuery = { user: - | Pick - | Pick - | ( - Pick - & { info: Maybe> } - ) + | { login: string, id: string } + | { message: string } + | { message: string, info: { message2: string, message: string } | null } }; - export type AdditionalInfoFragment = Pick; + export type AdditionalInfoFragment = { message: string }; - type UserResult1_User_Fragment = Pick; + type UserResult1_User_Fragment = { id: string }; - type UserResult1_Error3_Fragment = { info: Maybe> }; + type UserResult1_Error3_Fragment = { info: { message2: string } | null }; export type UserResult1Fragment = | UserResult1_User_Fragment | UserResult1_Error3_Fragment ; - type UserResult_User_Fragment = Pick; + type UserResult_User_Fragment = { id: string }; - type UserResult_Error2_Fragment = Pick; + type UserResult_Error2_Fragment = { message: string }; export type UserResultFragment = | UserResult_User_Fragment @@ -4440,59 +3819,7 @@ export type Q2Query = { search: Array< } }" `); - - expect(output).toMatchInlineSnapshot(` - "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; - - - export type UserQueryQuery = { user: - | Pick - | Pick - | ( - Pick - & { info: Maybe> } - ) - }; - - export type AdditionalInfoFragment = Pick; - - type UserResult1_User_Fragment = Pick; - - type UserResult1_Error3_Fragment = { info: Maybe> }; - - export type UserResult1Fragment = - | UserResult1_User_Fragment - | UserResult1_Error3_Fragment - ; - - type UserResult_User_Fragment = Pick; - - type UserResult_Error2_Fragment = Pick; - - export type UserResultFragment = - | UserResult_User_Fragment - | UserResult_Error2_Fragment - ; - - function t(q: UserQueryQuery) { - if (q.user) { - if (q.user.__typename === 'User') { - if (q.user.id) { - const u = q.user.login; - } - } - if (q.user.__typename === 'Error2') { - console.log(q.user.message); - } - if (q.user.__typename === 'Error3') { - if (q.user.info) { - console.log(q.user.info.__typename) - } - } - } - }" - `); - }); + }); it('Should handle union selection sets with both FragmentSpreads and InlineFragments with flattenGeneratedTypes', async () => { const testSchema = buildSchema(/* GraphQL */ ` @@ -4567,14 +3894,12 @@ export type Q2Query = { search: Array< } `); - const config = { - flattenGeneratedTypes: true, - preResolveTypes: false, - }; - - const { content } = await plugin(testSchema, [{ location: '', document: query }], config, { - outputFile: 'graphql.ts', - }); + const { content } = await plugin( + testSchema, + [{ location: '', document: query }], + { flattenGeneratedTypes: true }, + { outputFile: 'graphql.ts' }, + ); const output = await validate( content, @@ -4597,19 +3922,15 @@ export type Q2Query = { search: Array< } }`, ); - expect(mergeOutputs([output])).toMatchSnapshot(); expect(output).toMatchInlineSnapshot(` "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; export type UserQueryQuery = { user: - | Pick - | Pick - | ( - Pick - & { info: Maybe> } - ) + | { id: string, login: string } + | { message: string } + | { message: string, info: { message2: string, message: string } | null } }; function t(q: UserQueryQuery) { @@ -4682,29 +4003,23 @@ export type Q2Query = { search: Array< } `); - const config = { - flattenGeneratedTypes: true, - preResolveTypes: false, - }; - - const { content } = await plugin(testSchema, [{ location: '', document: query }], config, { - outputFile: 'graphql.ts', - }); + const { content } = await plugin( + testSchema, + [{ location: '', document: query }], + { flattenGeneratedTypes: true }, + { outputFile: 'graphql.ts' }, + ); const output = await validate(content); - expect(mergeOutputs([output])).toMatchSnapshot(); expect(output).toMatchInlineSnapshot(` "export type SearchPopularQueryVariables = Exact<{ [key: string]: never; }>; - export type SearchPopularQuery = { search: Maybe - | ( - Pick - & { dimension: Maybe> } - ) - >> }; + export type SearchPopularQuery = { search: Array< + | { id: string | null } + | { value: string, dimension: { id: string | null } | null } + > | null }; " `); }); @@ -4743,22 +4058,17 @@ export type Q2Query = { search: Array< } `); - const config = { - flattenGeneratedTypes: true, - flattenGeneratedTypesIncludeFragments: true, - preResolveTypes: true, - }; - const { content } = await plugin( testSchema, [ { location: '', document: query }, { location: '', document: fragment }, ], - config, { - outputFile: 'graphql.ts', + flattenGeneratedTypes: true, + flattenGeneratedTypesIncludeFragments: true, }, + { outputFile: 'graphql.ts' }, ); const output = await validate(content); @@ -4809,22 +4119,17 @@ export type Q2Query = { search: Array< } `); - const config = { - flattenGeneratedTypes: true, - flattenGeneratedTypesIncludeFragments: false, - preResolveTypes: true, - }; - const { content } = await plugin( testSchema, [ { location: '', document: query }, { location: '', document: fragment }, ], - config, { - outputFile: 'graphql.ts', + flattenGeneratedTypes: true, + flattenGeneratedTypesIncludeFragments: false, }, + { outputFile: 'graphql.ts' }, ); const output = await validate(content); @@ -4863,25 +4168,23 @@ export type Q2Query = { search: Array< } `); - const config = { - addOperationExport: true, - preResolveTypes: false, - }; - - const { content } = await plugin(testSchema, [{ location: '', document: query }], config, { - outputFile: 'graphql.ts', - }); + const { content } = await plugin( + testSchema, + [{ location: '', document: query }], + { addOperationExport: true }, + { outputFile: 'graphql.ts' }, + ); expect(content).toMatchInlineSnapshot(` "export type UserIdQueryQueryVariables = Exact<{ [key: string]: never; }>; - export type UserIdQueryQuery = { user: Pick }; + export type UserIdQueryQuery = { user: { id: string } }; export type UserLoginQueryQueryVariables = Exact<{ [key: string]: never; }>; - export type UserLoginQueryQuery = { user: Pick }; + export type UserLoginQueryQuery = { user: { login: string } }; export declare const UserIdQuery: import("graphql").DocumentNode; export declare const UserLoginQuery: import("graphql").DocumentNode;" @@ -4968,14 +4271,12 @@ export type Q2Query = { search: Array< } `); - const config = { - flattenGeneratedTypes: true, - preResolveTypes: false, - }; - - const { content } = await plugin(testSchema, [{ location: '', document: query }], config, { - outputFile: 'graphql.ts', - }); + const { content } = await plugin( + testSchema, + [{ location: '', document: query }], + { flattenGeneratedTypes: true }, + { outputFile: 'graphql.ts' }, + ); const output = await validate( content, @@ -4998,25 +4299,15 @@ export type Q2Query = { search: Array< } }`, ); - expect(mergeOutputs([output])).toMatchSnapshot(); expect(output).toMatchInlineSnapshot(` "export type UserQueryQueryVariables = Exact<{ [key: string]: never; }>; export type UserQueryQuery = { user: - | Pick< - User, - | 'id' - | 'test2' - | 'login' - | 'test' - > - | Pick - | ( - Pick - & { info: Maybe> } - ) + | { id: string, test2: string | null, login: string, test: string | null } + | { message: string } + | { message: string, info: { message2: string, message: string } | null } }; function t(q: UserQueryQuery) { @@ -5086,9 +4377,7 @@ export type Q2Query = { search: Array< testSchema, [{ location: '', document: query }], {}, - { - outputFile: 'graphql.ts', - }, + { outputFile: 'graphql.ts' }, ); await validate( @@ -5125,14 +4414,17 @@ export type Q2Query = { search: Array< const { content } = await plugin( testSchema, [{ location: '', document: query }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); - expect(content).not.toContain(`Maybe<>`); - expect(content).toContain(`Maybe`); + expect(content).toMatchInlineSnapshot(` + "export type TestQueryVariables = Exact<{ [key: string]: never; }>; + + + export type TestQuery = { test: never | null }; + " + `); }); it('#4389 - validate issues with interfaces', async () => { @@ -5170,16 +4462,14 @@ export type Q2Query = { search: Array< const { content } = await plugin( testSchema, [{ location: '', document: query }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type Unnamed_1_Query = { foo: Maybe> }; + export type Unnamed_1_Query = { foo: Record | null }; " `); }); @@ -5207,13 +4497,12 @@ export type Q2Query = { search: Array< } `); - const config = { - typesSuffix: 'Type', - }; - - const { content } = await plugin(testSchema, [{ location: '', document: query }], config, { - outputFile: 'graphql.ts', - }); + const { content } = await plugin( + testSchema, + [{ location: '', document: query }], + { typesSuffix: 'Type' }, + { outputFile: 'graphql.ts' }, + ); expect(content).not.toContain('UserTypeQueryVariablesType'); expect(content).not.toContain('UserTypeQueryType'); @@ -5276,13 +4565,12 @@ export type Q2Query = { search: Array< } `); - const config = {}; - - const { content } = await plugin(testSchema, [{ location: '', document: query }], config, { - outputFile: 'graphql.ts', - }); - - expect(content).toMatchSnapshot(); + const { content } = await plugin( + testSchema, + [{ location: '', document: query }], + {}, + { outputFile: 'graphql.ts' }, + ); const result = await validate( content, @@ -5299,7 +4587,7 @@ export type Q2Query = { search: Array< expect(mergeOutputs([result])).toMatchSnapshot(); }); - it('#2916 - Missing import prefix with preResolveTypes: true and near-operation-file preset', async () => { + it('#2916 - Missing import prefix with near-operation-file preset', async () => { const testSchema = buildSchema(/* GraphQL */ ` type Query { user(id: ID!): User! @@ -5329,15 +4617,15 @@ export type Q2Query = { search: Array< } `); - const config = { - skipTypename: true, - preResolveTypes: true, - namespacedImportName: 'Types', - }; - - const { content } = await plugin(testSchema, [{ location: '', document: query }], config, { - outputFile: 'graphql.ts', - }); + const { content } = await plugin( + testSchema, + [{ location: '', document: query }], + { + skipTypename: true, + namespacedImportName: 'Types', + }, + { outputFile: 'graphql.ts' }, + ); expect(content).toContain(`dep: Types.Department`); expect(content).toMatchSnapshot(); @@ -5465,9 +4753,7 @@ export type Q2Query = { search: Array< testSchema, [{ location: '', document: query }], {}, - { - outputFile: 'graphql.ts', - }, + { outputFile: 'graphql.ts' }, ); expect(mergeOutputs([content])).toMatchSnapshot(); @@ -5530,10 +4816,8 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( testSchema, [{ location: '', document: query }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` @@ -5541,13 +4825,13 @@ function test(q: GetEntityBrandDataQuery): void { export type TestQueryQuery = { fooBar: Array< - | Pick - | Pick + | { id: string } + | { id: string } > }; - type FooBarFragment_Foo_Fragment = Pick; + type FooBarFragment_Foo_Fragment = { id: string }; - type FooBarFragment_Bar_Fragment = Pick; + type FooBarFragment_Bar_Fragment = { id: string }; export type FooBarFragmentFragment = | FooBarFragment_Foo_Fragment @@ -5600,19 +4884,14 @@ function test(q: GetEntityBrandDataQuery): void { { location: '', document: productFragmentDocument }, { location: '', document: priceFragmentDocument }, ], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` - "export type ProductFragmentFragment = Pick; + "export type ProductFragmentFragment = { id: string, title: string }; - export type PriceFragmentFragment = ( - Pick - & { item: Array>> } - ); + export type PriceFragmentFragment = { id: string, item: Array<{ id: string, title: string } | null> }; " `); }); @@ -5641,10 +4920,8 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document: fragment }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` @@ -5653,7 +4930,7 @@ function test(q: GetEntityBrandDataQuery): void { }>; - export type UserQuery = { user?: Maybe> }; + export type UserQuery = { user?: { name: string | null } | null }; " `); }); @@ -5709,22 +4986,14 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document: fragment }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` "export type DashboardVersionFragmentFragment = { tiles: - | ( - Pick - & { md: Pick } - ) - | ( - Pick - & { md: Pick } - ) + | { tileId: string, md: { viz: string, columnInfo: string } } + | { tileId: string, md: { viz: string, columnInfo: string } } }; " `); @@ -5780,22 +5049,14 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document: fragment }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` "export type DashboardVersionFragmentFragment = { tiles: - | ( - Pick - & { md: Pick } - ) - | ( - Pick - & { md: Pick } - ) + | { tileId: string, md: { viz: string, columnInfo: string } } + | { tileId: string, md: { viz: string, columnInfo: string } } }; " `); @@ -5844,12 +5105,8 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document: query }], - { - skipTypename: true, - }, - { - outputFile: 'graphql.ts', - }, + { skipTypename: true }, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` @@ -5917,12 +5174,8 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document: query }], - { - skipTypename: false, - }, - { - outputFile: 'graphql.ts', - }, + { skipTypename: false }, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` @@ -5979,13 +5232,8 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document: query }], - { - skipTypename: true, - preResolveTypes: false, - }, - { - outputFile: 'graphql.ts', - }, + { skipTypename: true }, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` @@ -5993,7 +5241,7 @@ function test(q: GetEntityBrandDataQuery): void { export type UserQuery = { user: - | Pick + | { id: string, login: string | null } | Record }; " @@ -6022,10 +5270,13 @@ function test(q: GetEntityBrandDataQuery): void { } } `); - const config = { preResolveTypes: true }; - const { content } = await plugin(schema, [{ location: '', document: ast }], config, { - outputFile: 'graphql.ts', - }); + + const { content } = await plugin( + schema, + [{ location: '', document: ast }], + {}, + { outputFile: 'graphql.ts' }, + ); expect(content).toMatchInlineSnapshot(` "export type UserQueryVariables = Exact<{ @@ -6063,10 +5314,13 @@ function test(q: GetEntityBrandDataQuery): void { } } `); - const config = { preResolveTypes: true, arrayInputCoercion: false }; - const { content } = await plugin(schema, [{ location: '', document: ast }], config, { - outputFile: 'graphql.ts', - }); + + const { content } = await plugin( + schema, + [{ location: '', document: ast }], + { arrayInputCoercion: false }, + { outputFile: 'graphql.ts' }, + ); expect(content).toMatchInlineSnapshot(` "export type UserQueryVariables = Exact<{ @@ -6122,10 +5376,8 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` @@ -6133,8 +5385,8 @@ function test(q: GetEntityBrandDataQuery): void { export type EntityQuery = { entity: - | Pick - | Pick + | { id: string } + | { name: string, id: string } }; " `); @@ -6174,17 +5426,15 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` "export type InlineFragmentQueryQueryVariables = Exact<{ [key: string]: never; }>; - export type InlineFragmentQueryQuery = { user: { friends: Array> } }; + export type InlineFragmentQueryQuery = { user: { friends: Array<{ id: string, name: string }> } }; " `); }); @@ -6215,21 +5465,19 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` - "export type UserFriendsIdFragmentFragment = { user: { friends: Array> } }; + "export type UserFriendsIdFragmentFragment = { user: { friends: Array<{ id: string }> } }; - export type UserFriendsNameFragmentFragment = { user: { friends: Array> } }; + export type UserFriendsNameFragmentFragment = { user: { friends: Array<{ name: string }> } }; export type SpreadFragmentQueryQueryVariables = Exact<{ [key: string]: never; }>; - export type SpreadFragmentQueryQuery = { user: { friends: Array> } }; + export type SpreadFragmentQueryQuery = { user: { friends: Array<{ id: string, name: string }> } }; " `); }); @@ -6257,22 +5505,17 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` - "export type UserFriendsNameFragmentFragment = { user: { friends: Array> } }; + "export type UserFriendsNameFragmentFragment = { user: { friends: Array<{ name: string }> } }; export type SpreadFragmentWithSelectionQueryQueryVariables = Exact<{ [key: string]: never; }>; - export type SpreadFragmentWithSelectionQueryQuery = { user: ( - Pick - & { friends: Array> } - ) }; + export type SpreadFragmentWithSelectionQueryQuery = { user: { id: string, friends: Array<{ id: string, name: string }> } }; " `); }); @@ -6300,22 +5543,17 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` - "export type UserFriendsNameFragmentFragment = { user: { friends: Array> } }; + "export type UserFriendsNameFragmentFragment = { user: { friends: Array<{ name: string }> } }; export type SpreadFragmentWithSelectionQueryQueryVariables = Exact<{ [key: string]: never; }>; - export type SpreadFragmentWithSelectionQueryQuery = { user: ( - Pick - & { friends: Array> } - ) }; + export type SpreadFragmentWithSelectionQueryQuery = { user: { id: string, friends: Array<{ id: string, name: string }> } }; " `); }); @@ -6402,7 +5640,7 @@ function test(q: GetEntityBrandDataQuery): void { `); }); - it('#6874 - generates types when parent type differs from spread fragment member types and preResolveTypes=true', async () => { + it('#6874 - generates types when parent type differs from spread fragment member types', async () => { const testSchema = buildSchema(/* GraphQL */ ` interface Animal { name: String! @@ -6457,11 +5695,12 @@ function test(q: GetEntityBrandDataQuery): void { } `); - const config = { preResolveTypes: true }; - - const { content } = await plugin(testSchema, [{ location: '', document: query }], config, { - outputFile: 'graphql.ts', - }); + const { content } = await plugin( + testSchema, + [{ location: '', document: query }], + {}, + { outputFile: 'graphql.ts' }, + ); expect(content).toMatchSnapshot(); }); @@ -6505,13 +5744,23 @@ function test(q: GetEntityBrandDataQuery): void { } `); - const config = { preResolveTypes: true }; + const { content } = await plugin( + testSchema, + [{ location: '', document: query }], + {}, + { outputFile: 'graphql.ts' }, + ); + + expect(content).toMatchInlineSnapshot(` + "export type SnakeQueryQueryVariables = Exact<{ [key: string]: never; }>; - const { content } = await plugin(testSchema, [{ location: '', document: query }], config, { - outputFile: 'graphql.ts', - }); - expect(content).toMatchSnapshot(); + export type SnakeQueryQuery = { __typename: 'Query', snake: + | { __typename: 'Snake' } + | { __typename: 'Error' } + }; + " + `); }); it('#8461 - conditional directives are ignored on fields with alias', async () => { @@ -6543,11 +5792,12 @@ function test(q: GetEntityBrandDataQuery): void { } `); - const config = { preResolveTypes: true }; - - const { content } = await plugin(testSchema, [{ location: '', document: query }], config, { - outputFile: 'graphql.ts', - }); + const { content } = await plugin( + testSchema, + [{ location: '', document: query }], + {}, + { outputFile: 'graphql.ts' }, + ); expect(content).toMatchInlineSnapshot(` "export type UserQueryQueryVariables = Exact<{ @@ -6591,12 +5841,8 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document: fragment }], - { - preResolveTypes: true, - }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` @@ -6647,12 +5893,8 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document: fragment }], - { - preResolveTypes: true, - }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` @@ -6667,32 +5909,26 @@ function test(q: GetEntityBrandDataQuery): void { `); }); - it('fields with @skip, @include should make container resolve into MakeOptional type', async () => { + it('optionals (?) on types should be avoided by default', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { - user: User! + me: User! } + type User { - id: String! - name: String! - address: Address! - friends: [User!]! + messages: [Message!]! } - type Address { - city: String! + + type Message { + content: String! } `); const fragment = parse(/* GraphQL */ ` - query user($showAddress: Boolean!, $showName: Boolean!) { - user { - id - name @include(if: $showName) - address @include(if: $showAddress) { - city - } - friends @include(if: $isFriendly) { - id + query MyQuery($include: Boolean!) { + me { + messages @include(if: $include) { + content } } } @@ -6701,150 +5937,8 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document: fragment }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, - ); - - expect(content).toMatchInlineSnapshot(` - "export type UserQueryVariables = Exact<{ - showAddress: boolean; - showName: boolean; - }>; - - - export type UserQuery = { user: ( - MakeOptional, 'name'> - & { - address?: Pick, - friends?: Array>, - } - ) }; - " - `); - }); - - it('On avoidOptionals:true, fields with @skip, @include should make container resolve into MakeMaybe type', async () => { - const schema = buildSchema(/* GraphQL */ ` - type Query { - user(id: ID!): User! - } - - type User { - id: ID! - username: String! - email: String! - } - `); - - const fragment = parse(/* GraphQL */ ` - query user { - user(id: 1) { - id - username - email @skip(if: true) - } - } - `); - - const { content } = await plugin( - schema, - [{ location: '', document: fragment }], - { - avoidOptionals: true, - preResolveTypes: false, - }, - { - outputFile: 'graphql.ts', - }, - ); - - expect(content).toBeSimilarStringTo(` - export type UserQueryVariables = Exact<{ [key: string]: never; }>; - - export type UserQuery = ( - { __typename?: 'Query' } - & { user: ( - { __typename?: 'User' } - & MakeMaybe, 'email'> - ) } - ); - `); - }); - - it('Should handle "preResolveTypes" ', async () => { - const schema = buildSchema(/* GraphQL */ ` - type Query { - user(id: ID!): User! - } - - type User { - id: ID! - username: String! - email: String - } - `); - const operations = parse(/* GraphQL */ ` - query user { - user(id: 1) { - id - username - email - } - } - `); - const config = { preResolveTypes: true }; - const { content } = await plugin(schema, [{ location: '', document: operations }], config, { - outputFile: 'graphql.ts', - }); - - expect(content).toMatchInlineSnapshot( - ` - "export type UserQueryVariables = Exact<{ [key: string]: never; }>; - - - export type UserQuery = { user: { id: string, username: string, email: string | null } }; - " - `, - ); - }); - - it('optionals (?) on types should be avoided by default', async () => { - const schema = buildSchema(/* GraphQL */ ` - type Query { - me: User! - } - - type User { - messages: [Message!]! - } - - type Message { - content: String! - } - `); - - const fragment = parse(/* GraphQL */ ` - query MyQuery($include: Boolean!) { - me { - messages @include(if: $include) { - content - } - } - } - `); - - const { content } = await plugin( - schema, - [{ location: '', document: fragment }], - { - nonOptionalTypename: true, - preResolveTypes: false, - }, - { - outputFile: 'graphql.ts', - }, + { nonOptionalTypename: true }, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` @@ -6853,16 +5947,7 @@ function test(q: GetEntityBrandDataQuery): void { }>; - export type MyQueryQuery = ( - { __typename: 'Query' } - & { me: ( - { __typename: 'User' } - & { messages?: Array<( - { __typename: 'Message' } - & Pick - )> } - ) } - ); + export type MyQueryQuery = { __typename: 'Query', me: { __typename: 'User', messages?: Array<{ __typename: 'Message', content: string }> } }; " `); }); @@ -6899,10 +5984,8 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document: fragment }], - { preResolveTypes: true }, - { - outputFile: 'graphql.ts', - }, + {}, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` @@ -6946,13 +6029,8 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document: fragment }], - { - preResolveTypes: true, - maybeValue: "T | 'specialType'", - }, - { - outputFile: 'graphql.ts', - }, + { maybeValue: "T | 'specialType'" }, + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` "export type UserQueryVariables = Exact<{ @@ -6964,62 +6042,10 @@ function test(q: GetEntityBrandDataQuery): void { " `); }); - - it('inline fragment with conditional directives, without preResolveTypes', async () => { - const schema = buildSchema(/* GraphQL */ ` - type Query { - user: User - group: Group! - } - - type User { - name: String - } - - type Group { - id: Int! - } - `); - - const fragment = parse(/* GraphQL */ ` - query user($withUser: Boolean! = false) { - ... @include(if: $withUser) { - user { - name - } - group { - id - } - } - } - `); - - const { content } = await plugin( - schema, - [{ location: '', document: fragment }], - { preResolveTypes: false }, - { - outputFile: 'graphql.ts', - }, - ); - - expect(content).toMatchInlineSnapshot(` - "export type UserQueryVariables = Exact<{ - withUser?: boolean; - }>; - - - export type UserQuery = { - user?: Maybe>, - group?: Pick, - }; - " - `); - }); }); describe('incremental delivery directive handling', () => { - it('should generate an union of initial and deferred fields for fragments (preResolveTypes: true)', async () => { + it('should generate an union of initial and deferred fields for fragments', async () => { const schema = buildSchema(/* GraphQL */ ` type Address { street1: String! @@ -7104,7 +6130,7 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document: fragment }], - { preResolveTypes: true }, + {}, { outputFile: 'graphql.ts' }, ); @@ -7123,294 +6149,6 @@ function test(q: GetEntityBrandDataQuery): void { `); }); - it('should generate an union of initial and deferred fields for fragments using MakeEmpty (preResolveTypes: false)', async () => { - const schema = buildSchema(/* GraphQL */ ` - type Address { - street1: String! - } - - type Phone { - home: String! - } - - type Employment { - title: String! - } - - type User { - name: String! - email: String! - address: Address! - phone: Phone! - employment: Employment! - widgetCount: Int! - clearanceLevel: String! - } - - type Query { - user: User! - } - `); - - const fragment = parse(/* GraphQL */ ` - fragment WidgetFragment on User { - widgetCount - } - - fragment EmploymentFragment on User { - employment { - title - } - } - - query user { - user { - # Test inline fragment defer - ... @defer { - email - } - - # Test inline fragment defer with nested selection set - ... @defer { - address { - street1 - } - } - - # Test named fragment defer - ...WidgetFragment @defer - - # Not deferred fields, fragments, selection sets, etc are left alone - name - phone { - home - } - ...EmploymentFragment - ... { - clearanceLevel - } - } - } - `); - - const { content } = await plugin( - schema, - [{ location: '', document: fragment }], - { preResolveTypes: false }, - { outputFile: 'graphql.ts' }, - ); - - expect(content).toMatchInlineSnapshot(` - "export type WidgetFragmentFragment = Pick; - - export type EmploymentFragmentFragment = { employment: Pick }; - - export type UserQueryVariables = Exact<{ [key: string]: never; }>; - - - export type UserQuery = { user: ( - Pick - & { - phone: Pick, - employment: Pick, - } - ) & (Pick | MakeEmpty) & ({ address: Pick } | { address?: Pick }) & (Pick | MakeEmpty) }; - " - `); - }); - - it('should generate an union of initial and deferred fields for fragments MakeEmpty', async () => { - const schema = buildSchema(/* GraphQL */ ` - type Address { - street1: String! - } - - type Phone { - home: String! - } - - type Employment { - title: String! - } - - type User { - name: String! - email: String! - address: Address! - phone: Phone! - employment: Employment! - widgetName: String! - widgetCount: Int! - clearanceLevel: String! - } - - type Query { - user: User! - } - `); - - const fragment = parse(/* GraphQL */ ` - fragment WidgetFragment on User { - widgetName - widgetCount - } - - fragment EmploymentFragment on User { - employment { - title - } - } - - query user { - user { - # Test inline fragment defer - ... @defer { - email - } - - # Test inline fragment defer with nested selection set - ... @defer { - address { - street1 - } - } - - # Test named fragment defer - ...WidgetFragment @defer - - # Not deferred fields, fragments, selection sets, etc are left alone - name - phone { - home - } - ...EmploymentFragment - ... { - clearanceLevel - } - } - } - `); - - const { content } = await plugin( - schema, - [{ location: '', document: fragment }], - { - preResolveTypes: false, - }, - { outputFile: 'graphql.ts' }, - ); - - expect(content).toMatchInlineSnapshot(` - "export type WidgetFragmentFragment = Pick; - - export type EmploymentFragmentFragment = { employment: Pick }; - - export type UserQueryVariables = Exact<{ [key: string]: never; }>; - - - export type UserQuery = { user: ( - Pick - & { - phone: Pick, - employment: Pick, - } - ) & (Pick | MakeEmpty) & ({ address: Pick } | { address?: Pick }) & (Pick | MakeEmpty) }; - " - `); - }); - - it('should support "preResolveTypes: true"', async () => { - const schema = buildSchema(/* GraphQL */ ` - type Address { - street1: String! - } - - type Phone { - home: String! - } - - type Employment { - title: String! - } - - type User { - name: String! - email: String! - address: Address! - phone: Phone! - employment: Employment! - widgetCount: Int! - clearanceLevel: String! - } - - type Query { - user: User! - } - `); - - const fragment = parse(/* GraphQL */ ` - fragment WidgetFragment on User { - widgetCount - } - - fragment EmploymentFragment on User { - employment { - title - } - } - - query user { - user { - # Test inline fragment defer - ... @defer { - email - } - - # Test inline fragment defer with nested selection set - ... @defer { - address { - street1 - } - } - - # Test named fragment defer - ...WidgetFragment @defer - - # Not deferred fields, fragments, selection sets, etc are left alone - name - phone { - home - } - ...EmploymentFragment - ... { - clearanceLevel - } - } - } - `); - - const { content } = await plugin( - schema, - [{ location: '', document: fragment }], - { - preResolveTypes: true, - }, - { outputFile: 'graphql.ts' }, - ); - - expect(content).toMatchInlineSnapshot(` - "export type WidgetFragmentFragment = { widgetCount: number }; - - export type EmploymentFragmentFragment = { employment: { title: string } }; - - export type UserQueryVariables = Exact<{ [key: string]: never; }>; - - - export type UserQuery = { user: { clearanceLevel: string, name: string, phone: { home: string }, employment: { title: string } } & ({ email: string } | { email?: never }) & ({ address: { street1: string } } | { address?: never }) & ({ widgetCount: number } | { widgetCount?: never }) }; - " - `); - }); - it('should resolve optionals according to maybeValue together with deferred fragments', async () => { const schema = buildSchema(/* GraphQL */ ` type Address { @@ -7486,10 +6224,7 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document: fragment }], - { - preResolveTypes: true, - maybeValue: "T | 'specialType'", - }, + { maybeValue: "T | 'specialType'" }, { outputFile: 'graphql.ts' }, ); @@ -7588,15 +6323,19 @@ function test(q: GetEntityBrandDataQuery): void { } `); - const { content } = await plugin( - schema, - [{ location: '', document: fragment }], - { preResolveTypes: true, inlineFragmentTypes: 'mask' }, - { outputFile: 'graphql.ts' }, - ); + const content = mergeOutputs([ + await plugin( + schema, + [{ location: '', document: fragment }], + { inlineFragmentTypes: 'mask' }, + { outputFile: 'graphql.ts' }, + ), + ]); expect(content).toMatchInlineSnapshot(` - "export type WidgetFragmentFragment = { widgetCount: number, widgetPreference: string } & { ' $fragmentName'?: 'WidgetFragmentFragment' }; + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type WidgetFragmentFragment = { widgetCount: number, widgetPreference: string } & { ' $fragmentName'?: 'WidgetFragmentFragment' }; export type FoodFragmentFragment = { favoriteFood: string, leastFavoriteFood: string } & { ' $fragmentName'?: 'FoodFragmentFragment' }; @@ -7626,7 +6365,7 @@ function test(q: GetEntityBrandDataQuery): void { const result = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { preResolveTypes: false }, + {}, { outputFile: '' }, ); expect(result.content).toMatchInlineSnapshot(` @@ -7634,8 +6373,8 @@ function test(q: GetEntityBrandDataQuery): void { export type Unnamed_1_Query = { notifications: Array< - | Pick - | Pick + | { id: string } + | { id: string } > }; " `); From c062fd8369236ff8ca4745f236eb4208cc66834e Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Tue, 6 Jan 2026 22:34:09 +1100 Subject: [PATCH 18/69] Adjust config inheritance to reflect usage and type-hint better (#10560) * Refactor utility function to match practice * Fix config option inheritance - addTypename/skipTypename: is only a types-visitor concern. This is moved to types-visitor from base-visitor - nonOptionalTypename: is a documents-visitor and types-visitor concern. Moved from base-visitor there - extractAllFieldsToTypes: is a documents-visitor concern. Moved from base-visitor there - enumPrefix and enumSuffix: need to be in base-visitor as all 3 types of visitors need this to correctly sync the enum type names. This is moved to base visitor - ignoreEnumValuesFromSchema: is a documents-visitor and types-visitor concern. Moved from base-visitor there. - globalNamespace: is a documents-visitor concern. Moved from base-visitor there Other changes: - documents-visitor no longer extends types-visitor _option types_ as they have two distinct usages now. The types now extend base-visitor types. This is now consistent with documents-visitor extending base-visitor - Classes now handle config parsing and types at the same level e.g. if typescript-operations plugin parses configOne, then the types for configOne must be in that class, rather than in base-documents-visitor * Remove references and tests related to skipTypename in operations plugin * Add changeset --- .changeset/brown-things-jump.md | 27 +++ .../src/base-documents-visitor.ts | 70 +++++-- .../src/base-resolvers-visitor.ts | 56 ------ .../src/base-types-visitor.ts | 141 +++++++------ .../visitor-plugin-common/src/base-visitor.ts | 53 +++-- .../src/selection-set-processor/base.ts | 4 +- .../src/selection-set-to-object.ts | 3 - .../typescript/operations/src/config.ts | 28 ++- .../typescript/operations/src/index.ts | 2 - .../typescript/operations/src/visitor.ts | 8 +- .../operations/tests/ts-documents.spec.ts | 188 +++--------------- 11 files changed, 234 insertions(+), 346 deletions(-) create mode 100644 .changeset/brown-things-jump.md diff --git a/.changeset/brown-things-jump.md b/.changeset/brown-things-jump.md new file mode 100644 index 00000000000..115b47b37f1 --- /dev/null +++ b/.changeset/brown-things-jump.md @@ -0,0 +1,27 @@ +--- +'@graphql-codegen/visitor-plugin-common': major +'@graphql-codegen/typescript-operations': major +'@graphql-codegen/typescript': major +'@graphql-codegen/typescript-resolvers': major +--- + +BREAKING CHANGE: visitors' config option are moved based on their use case + +- addTypename/skipTypename: is only a types-visitor concern. This is moved to types-visitor from base-visitor +- nonOptionalTypename: is a documents-visitor and types-visitor concern. Moved from base-visitor there +- extractAllFieldsToTypes: is a documents-visitor concern. Moved from base-visitor there +- enumPrefix and enumSuffix: need to be in base-visitor as all 3 types of visitors need this to correctly sync the enum type names. This is moved to base visitor +- ignoreEnumValuesFromSchema: is a documents-visitor and types-visitor concern. Moved from base-visitor there. +- globalNamespace: is a documents-visitor concern. Moved from base-visitor there + +Refactors + +- documents-visitor no longer extends types-visitor _option types_ as they have two distinct usages now. The types now extend base-visitor types. This is now consistent with documents-visitor extending base-visitor +- Classes now handle config parsing and types at the same level e.g. if typescript-operations plugin parses configOne, then the types for configOne must be in that class, rather than in base-documents-visitor + +Note: These visitors are rolled up into one type for simplicity + +- base-visitor: includes `base-visitor` +- documents-visitor: includes `base-documents-visitor` and `typescript-operations` visitor +- types-visitor: includes `base-types-visitor` and `typescript` visitor +- resolvers-visitor: includes `base-resolvers-visitor` and `typescript-resolvers` visitor diff --git a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts index a8281eabf00..d2d31b13497 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts @@ -7,8 +7,7 @@ import { OperationTypeNode, VariableDefinitionNode, } from 'graphql'; -import { ParsedTypesConfig, RawTypesConfig } from './base-types-visitor.js'; -import { BaseVisitor } from './base-visitor.js'; +import { BaseVisitor, type RawConfig, type ParsedConfig } from './base-visitor.js'; import { DEFAULT_SCALARS } from './scalars.js'; import { SelectionSetToObject } from './selection-set-to-object.js'; import { CustomDirectivesConfig, NormalizedScalarsMap } from './types.js'; @@ -20,27 +19,16 @@ import { } from './utils.js'; import { OperationVariablesToObject } from './variables-to-object.js'; -function getRootType(operation: OperationTypeNode, schema: GraphQLSchema) { - switch (operation) { - case 'query': - return schema.getQueryType(); - case 'mutation': - return schema.getMutationType(); - case 'subscription': - return schema.getSubscriptionType(); - } - throw new Error(`Unknown operation type: ${operation}`); -} - -export interface ParsedDocumentsConfig extends ParsedTypesConfig { +export interface ParsedDocumentsConfig extends ParsedConfig { extractAllFieldsToTypes: boolean; - globalNamespace: boolean; operationResultSuffix: string; dedupeOperationSuffix: boolean; omitOperationSuffix: boolean; namespacedImportName: string | null; exportFragmentSpreadSubTypes: boolean; skipTypeNameForRoot: boolean; + nonOptionalTypename: boolean; + globalNamespace: boolean; experimentalFragmentVariables: boolean; mergeFragmentTypes: boolean; customDirectives: CustomDirectivesConfig; @@ -48,7 +36,7 @@ export interface ParsedDocumentsConfig extends ParsedTypesConfig { importSchemaTypesFrom: string; } -export interface RawDocumentsConfig extends RawTypesConfig { +export interface RawDocumentsConfig extends RawConfig { /** * @default false * @description Avoid adding `__typename` for root types. This is ignored when a selection explicitly specifies `__typename`. @@ -72,6 +60,30 @@ export interface RawDocumentsConfig extends RawTypesConfig { * ``` */ skipTypeNameForRoot?: boolean; + /** + * @default false + * @description Automatically adds `__typename` field to the generated types, even when they are not specified + * in the selection set, and makes it non-optional + * + * @exampleMarkdown + * ```ts filename="codegen.ts" + * import type { CodegenConfig } from '@graphql-codegen/cli'; + * + * const config: CodegenConfig = { + * // ... + * generates: { + * 'path/to/file': { + * // plugins... + * config: { + * nonOptionalTypename: true + * }, + * }, + * }, + * }; + * export default config; + * ``` + */ + nonOptionalTypename?: boolean; /** * @default false * @description Puts all generated code under `global` namespace. Useful for Stencil integration. @@ -204,6 +216,14 @@ export interface RawDocumentsConfig extends RawTypesConfig { * ``` */ importSchemaTypesFrom?: string; + /** + * @default false + * @description Extract all field types to their own types, instead of inlining them. + * This helps to reduce type duplication, and makes type errors more readable. + * It can also significantly reduce the size of the generated code, the generation time, + * and the typechecking time. + */ + extractAllFieldsToTypes?: boolean; } export class BaseDocumentsVisitor< @@ -223,11 +243,10 @@ export class BaseDocumentsVisitor< ) { super(rawConfig, { exportFragmentSpreadSubTypes: getConfigValue(rawConfig.exportFragmentSpreadSubTypes, false), - enumPrefix: getConfigValue(rawConfig.enumPrefix, true), - enumSuffix: getConfigValue(rawConfig.enumSuffix, true), dedupeOperationSuffix: getConfigValue(rawConfig.dedupeOperationSuffix, false), omitOperationSuffix: getConfigValue(rawConfig.omitOperationSuffix, false), skipTypeNameForRoot: getConfigValue(rawConfig.skipTypeNameForRoot, false), + nonOptionalTypename: getConfigValue(rawConfig.nonOptionalTypename, false), namespacedImportName: getConfigValue(rawConfig.namespacedImportName, null), experimentalFragmentVariables: getConfigValue(rawConfig.experimentalFragmentVariables, false), globalNamespace: !!rawConfig.globalNamespace, @@ -238,6 +257,7 @@ export class BaseDocumentsVisitor< }), generatesOperationTypes: getConfigValue(rawConfig.generatesOperationTypes, true), importSchemaTypesFrom: getConfigValue(rawConfig.importSchemaTypesFrom, ''), + extractAllFieldsToTypes: getConfigValue(rawConfig.extractAllFieldsToTypes, false), ...((additionalConfig || {}) as any), }); @@ -394,3 +414,15 @@ export class BaseDocumentsVisitor< .join('\n\n'); } } + +function getRootType(operation: OperationTypeNode, schema: GraphQLSchema) { + switch (operation) { + case 'query': + return schema.getQueryType(); + case 'mutation': + return schema.getMutationType(); + case 'subscription': + return schema.getSubscriptionType(); + } + throw new Error(`Unknown operation type: ${operation}`); +} diff --git a/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts index ddd3dae132f..05ac1c49b06 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts @@ -79,8 +79,6 @@ export interface ParsedResolversConfig extends ParsedConfig { enumValues: ParsedEnumValuesMap; resolverTypeWrapperSignature: string; federation: boolean; - enumPrefix: boolean; - enumSuffix: boolean; optionalResolveType: boolean; immutableTypes: boolean; namespacedImportName: string; @@ -522,59 +520,7 @@ export interface RawResolversConfig extends RawConfig { * @description Supports Apollo Federation */ federation?: boolean; - /** - * @default true - * @description Allow you to disable prefixing for generated enums, works in combination with `typesPrefix`. - * - * @exampleMarkdown - * ## Disable enum prefixes - * - * ```ts filename="codegen.ts" - * import type { CodegenConfig } from '@graphql-codegen/cli'; - * - * const config: CodegenConfig = { - * // ... - * generates: { - * 'path/to/file': { - * plugins: ['typescript', 'typescript-resolver'], - * config: { - * typesPrefix: 'I', - * enumPrefix: false - * }, - * }, - * }, - * }; - * export default config; - * ``` - */ - enumPrefix?: boolean; - /** - * @default true - * @description Allow you to disable suffixing for generated enums, works in combination with `typesSuffix`. - * - * @exampleMarkdown - * ## Disable enum suffixes - * - * ```ts filename="codegen.ts" - * import type { CodegenConfig } from '@graphql-codegen/cli'; - * - * const config: CodegenConfig = { - * // ... - * generates: { - * 'path/to/file': { - * plugins: ['typescript', 'typescript-resolver'], - * config: { - * typesSuffix: 'I', - * enumSuffix: false - * }, - * }, - * }, - * }; - * export default config; - * ``` - */ - enumSuffix?: boolean; /** * @description Configures behavior for custom directives from various GraphQL libraries. * @exampleMarkdown @@ -811,8 +757,6 @@ export class BaseResolversVisitor< super(rawConfig, { immutableTypes: getConfigValue(rawConfig.immutableTypes, false), optionalResolveType: getConfigValue(rawConfig.optionalResolveType, false), - enumPrefix: getConfigValue(rawConfig.enumPrefix, true), - enumSuffix: getConfigValue(rawConfig.enumSuffix, true), federation: getConfigValue(rawConfig.federation, false), resolverTypeWrapperSignature: getConfigValue( rawConfig.resolverTypeWrapperSignature, diff --git a/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts index 536dc70adcd..88497273365 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts @@ -23,7 +23,7 @@ import { parseEnumValues } from './enum-values.js'; import { buildTypeImport, getEnumsImports } from './imports.js'; import { transformDirectiveArgumentAndInputFieldMappings } from './mappers.js'; import { DEFAULT_SCALARS } from './scalars.js'; -import { +import type { DeclarationKind, DeclarationKindConfig, DirectiveArgumentAndInputFieldMappings, @@ -47,18 +47,18 @@ import { OperationVariablesToObject } from './variables-to-object.js'; export interface ParsedTypesConfig extends ParsedConfig { enumValues: ParsedEnumValuesMap; + ignoreEnumValuesFromSchema: boolean; declarationKind: DeclarationKindConfig; addUnderscoreToArgsType: boolean; onlyEnums: boolean; onlyOperationTypes: boolean; - enumPrefix: boolean; - enumSuffix: boolean; fieldWrapperValue: string; wrapFieldDefinitions: boolean; entireFieldWrapperValue: string; wrapEntireDefinitions: boolean; - ignoreEnumValuesFromSchema: boolean; directiveArgumentAndInputFieldMappings: ParsedDirectiveArgumentAndInputFieldMappings; + addTypename: boolean; + nonOptionalTypename: boolean; } export interface RawTypesConfig extends RawConfig { @@ -155,29 +155,11 @@ export interface RawTypesConfig extends RawConfig { */ enumValues?: EnumValuesMap; /** - * @description Overrides the default output for various GraphQL elements. + * @description This will cause the generator to ignore enum values defined in GraphQLSchema + * @default false * * @exampleMarkdown - * ## Override all declarations - * - * ```ts filename="codegen.ts" - * import type { CodegenConfig } from '@graphql-codegen/cli'; - * - * const config: CodegenConfig = { - * // ... - * generates: { - * 'path/to/file': { - * // plugins... - * config: { - * declarationKind: 'interface' - * }, - * }, - * }, - * }; - * export default config; - * ``` - * - * ## Override only specific declarations + * ## Ignore enum values from schema * * ```ts filename="codegen.ts" * import type { CodegenConfig } from '@graphql-codegen/cli'; @@ -188,10 +170,7 @@ export interface RawTypesConfig extends RawConfig { * 'path/to/file': { * // plugins... * config: { - * declarationKind: { - * type: 'interface', - * input: 'interface' - * } + * ignoreEnumValuesFromSchema: true, * }, * }, * }, @@ -199,13 +178,12 @@ export interface RawTypesConfig extends RawConfig { * export default config; * ``` */ - declarationKind?: DeclarationKind | DeclarationKindConfig; + ignoreEnumValuesFromSchema?: boolean; /** - * @default true - * @description Allow you to disable prefixing for generated enums, works in combination with `typesPrefix`. + * @description Overrides the default output for various GraphQL elements. * * @exampleMarkdown - * ## Disable enum prefixes + * ## Override all declarations * * ```ts filename="codegen.ts" * import type { CodegenConfig } from '@graphql-codegen/cli'; @@ -216,22 +194,15 @@ export interface RawTypesConfig extends RawConfig { * 'path/to/file': { * // plugins... * config: { - * typesPrefix: 'I', - * enumPrefix: false + * declarationKind: 'interface' * }, * }, * }, * }; * export default config; * ``` - */ - enumPrefix?: boolean; - /** - * @default true - * @description Allow you to disable suffixing for generated enums, works in combination with `typesSuffix`. * - * @exampleMarkdown - * ## Disable enum suffixes + * ## Override only specific declarations * * ```ts filename="codegen.ts" * import type { CodegenConfig } from '@graphql-codegen/cli'; @@ -242,8 +213,10 @@ export interface RawTypesConfig extends RawConfig { * 'path/to/file': { * // plugins... * config: { - * typesSuffix: 'I', - * enumSuffix: false + * declarationKind: { + * type: 'interface', + * input: 'interface' + * } * }, * }, * }, @@ -251,7 +224,7 @@ export interface RawTypesConfig extends RawConfig { * export default config; * ``` */ - enumSuffix?: boolean; + declarationKind?: DeclarationKind | DeclarationKindConfig; /** * @description Allow you to add wrapper for field type, use T as the generic value. Make sure to set `wrapFieldDefinitions` to `true` in order to make this flag work. * @default T @@ -354,31 +327,6 @@ export interface RawTypesConfig extends RawConfig { * ``` */ onlyOperationTypes?: boolean; - /** - * @description This will cause the generator to ignore enum values defined in GraphQLSchema - * @default false - * - * @exampleMarkdown - * ## Ignore enum values from schema - * - * ```ts filename="codegen.ts" - * import type { CodegenConfig } from '@graphql-codegen/cli'; - * - * const config: CodegenConfig = { - * // ... - * generates: { - * 'path/to/file': { - * // plugins... - * config: { - * ignoreEnumValuesFromSchema: true, - * }, - * }, - * }, - * }; - * export default config; - * ``` - */ - ignoreEnumValuesFromSchema?: boolean; /** * @name wrapEntireFieldDefinitions * @type boolean @@ -492,6 +440,53 @@ export interface RawTypesConfig extends RawConfig { * ``` */ directiveArgumentAndInputFieldMappingTypeSuffix?: string; + /** + * @default false + * @description Does not add `__typename` to the generated types, unless it was specified in the selection set. + * + * @exampleMarkdown + * ```ts filename="codegen.ts" + * import type { CodegenConfig } from '@graphql-codegen/cli'; + * + * const config: CodegenConfig = { + * // ... + * generates: { + * 'path/to/file': { + * // plugins... + * config: { + * skipTypename: true + * }, + * }, + * }, + * }; + * export default config; + * ``` + */ + skipTypename?: boolean; + /** + * @default false + * @description Automatically adds `__typename` field to the generated types, even when they are not specified + * in the selection set, and makes it non-optional + * + * @exampleMarkdown + * ```ts filename="codegen.ts" + * import type { CodegenConfig } from '@graphql-codegen/cli'; + * + * const config: CodegenConfig = { + * // ... + * generates: { + * 'path/to/file': { + * // plugins... + * config: { + * nonOptionalTypename: true + * }, + * }, + * }, + * }; + * export default config; + * ``` + */ + nonOptionalTypename?: boolean; } export class BaseTypesVisitor< @@ -507,8 +502,6 @@ export class BaseTypesVisitor< defaultScalars: NormalizedScalarsMap = DEFAULT_SCALARS, ) { super(rawConfig, { - enumPrefix: getConfigValue(rawConfig.enumPrefix, true), - enumSuffix: getConfigValue(rawConfig.enumSuffix, true), onlyEnums: getConfigValue(rawConfig.onlyEnums, false), onlyOperationTypes: getConfigValue(rawConfig.onlyOperationTypes, false), addUnderscoreToArgsType: getConfigValue(rawConfig.addUnderscoreToArgsType, false), @@ -517,17 +510,19 @@ export class BaseTypesVisitor< mapOrStr: rawConfig.enumValues, ignoreEnumValuesFromSchema: rawConfig.ignoreEnumValuesFromSchema, }), + ignoreEnumValuesFromSchema: getConfigValue(rawConfig.ignoreEnumValuesFromSchema, false), declarationKind: normalizeDeclarationKind(rawConfig.declarationKind), scalars: buildScalarsFromConfig(_schema, rawConfig, defaultScalars), fieldWrapperValue: getConfigValue(rawConfig.fieldWrapperValue, 'T'), wrapFieldDefinitions: getConfigValue(rawConfig.wrapFieldDefinitions, false), entireFieldWrapperValue: getConfigValue(rawConfig.entireFieldWrapperValue, 'T'), wrapEntireDefinitions: getConfigValue(rawConfig.wrapEntireFieldDefinitions, false), - ignoreEnumValuesFromSchema: getConfigValue(rawConfig.ignoreEnumValuesFromSchema, false), directiveArgumentAndInputFieldMappings: transformDirectiveArgumentAndInputFieldMappings( rawConfig.directiveArgumentAndInputFieldMappings ?? {}, rawConfig.directiveArgumentAndInputFieldMappingTypeSuffix, ), + addTypename: !rawConfig.skipTypename, + nonOptionalTypename: getConfigValue(rawConfig.nonOptionalTypename, false), ...additionalConfig, }); diff --git a/packages/plugins/other/visitor-plugin-common/src/base-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-visitor.ts index 16caee72a4d..f1a8d0a196a 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-visitor.ts @@ -13,7 +13,7 @@ import { ParsedScalarsMap, ScalarsMap, } from './types.js'; -import { DeclarationBlockConfig } from './utils.js'; +import { DeclarationBlockConfig, getConfigValue } from './utils.js'; export interface BaseVisitorConvertOptions { useTypesPrefix?: boolean; @@ -27,9 +27,8 @@ export interface ParsedConfig { convert: ConvertFn; typesPrefix: string; typesSuffix: string; - addTypename: boolean; - nonOptionalTypename: boolean; - extractAllFieldsToTypes: boolean; + enumPrefix: boolean; + enumSuffix: boolean; externalFragments: LoadedFragment[]; fragmentImports: ImportDeclaration[]; immutableTypes: boolean; @@ -261,10 +260,12 @@ export interface RawConfig { */ typesSuffix?: string; /** - * @default false - * @description Does not add `__typename` to the generated types, unless it was specified in the selection set. + * @default true + * @description Allow you to disable prefixing for generated enums, works in combination with `typesPrefix`. * * @exampleMarkdown + * ## Disable enum prefixes + * * ```ts filename="codegen.ts" * import type { CodegenConfig } from '@graphql-codegen/cli'; * @@ -274,7 +275,8 @@ export interface RawConfig { * 'path/to/file': { * // plugins... * config: { - * skipTypename: true + * typesPrefix: 'I', + * enumPrefix: false * }, * }, * }, @@ -282,13 +284,14 @@ export interface RawConfig { * export default config; * ``` */ - skipTypename?: boolean; + enumPrefix?: boolean; /** - * @default false - * @description Automatically adds `__typename` field to the generated types, even when they are not specified - * in the selection set, and makes it non-optional + * @default true + * @description Allow you to disable suffixing for generated enums, works in combination with `typesSuffix`. * * @exampleMarkdown + * ## Disable enum suffixes + * * ```ts filename="codegen.ts" * import type { CodegenConfig } from '@graphql-codegen/cli'; * @@ -298,7 +301,8 @@ export interface RawConfig { * 'path/to/file': { * // plugins... * config: { - * nonOptionalTypename: true + * typesSuffix: 'I', + * enumSuffix: false * }, * }, * }, @@ -306,7 +310,7 @@ export interface RawConfig { * export default config; * ``` */ - nonOptionalTypename?: boolean; + enumSuffix?: boolean; /** * @name useTypeImports * @type boolean @@ -343,10 +347,6 @@ export interface RawConfig { * @ignore */ fragmentImports?: ImportDeclaration[]; - /** - * @ignore - */ - globalNamespace?: boolean; /** * @ignore */ @@ -374,15 +374,6 @@ export interface RawConfig { */ importExtension?: '' | `.${string}`; - /** - * @default false - * @description Extract all field types to their own types, instead of inlining them. - * This helps to reduce type duplication, and makes type errors more readable. - * It can also significantly reduce the size of the generated code, the generation time, - * and the typechecking time. - */ - extractAllFieldsToTypes?: boolean; - /** * @default false * @description If you prefer to have each field in generated types printed on a new line, set this to true. @@ -416,16 +407,18 @@ export class BaseVisitor< convert: convertFactory(rawConfig), typesPrefix: rawConfig.typesPrefix || '', typesSuffix: rawConfig.typesSuffix || '', + enumPrefix: getConfigValue(rawConfig.enumPrefix, true), + enumSuffix: getConfigValue(rawConfig.enumSuffix, true), externalFragments: rawConfig.externalFragments || [], fragmentImports: rawConfig.fragmentImports || [], - addTypename: !rawConfig.skipTypename, - nonOptionalTypename: !!rawConfig.nonOptionalTypename, useTypeImports: !!rawConfig.useTypeImports, allowEnumStringTypes: !!rawConfig.allowEnumStringTypes, inlineFragmentTypes: rawConfig.inlineFragmentTypes ?? 'inline', - emitLegacyCommonJSImports: rawConfig.emitLegacyCommonJSImports ?? true, + emitLegacyCommonJSImports: + rawConfig.emitLegacyCommonJSImports === undefined + ? true + : !!rawConfig.emitLegacyCommonJSImports, importExtension, - extractAllFieldsToTypes: rawConfig.extractAllFieldsToTypes ?? false, printFieldsOnNewLines: rawConfig.printFieldsOnNewLines ?? false, includeExternalFragments: rawConfig.includeExternalFragments ?? false, ...((additionalConfig || {}) as any), diff --git a/packages/plugins/other/visitor-plugin-common/src/selection-set-processor/base.ts b/packages/plugins/other/visitor-plugin-common/src/selection-set-processor/base.ts index 8fc8b34a153..5a86ca303f8 100644 --- a/packages/plugins/other/visitor-plugin-common/src/selection-set-processor/base.ts +++ b/packages/plugins/other/visitor-plugin-common/src/selection-set-processor/base.ts @@ -25,8 +25,8 @@ export type ProcessResult = null | Array; export type SelectionSetProcessorConfig = { namespacedImportName: string | null; convertName: ConvertNameFn; - enumPrefix: boolean | null; - enumSuffix: boolean | null; + enumPrefix: boolean; + enumSuffix: boolean; scalars: NormalizedScalarsMap; formatNamedField(params: { name: string; isOptional?: boolean }): string; wrapTypeWithModifiers(baseType: string, type: GraphQLOutputType | GraphQLNamedType): string; diff --git a/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts b/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts index 095f6cdd202..400c7411e60 100644 --- a/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts +++ b/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts @@ -553,9 +553,6 @@ export class SelectionSetToObject< // The keys here will be used to generate intermediary // fragment names. To avoid blowing up the type name on large // unions, calculate a stable hash here instead. - // - // Also use fragment hashing if skipTypename is true, since we - // then don't have a typename for naming the fragment. acc[ selectedTypes.length <= 3 ? // Remove quote marks to produce a valid type name diff --git a/packages/plugins/typescript/operations/src/config.ts b/packages/plugins/typescript/operations/src/config.ts index 44fb213b786..9dcbcb6ce01 100644 --- a/packages/plugins/typescript/operations/src/config.ts +++ b/packages/plugins/typescript/operations/src/config.ts @@ -186,7 +186,6 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { * ``` */ noExport?: boolean; - globalNamespace?: boolean; /** * @name addOperationExport * @type boolean @@ -364,7 +363,6 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { * export default config */ enumType?: ConvertSchemaEnumToDeclarationBlockString['outputType']; - /** * @description Overrides the default value of enum values declared in your GraphQL schema. * You can also map the entire enum to an external type by providing a string that of `module#type`. @@ -433,7 +431,31 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { * ``` */ enumValues?: EnumValuesMap; - + /** + * @description This will cause the generator to ignore enum values defined in GraphQLSchema + * @default false + * + * @exampleMarkdown + * ## Ignore enum values from schema + * + * ```ts filename="codegen.ts" + * import type { CodegenConfig } from '@graphql-codegen/cli'; + * + * const config: CodegenConfig = { + * // ... + * generates: { + * 'path/to/file': { + * // plugins... + * config: { + * ignoreEnumValuesFromSchema: true, + * }, + * }, + * }, + * }; + * export default config; + * ``` + */ + ignoreEnumValuesFromSchema?: boolean; /** * @description This option controls whether or not a catch-all entry is added to enum type definitions for values that may be added in the future. * This is useful if you are using `relay`. diff --git a/packages/plugins/typescript/operations/src/index.ts b/packages/plugins/typescript/operations/src/index.ts index 1a65049286b..5812d201c80 100644 --- a/packages/plugins/typescript/operations/src/index.ts +++ b/packages/plugins/typescript/operations/src/index.ts @@ -5,8 +5,6 @@ import { optimizeOperations } from '@graphql-codegen/visitor-plugin-common'; import { TypeScriptDocumentsPluginConfig } from './config.js'; import { TypeScriptDocumentsVisitor } from './visitor.js'; -export { TypeScriptDocumentsPluginConfig } from './config.js'; - export const plugin: PluginFunction< TypeScriptDocumentsPluginConfig, Types.ComplexPluginOutput diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 4facfc4daa8..f9490260a62 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -59,8 +59,9 @@ export interface TypeScriptDocumentsParsedConfig extends ParsedDocumentsConfig { maybeValue: string; allowUndefinedQueryVariables: boolean; enumType: ConvertSchemaEnumToDeclarationBlockString['outputType']; - futureProofEnums: boolean; enumValues: ParsedEnumValuesMap; + ignoreEnumValuesFromSchema: boolean; + futureProofEnums: boolean; } type UsedNamedInputTypes = Record< @@ -99,6 +100,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< mapOrStr: config.enumValues, ignoreEnumValuesFromSchema: config.ignoreEnumValuesFromSchema, }), + ignoreEnumValuesFromSchema: getConfigValue(config.ignoreEnumValuesFromSchema, false), futureProofEnums: getConfigValue(config.futureProofEnums, false), } as TypeScriptDocumentsParsedConfig, schema, @@ -146,10 +148,10 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< }, printFieldsOnNewLines: this.config.printFieldsOnNewLines, }; - const processor = new PreResolveTypesProcessor(processorConfig); + this.setSelectionSetHandler( new SelectionSetToObject( - processor, + new PreResolveTypesProcessor(processorConfig), this.scalars, this.schema, this.convertName.bind(this), diff --git a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts index 2847de13cda..ba6e0379c0a 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts @@ -810,7 +810,7 @@ describe('TypeScript Operations Plugin', () => { await validate(content); }); - it('Should add __typename correctly with nonOptionalTypename=false,skipTypename=true and explicit field', async () => { + it('Should add __typename correctly with nonOptionalTypename=false and explicit field', async () => { const testSchema = buildSchema(/* GraphQL */ ` type Search { search: [SearchResult!]! @@ -865,10 +865,7 @@ describe('TypeScript Operations Plugin', () => { const { content } = await plugin( testSchema, [{ location: 'test-file.ts', document: ast }], - { - nonOptionalTypename: false, - skipTypename: true, - }, + { nonOptionalTypename: false }, { outputFile: '' }, ); @@ -889,24 +886,6 @@ export type Q2Query = { search: Array< await validate(content); }); - it('Should skip __typename when skipTypename is set to true', async () => { - const ast = parse(/* GraphQL */ ` - query { - dummy - } - `); - - const { content } = await plugin( - schema, - [{ location: 'test-file.ts', document: ast }], - { skipTypename: true }, - { outputFile: '' }, - ); - - expect(content).not.toContain(`__typename`); - await validate(content); - }); - it('Should add __typename when dealing with fragments', async () => { const testSchema = buildSchema(/* GraphQL */ ` interface Node { @@ -1039,31 +1018,6 @@ export type Q2Query = { search: Array< await validate(content); }); - it('Should add __typename as non-optional when its explictly specified, even if skipTypename is true', async () => { - const ast = parse(/* GraphQL */ ` - query { - __typename - dummy - } - `); - - const { content } = await plugin( - schema, - [{ location: 'test-file.ts', document: ast }], - { skipTypename: true }, - { outputFile: '' }, - ); - - expect(content).toMatchInlineSnapshot(` - "export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - - - export type Unnamed_1_Query = { __typename: 'Query', dummy: string | null }; - " - `); - await validate(content); - }); - it('Should add __typename correctly when unions are in use and nonOptionalTypename=true', async () => { const ast = parse(/* GraphQL */ ` query unionTest { @@ -1215,7 +1169,7 @@ export type Q2Query = { search: Array< const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { skipTypename: true }, + {}, { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` @@ -1249,7 +1203,7 @@ export type Q2Query = { search: Array< const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { skipTypename: true }, + {}, { outputFile: '' }, ); @@ -1690,7 +1644,7 @@ export type Q2Query = { search: Array< const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { skipTypename: true }, + {}, { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` @@ -1729,7 +1683,7 @@ export type Q2Query = { search: Array< const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { skipTypename: true }, + {}, { outputFile: '' }, ); @@ -1769,7 +1723,7 @@ export type Q2Query = { search: Array< const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { skipTypename: false }, + {}, { outputFile: '' }, ); @@ -2285,7 +2239,7 @@ export type Q2Query = { search: Array< await validate(content); }); - it('Should support merging identical fragment union types with skipTypename', async () => { + it('Should support merging identical fragment union types', async () => { const ast = parse(/* GraphQL */ ` query test { notifications { @@ -2301,7 +2255,10 @@ export type Q2Query = { search: Array< const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { skipTypename: true, mergeFragmentTypes: true, namingConvention: 'keep' }, + { + mergeFragmentTypes: true, + namingConvention: 'keep', + }, { outputFile: '' }, ); @@ -2317,7 +2274,7 @@ export type Q2Query = { search: Array< await validate(content); }); - it('Should support computing correct names for merged fragment union types with skipTypename', async () => { + it('Should support computing correct names for merged fragment union types', async () => { const ast = parse(/* GraphQL */ ` fragment N on Notifiction { id @@ -2330,7 +2287,10 @@ export type Q2Query = { search: Array< const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { skipTypename: true, mergeFragmentTypes: true, namingConvention: 'keep' }, + { + mergeFragmentTypes: true, + namingConvention: 'keep', + }, { outputFile: '' }, ); @@ -2408,7 +2368,7 @@ export type Q2Query = { search: Array< const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { skipTypename: true }, + {}, { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` @@ -2443,7 +2403,7 @@ export type Q2Query = { search: Array< const { content } = await plugin( gitHuntSchema, [{ location: 'test-file.ts', document: ast }], - { skipTypename: true }, + {}, { outputFile: '' }, ); @@ -2458,16 +2418,6 @@ export type Q2Query = { search: Array< " `, ); - - expect(content).toMatchInlineSnapshot(` - "export type MeQueryVariables = Exact<{ - repoFullName: string; - }>; - - - export type MeQuery = { currentUser: { login: string, html_url: string } | null, entry: { id: number, createdAt: number, postedBy: { login: string, html_url: string } } | null }; - " - `); await validate(content); }); @@ -2704,7 +2654,7 @@ export type Q2Query = { search: Array< const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { skipTypename: true }, + {}, { outputFile: '' }, ); @@ -2731,7 +2681,7 @@ export type Q2Query = { search: Array< const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { skipTypename: true }, + {}, { outputFile: '' }, ); @@ -2762,7 +2712,7 @@ export type Q2Query = { search: Array< const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { skipTypename: true }, + {}, { outputFile: '' }, ); @@ -2796,7 +2746,7 @@ export type Q2Query = { search: Array< const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { skipTypename: true }, + {}, { outputFile: '' }, ); @@ -2825,7 +2775,7 @@ export type Q2Query = { search: Array< const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { skipTypename: true }, + {}, { outputFile: '' }, ); @@ -2849,7 +2799,7 @@ export type Q2Query = { search: Array< const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { skipTypename: false }, + {}, { outputFile: '' }, ); @@ -2875,7 +2825,7 @@ export type Q2Query = { search: Array< const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { skipTypename: true }, + {}, { outputFile: '' }, ); @@ -2908,7 +2858,7 @@ export type Q2Query = { search: Array< const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { skipTypename: true }, + {}, { outputFile: '' }, ); @@ -2947,7 +2897,7 @@ export type Q2Query = { search: Array< const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { skipTypename: true }, + {}, { outputFile: '' }, ); @@ -2975,7 +2925,7 @@ export type Q2Query = { search: Array< const { content } = await plugin( schema, [{ location: 'test-file.ts', document: ast }], - { skipTypename: true }, + {}, { outputFile: '' }, ); @@ -4620,10 +4570,7 @@ export type Q2Query = { search: Array< const { content } = await plugin( testSchema, [{ location: '', document: query }], - { - skipTypename: true, - namespacedImportName: 'Types', - }, + { namespacedImportName: 'Types' }, { outputFile: 'graphql.ts' }, ); @@ -5062,76 +5009,7 @@ function test(q: GetEntityBrandDataQuery): void { `); }); - it('#3950 - Invalid output with fragments and skipTypename: true', async () => { - const schema = buildSchema(/* GraphQL */ ` - type Query { - animals: [Animal!]! - } - - interface Animal { - id: ID! - } - type Duck implements Animal { - id: ID! - } - type Lion implements Animal { - id: ID! - } - type Puma implements Animal { - id: ID! - } - type Wolf implements Animal { - id: ID! - } - `); - - const query = parse(/* GraphQL */ ` - fragment CatFragment on Animal { - ... on Lion { - id - } - ... on Puma { - id - } - } - - query kitty { - animals { - ...CatFragment - } - } - `); - - const { content } = await plugin( - schema, - [{ location: '', document: query }], - { skipTypename: true }, - { outputFile: 'graphql.ts' }, - ); - - expect(content).toMatchInlineSnapshot(` - "type CatFragment_Lion_Fragment = { id: string }; - - type CatFragment_Puma_Fragment = { id: string }; - - export type CatFragmentFragment = - | CatFragment_Lion_Fragment - | CatFragment_Puma_Fragment - ; - - export type KittyQueryVariables = Exact<{ [key: string]: never; }>; - - - export type KittyQuery = { animals: Array< - | { id: string } - | { id: string } - | Record - > }; - " - `); - }); - - it('#3950 - Invalid output with fragments and skipTypename: false', async () => { + it('#3950 - Invalid output with fragments', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { animals: [Animal!]! @@ -5174,7 +5052,7 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document: query }], - { skipTypename: false }, + {}, { outputFile: 'graphql.ts' }, ); @@ -5232,7 +5110,7 @@ function test(q: GetEntityBrandDataQuery): void { const { content } = await plugin( schema, [{ location: '', document: query }], - { skipTypename: true }, + {}, { outputFile: 'graphql.ts' }, ); From 6055f6b4254a61d9ecd224b06aa1450567ad2203 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 6 Jan 2026 13:16:50 +0000 Subject: [PATCH 19/69] chore(dependencies): updated changesets for modified dependencies --- .changeset/@graphql-codegen_cli-10496-dependencies.md | 6 ------ ...graphql-codegen_client-preset-10496-dependencies.md | 10 ---------- ...ql-codegen_gql-tag-operations-10496-dependencies.md | 6 ------ ...odegen_graphql-modules-preset-10496-dependencies.md | 6 ------ ...l-codegen_typed-document-node-10496-dependencies.md | 6 ------ .../@graphql-codegen_typescript-10496-dependencies.md | 6 ------ ...gen_typescript-document-nodes-10496-dependencies.md | 6 ------ ...codegen_typescript-operations-10496-dependencies.md | 7 ------- ...-codegen_typescript-resolvers-10496-dependencies.md | 7 ------- ...codegen_visitor-plugin-common-10496-dependencies.md | 5 ----- 10 files changed, 65 deletions(-) delete mode 100644 .changeset/@graphql-codegen_cli-10496-dependencies.md delete mode 100644 .changeset/@graphql-codegen_client-preset-10496-dependencies.md delete mode 100644 .changeset/@graphql-codegen_gql-tag-operations-10496-dependencies.md delete mode 100644 .changeset/@graphql-codegen_graphql-modules-preset-10496-dependencies.md delete mode 100644 .changeset/@graphql-codegen_typed-document-node-10496-dependencies.md delete mode 100644 .changeset/@graphql-codegen_typescript-10496-dependencies.md delete mode 100644 .changeset/@graphql-codegen_typescript-document-nodes-10496-dependencies.md delete mode 100644 .changeset/@graphql-codegen_typescript-operations-10496-dependencies.md delete mode 100644 .changeset/@graphql-codegen_typescript-resolvers-10496-dependencies.md delete mode 100644 .changeset/@graphql-codegen_visitor-plugin-common-10496-dependencies.md diff --git a/.changeset/@graphql-codegen_cli-10496-dependencies.md b/.changeset/@graphql-codegen_cli-10496-dependencies.md deleted file mode 100644 index 1da26fe3256..00000000000 --- a/.changeset/@graphql-codegen_cli-10496-dependencies.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@graphql-codegen/cli": patch ---- -dependencies updates: - - Updated dependency [`@graphql-codegen/client-preset@^5.2.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/client-preset/v/5.2.0) (from `^5.1.2`, in `dependencies`) - - Updated dependency [`@graphql-codegen/plugin-helpers@^6.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers/v/6.1.0) (from `^6.0.0`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_client-preset-10496-dependencies.md b/.changeset/@graphql-codegen_client-preset-10496-dependencies.md deleted file mode 100644 index aa76a06c453..00000000000 --- a/.changeset/@graphql-codegen_client-preset-10496-dependencies.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -"@graphql-codegen/client-preset": patch ---- -dependencies updates: - - Updated dependency [`@graphql-codegen/typed-document-node@^6.1.3` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typed-document-node/v/6.1.3) (from `^6.1.2`, in `dependencies`) - - Updated dependency [`@graphql-codegen/typescript@^5.0.5` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.5) (from `^5.0.4`, in `dependencies`) - - Updated dependency [`@graphql-codegen/typescript-operations@^5.0.5` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript-operations/v/5.0.5) (from `^5.0.4`, in `dependencies`) - - Updated dependency [`@graphql-codegen/gql-tag-operations@5.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/gql-tag-operations/v/5.1.0) (from `5.0.5`, in `dependencies`) - - Updated dependency [`@graphql-codegen/plugin-helpers@^6.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers/v/6.1.0) (from `^6.0.0`, in `dependencies`) - - Updated dependency [`@graphql-codegen/visitor-plugin-common@^6.2.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/visitor-plugin-common/v/6.2.0) (from `^6.1.2`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_gql-tag-operations-10496-dependencies.md b/.changeset/@graphql-codegen_gql-tag-operations-10496-dependencies.md deleted file mode 100644 index 8b556536d8a..00000000000 --- a/.changeset/@graphql-codegen_gql-tag-operations-10496-dependencies.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@graphql-codegen/gql-tag-operations": patch ---- -dependencies updates: - - Updated dependency [`@graphql-codegen/plugin-helpers@^6.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers/v/6.1.0) (from `^6.0.0`, in `dependencies`) - - Updated dependency [`@graphql-codegen/visitor-plugin-common@6.2.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/visitor-plugin-common/v/6.2.0) (from `6.1.2`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_graphql-modules-preset-10496-dependencies.md b/.changeset/@graphql-codegen_graphql-modules-preset-10496-dependencies.md deleted file mode 100644 index 5251ebebfdb..00000000000 --- a/.changeset/@graphql-codegen_graphql-modules-preset-10496-dependencies.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@graphql-codegen/graphql-modules-preset": patch ---- -dependencies updates: - - Updated dependency [`@graphql-codegen/plugin-helpers@^6.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers/v/6.1.0) (from `^6.0.0`, in `dependencies`) - - Updated dependency [`@graphql-codegen/visitor-plugin-common@6.2.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/visitor-plugin-common/v/6.2.0) (from `6.1.2`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typed-document-node-10496-dependencies.md b/.changeset/@graphql-codegen_typed-document-node-10496-dependencies.md deleted file mode 100644 index ffc6eb27d68..00000000000 --- a/.changeset/@graphql-codegen_typed-document-node-10496-dependencies.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@graphql-codegen/typed-document-node": patch ---- -dependencies updates: - - Updated dependency [`@graphql-codegen/plugin-helpers@^6.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers/v/6.1.0) (from `^6.0.0`, in `dependencies`) - - Updated dependency [`@graphql-codegen/visitor-plugin-common@6.2.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/visitor-plugin-common/v/6.2.0) (from `6.1.2`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typescript-10496-dependencies.md b/.changeset/@graphql-codegen_typescript-10496-dependencies.md deleted file mode 100644 index 7f1cbc7a52e..00000000000 --- a/.changeset/@graphql-codegen_typescript-10496-dependencies.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@graphql-codegen/typescript": patch ---- -dependencies updates: - - Updated dependency [`@graphql-codegen/plugin-helpers@^6.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers/v/6.1.0) (from `^6.0.0`, in `dependencies`) - - Updated dependency [`@graphql-codegen/visitor-plugin-common@6.2.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/visitor-plugin-common/v/6.2.0) (from `6.1.2`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typescript-document-nodes-10496-dependencies.md b/.changeset/@graphql-codegen_typescript-document-nodes-10496-dependencies.md deleted file mode 100644 index e26048ceb9c..00000000000 --- a/.changeset/@graphql-codegen_typescript-document-nodes-10496-dependencies.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@graphql-codegen/typescript-document-nodes": patch ---- -dependencies updates: - - Updated dependency [`@graphql-codegen/plugin-helpers@^6.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers/v/6.1.0) (from `^6.0.0`, in `dependencies`) - - Updated dependency [`@graphql-codegen/visitor-plugin-common@6.2.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/visitor-plugin-common/v/6.2.0) (from `6.1.2`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md b/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md deleted file mode 100644 index f987ce2292c..00000000000 --- a/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@graphql-codegen/typescript-operations": patch ---- -dependencies updates: - - Updated dependency [`@graphql-codegen/plugin-helpers@^6.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers/v/6.1.0) (from `^6.0.0`, in `dependencies`) - - Updated dependency [`@graphql-codegen/typescript@^5.0.5` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.5) (from `^5.0.4`, in `dependencies`) - - Updated dependency [`@graphql-codegen/visitor-plugin-common@6.2.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/visitor-plugin-common/v/6.2.0) (from `6.1.2`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typescript-resolvers-10496-dependencies.md b/.changeset/@graphql-codegen_typescript-resolvers-10496-dependencies.md deleted file mode 100644 index 90c2beaf989..00000000000 --- a/.changeset/@graphql-codegen_typescript-resolvers-10496-dependencies.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@graphql-codegen/typescript-resolvers": patch ---- -dependencies updates: - - Updated dependency [`@graphql-codegen/plugin-helpers@^6.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers/v/6.1.0) (from `^6.0.0`, in `dependencies`) - - Updated dependency [`@graphql-codegen/typescript@^5.0.5` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.5) (from `^5.0.4`, in `dependencies`) - - Updated dependency [`@graphql-codegen/visitor-plugin-common@6.2.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/visitor-plugin-common/v/6.2.0) (from `6.1.2`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_visitor-plugin-common-10496-dependencies.md b/.changeset/@graphql-codegen_visitor-plugin-common-10496-dependencies.md deleted file mode 100644 index 7e6a61d5d42..00000000000 --- a/.changeset/@graphql-codegen_visitor-plugin-common-10496-dependencies.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@graphql-codegen/visitor-plugin-common": patch ---- -dependencies updates: - - Updated dependency [`@graphql-codegen/plugin-helpers@^6.1.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/plugin-helpers/v/6.1.0) (from `^6.0.0`, in `dependencies`) From a02b8589ca0f4aaaacdc9e5cefddfccf7e6589ea Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Wed, 7 Jan 2026 23:15:47 +1100 Subject: [PATCH 20/69] Fix issues after rebasing (#10563) * Fix missing dep * chore(dependencies): updated changesets for modified dependencies * Fix dev-tests --------- Co-authored-by: github-actions[bot] --- ...ypescript-operations-10563-dependencies.md | 5 ++++ .../typescript/operations/package.json | 2 +- .../typescript/operations/src/index.ts | 2 +- .../tests/extract-all-types.spec.ts | 25 +++++++++---------- 4 files changed, 19 insertions(+), 15 deletions(-) create mode 100644 .changeset/@graphql-codegen_typescript-operations-10563-dependencies.md diff --git a/.changeset/@graphql-codegen_typescript-operations-10563-dependencies.md b/.changeset/@graphql-codegen_typescript-operations-10563-dependencies.md new file mode 100644 index 00000000000..e66f900bbf7 --- /dev/null +++ b/.changeset/@graphql-codegen_typescript-operations-10563-dependencies.md @@ -0,0 +1,5 @@ +--- +"@graphql-codegen/typescript-operations": patch +--- +dependencies updates: + - Added dependency [`@graphql-codegen/schema-ast@^5.0.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/schema-ast/v/5.0.0) (to `dependencies`) diff --git a/packages/plugins/typescript/operations/package.json b/packages/plugins/typescript/operations/package.json index 437c8049e46..b8c9abf5480 100644 --- a/packages/plugins/typescript/operations/package.json +++ b/packages/plugins/typescript/operations/package.json @@ -47,7 +47,7 @@ }, "dependencies": { "@graphql-codegen/plugin-helpers": "^6.3.0", - "@graphql-codegen/typescript": "^5.0.10", + "@graphql-codegen/schema-ast": "^5.0.1", "@graphql-codegen/visitor-plugin-common": "^6.3.0", "auto-bind": "~4.0.0", "tslib": "^2.8.0" diff --git a/packages/plugins/typescript/operations/src/index.ts b/packages/plugins/typescript/operations/src/index.ts index 5812d201c80..7ac24ee1054 100644 --- a/packages/plugins/typescript/operations/src/index.ts +++ b/packages/plugins/typescript/operations/src/index.ts @@ -103,7 +103,7 @@ export const plugin: PluginFunction< }; }; -export { TypeScriptDocumentsVisitor }; +export { TypeScriptDocumentsVisitor, type TypeScriptDocumentsPluginConfig }; const semanticToStrict = async (schema: GraphQLSchema): Promise => { try { diff --git a/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts b/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts index b3e18d517d8..90e191c179a 100644 --- a/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts @@ -1,12 +1,11 @@ import { buildSchema, parse } from 'graphql'; import { mergeOutputs, Types } from '@graphql-codegen/plugin-helpers'; import { validateTs } from '@graphql-codegen/testing'; -import { plugin as tsPlugin } from '../../typescript/src/index.js'; -import { plugin, TypeScriptDocumentsPluginConfig } from '../src/index.js'; +import { plugin, type TypeScriptDocumentsPluginConfig } from '../src/index.js'; describe('extractAllFieldsToTypes: true', () => { - const validate = async (content: Types.PluginOutput, config: any = {}, pluginSchema) => { - const m = mergeOutputs([await tsPlugin(pluginSchema, [], config, { outputFile: '' }), content]); + const validate = async (content: Types.PluginOutput) => { + const m = mergeOutputs([content]); validateTs(m, undefined, undefined, undefined, []); return m; @@ -197,7 +196,7 @@ describe('extractAllFieldsToTypes: true', () => { " `); - await validate(content, config, dummyUserTestSchema); + await validate(content); }); const complexTestSchemaWithUnionsAndInterfaces = buildSchema(/* GraphQL */ ` @@ -551,7 +550,7 @@ describe('extractAllFieldsToTypes: true', () => { " `); - await validate(content, config, complexTestSchemaWithUnionsAndInterfaces); + await validate(content); }); it('should extract types from multiple fragments (mergeFragmentTypes: true)', async () => { @@ -725,7 +724,7 @@ describe('extractAllFieldsToTypes: true', () => { " `); - await validate(content, config, complexTestSchemaWithUnionsAndInterfaces); + await validate(content); }); it("should extract types from multiple fragments (inlineFragmentTypes: 'combine')", async () => { @@ -968,7 +967,7 @@ describe('extractAllFieldsToTypes: true', () => { " `); - await validate(content, config, complexTestSchemaWithUnionsAndInterfaces); + await validate(content); }); it("should extract types from multiple fragments (inlineFragmentTypes: 'mask')", async () => { @@ -1209,7 +1208,7 @@ describe('extractAllFieldsToTypes: true', () => { " `); - await validate(content, config, complexTestSchemaWithUnionsAndInterfaces); + await validate(content); }); it('fields with shared types and no fragments should use the shared type interface name', async () => { @@ -1302,7 +1301,7 @@ describe('extractAllFieldsToTypes: true', () => { " `); - await validate(content, config, nestedInterfacesSchema); + await validate(content); }); it('fragment spreads on the same interface should not force concrete parent type names (regression #10502)', async () => { @@ -1408,7 +1407,7 @@ describe('extractAllFieldsToTypes: true', () => { " `); - await validate(content, config, interfaceFragmentSchema); + await validate(content); }); // Exception case for Issue #10502 - shared schema for fragment tests @@ -1517,7 +1516,7 @@ describe('extractAllFieldsToTypes: true', () => { export type GetNotificationsQuery = GetNotificationsQuery_Query; " `); - await validate(content, config, notificationSchema); + await validate(content); }); it('named fragments should use their name and not parent type name', async () => { @@ -1598,6 +1597,6 @@ describe('extractAllFieldsToTypes: true', () => { export type GetNotificationsQuery = GetNotificationsQuery_Query; " `); - await validate(content, config, notificationSchema); + await validate(content); }); }); From 8e4eab899fbb57717ce59e89a1fc878ec7fbcc88 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 7 Jan 2026 12:16:09 +0000 Subject: [PATCH 21/69] chore(dependencies): updated changesets for modified dependencies --- ...aphql-codegen_typescript-operations-10496-dependencies.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/@graphql-codegen_typescript-operations-10496-dependencies.md diff --git a/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md b/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md new file mode 100644 index 00000000000..e66f900bbf7 --- /dev/null +++ b/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md @@ -0,0 +1,5 @@ +--- +"@graphql-codegen/typescript-operations": patch +--- +dependencies updates: + - Added dependency [`@graphql-codegen/schema-ast@^5.0.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/schema-ast/v/5.0.0) (to `dependencies`) From 7f447494f8138426e0eff542129a05ff614f02df Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Thu, 8 Jan 2026 00:09:23 +1100 Subject: [PATCH 22/69] Remove unused utility types and functions (#10564) * Remove MakeOptional MakeMaybe MakeEmpty and Incremental utitlity types from typescript plugin because they were used for typescript-operations * Fix unit tests * Remove deprecated functions * Add changeset --- .changeset/twelve-trams-pump.md | 13 ++++++++ dev-test/modules/types.ts | 8 ----- dev-test/subpath-import/result.d.ts | 8 ----- dev-test/test-federation/generated/types.ts | 8 ----- dev-test/test-schema/env.types.ts | 8 ----- dev-test/test-schema/resolvers-federation.ts | 8 ----- dev-test/test-schema/resolvers-root.ts | 8 ----- dev-test/test-schema/resolvers-stitching.ts | 8 ----- dev-test/test-schema/resolvers-types.ts | 8 ----- .../test-schema/typings.avoidOptionals.ts | 8 ----- dev-test/test-schema/typings.enum.ts | 8 ----- .../test-schema/typings.immutableTypes.ts | 8 ----- dev-test/test-schema/typings.ts | 8 ----- dev-test/test-schema/typings.wrapped.ts | 10 ------ .../typescript-resolvers/src/type-defs.d.ts | 8 ----- .../other/visitor-plugin-common/src/utils.ts | 7 ---- .../__snapshots__/ts-resolvers.spec.ts.snap | 8 ----- .../typescript/typescript/src/visitor.ts | 32 +------------------ 18 files changed, 14 insertions(+), 160 deletions(-) create mode 100644 .changeset/twelve-trams-pump.md diff --git a/.changeset/twelve-trams-pump.md b/.changeset/twelve-trams-pump.md new file mode 100644 index 00000000000..6ec52b480bf --- /dev/null +++ b/.changeset/twelve-trams-pump.md @@ -0,0 +1,13 @@ +--- +'@graphql-codegen/visitor-plugin-common': major +'@graphql-codegen/typescript': major +--- + +BREAKING CHANGE: Remove unused utility types from `typescript` plugin as they were previously used for `typescript-operations` plugin: + +- `MakeOptional` +- `MakeMaybe` +- `MakeEmpty` +- `Incremental` + +BREAKING CHANGE: Remove `getRootTypeNames` function because it's available in `@graphql-utils/tools` and not used anywhere diff --git a/dev-test/modules/types.ts b/dev-test/modules/types.ts index 656b99b6de1..44edaa1b576 100644 --- a/dev-test/modules/types.ts +++ b/dev-test/modules/types.ts @@ -2,14 +2,6 @@ import { GraphQLResolveInfo } from 'graphql'; export type Maybe = T | null; export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; -export type Incremental = - | T - | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type Omit = Pick>; export type RequireFields = Omit & { [P in K]-?: NonNullable }; /** All built-in and custom scalars, mapped to their actual values */ diff --git a/dev-test/subpath-import/result.d.ts b/dev-test/subpath-import/result.d.ts index 0594f80c2ae..57fea3fbf7e 100644 --- a/dev-test/subpath-import/result.d.ts +++ b/dev-test/subpath-import/result.d.ts @@ -5,14 +5,6 @@ import { GraphQLResolveInfo } from 'graphql'; export type Maybe = T | null; export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; -export type Incremental = - | T - | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type EnumResolverSignature = { [key in keyof T]?: AllowedValues }; export type RequireFields = Omit & { [P in K]-?: NonNullable }; /** All built-in and custom scalars, mapped to their actual values */ diff --git a/dev-test/test-federation/generated/types.ts b/dev-test/test-federation/generated/types.ts index 65c97cd274a..bedeb91f77d 100644 --- a/dev-test/test-federation/generated/types.ts +++ b/dev-test/test-federation/generated/types.ts @@ -2,14 +2,6 @@ import { GraphQLResolveInfo, GraphQLScalarType, GraphQLScalarTypeConfig } from ' export type Maybe = T | null | undefined; export type InputMaybe = T | null | undefined; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; -export type Incremental = - | T - | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/test-schema/env.types.ts b/dev-test/test-schema/env.types.ts index 4b28b59578d..535aed9beef 100644 --- a/dev-test/test-schema/env.types.ts +++ b/dev-test/test-schema/env.types.ts @@ -1,13 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; -export type Incremental = - | T - | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/test-schema/resolvers-federation.ts b/dev-test/test-schema/resolvers-federation.ts index 75ebca192e8..1fd41a62ebd 100644 --- a/dev-test/test-schema/resolvers-federation.ts +++ b/dev-test/test-schema/resolvers-federation.ts @@ -2,14 +2,6 @@ import { GraphQLResolveInfo } from 'graphql'; export type Maybe = T | null; export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; -export type Incremental = - | T - | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/test-schema/resolvers-root.ts b/dev-test/test-schema/resolvers-root.ts index 3528e3a05a7..a64be22359e 100644 --- a/dev-test/test-schema/resolvers-root.ts +++ b/dev-test/test-schema/resolvers-root.ts @@ -2,14 +2,6 @@ import { GraphQLResolveInfo } from 'graphql'; export type Maybe = T | null; export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; -export type Incremental = - | T - | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type RequireFields = Omit & { [P in K]-?: NonNullable }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { diff --git a/dev-test/test-schema/resolvers-stitching.ts b/dev-test/test-schema/resolvers-stitching.ts index 65e6ea0b0c9..7ee5fcd8dd3 100644 --- a/dev-test/test-schema/resolvers-stitching.ts +++ b/dev-test/test-schema/resolvers-stitching.ts @@ -2,14 +2,6 @@ import { FieldNode, GraphQLResolveInfo, SelectionSetNode } from 'graphql'; export type Maybe = T | null; export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; -export type Incremental = - | T - | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type RequireFields = Omit & { [P in K]-?: NonNullable }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { diff --git a/dev-test/test-schema/resolvers-types.ts b/dev-test/test-schema/resolvers-types.ts index cb13e5c9bb8..9792914540d 100644 --- a/dev-test/test-schema/resolvers-types.ts +++ b/dev-test/test-schema/resolvers-types.ts @@ -2,14 +2,6 @@ import { GraphQLResolveInfo } from 'graphql'; export type Maybe = T | null; export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; -export type Incremental = - | T - | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type RequireFields = Omit & { [P in K]-?: NonNullable }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { diff --git a/dev-test/test-schema/typings.avoidOptionals.ts b/dev-test/test-schema/typings.avoidOptionals.ts index d5215c529a5..2387065b40d 100644 --- a/dev-test/test-schema/typings.avoidOptionals.ts +++ b/dev-test/test-schema/typings.avoidOptionals.ts @@ -1,13 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; -export type Incremental = - | T - | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/test-schema/typings.enum.ts b/dev-test/test-schema/typings.enum.ts index 3cfe81f2d53..bf4be12bece 100644 --- a/dev-test/test-schema/typings.enum.ts +++ b/dev-test/test-schema/typings.enum.ts @@ -1,13 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; -export type Incremental = - | T - | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/test-schema/typings.immutableTypes.ts b/dev-test/test-schema/typings.immutableTypes.ts index 36b580cf3a9..dc7757718f3 100644 --- a/dev-test/test-schema/typings.immutableTypes.ts +++ b/dev-test/test-schema/typings.immutableTypes.ts @@ -1,13 +1,5 @@ export type Maybe = T | null; export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; -export type Incremental = - | T - | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/dev-test/test-schema/typings.ts b/dev-test/test-schema/typings.ts index 5afeb856f16..053a74746d7 100644 --- a/dev-test/test-schema/typings.ts +++ b/dev-test/test-schema/typings.ts @@ -2,14 +2,6 @@ import { GraphQLResolveInfo } from 'graphql'; export type Maybe = T | null; export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; -export type Incremental = - | T - | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type RequireFields = Omit & { [P in K]-?: NonNullable }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { diff --git a/dev-test/test-schema/typings.wrapped.ts b/dev-test/test-schema/typings.wrapped.ts index 029f15125d9..f9aaf485327 100644 --- a/dev-test/test-schema/typings.wrapped.ts +++ b/dev-test/test-schema/typings.wrapped.ts @@ -1,16 +1,6 @@ declare namespace GraphQL { export type Maybe = T | null; export type InputMaybe = Maybe; - export type MakeOptional = Omit & { - [SubKey in K]?: Maybe; - }; - export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; - export type MakeEmpty = { - [_ in K]?: never; - }; - export type Incremental = - | T - | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { ID: { input: string; output: string }; diff --git a/examples/typescript-resolvers/src/type-defs.d.ts b/examples/typescript-resolvers/src/type-defs.d.ts index d16780792a3..3a73816d3ec 100644 --- a/examples/typescript-resolvers/src/type-defs.d.ts +++ b/examples/typescript-resolvers/src/type-defs.d.ts @@ -2,14 +2,6 @@ import { GraphQLResolveInfo } from 'graphql'; export type Maybe = T | null; export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { - [_ in K]?: never; -}; -export type Incremental = - | T - | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type RequireFields = Omit & { [P in K]-?: NonNullable }; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = { diff --git a/packages/plugins/other/visitor-plugin-common/src/utils.ts b/packages/plugins/other/visitor-plugin-common/src/utils.ts index 75c9ebf4c14..387c0a8bbfa 100644 --- a/packages/plugins/other/visitor-plugin-common/src/utils.ts +++ b/packages/plugins/other/visitor-plugin-common/src/utils.ts @@ -449,13 +449,6 @@ function isStringValueNode(node: any): node is StringValueNode { return node && typeof node === 'object' && node.kind === Kind.STRING; } -// will be removed on next release because tools already has it -export function getRootTypeNames(schema: GraphQLSchema): string[] { - return [schema.getQueryType(), schema.getMutationType(), schema.getSubscriptionType()] - .filter(t => t) - .map(t => t.name); -} - export function stripMapperTypeInterpolation(identifier: string): string { return identifier.trim().replace(/<{.*}>/, ''); } diff --git a/packages/plugins/typescript/resolvers/tests/__snapshots__/ts-resolvers.spec.ts.snap b/packages/plugins/typescript/resolvers/tests/__snapshots__/ts-resolvers.spec.ts.snap index b63bc6c726b..5b2d327f9c2 100644 --- a/packages/plugins/typescript/resolvers/tests/__snapshots__/ts-resolvers.spec.ts.snap +++ b/packages/plugins/typescript/resolvers/tests/__snapshots__/ts-resolvers.spec.ts.snap @@ -3,10 +3,6 @@ exports[`TypeScript Resolvers Plugin > Config > allowParentTypeOverride - should allow to have less strict resolvers by overrding parent type 1`] = ` "export type Maybe = T | null; export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { [_ in K]?: never }; -export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; import { GraphQLResolveInfo, GraphQLScalarType, GraphQLScalarTypeConfig } from 'graphql'; export type Omit = Pick>; export type RequireFields = Omit & { [P in K]-?: NonNullable }; @@ -622,10 +618,6 @@ export type DirectiveResolvers = ResolversObject<{ exports[`TypeScript Resolvers Plugin > Config > optionalInfoArgument - should allow to have optional info argument 1`] = ` "export type Maybe = T | null; export type InputMaybe = Maybe; -export type MakeOptional = Omit & { [SubKey in K]?: Maybe }; -export type MakeMaybe = Omit & { [SubKey in K]: Maybe }; -export type MakeEmpty = { [_ in K]?: never }; -export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; import { GraphQLResolveInfo, GraphQLScalarType, GraphQLScalarTypeConfig } from 'graphql'; export type Omit = Pick>; export type RequireFields = Omit & { [P in K]-?: NonNullable }; diff --git a/packages/plugins/typescript/typescript/src/visitor.ts b/packages/plugins/typescript/typescript/src/visitor.ts index 363dac5ffab..ca7a288bbfd 100644 --- a/packages/plugins/typescript/typescript/src/visitor.ts +++ b/packages/plugins/typescript/typescript/src/visitor.ts @@ -46,11 +46,6 @@ export interface TypeScriptPluginParsedConfig extends ParsedTypesConfig { useImplementingTypes: boolean; } -export const MAKE_OPTIONAL_SIGNATURE = `type MakeOptional = Omit & { [SubKey in K]?: Maybe };`; -export const MAKE_MAYBE_SIGNATURE = `type MakeMaybe = Omit & { [SubKey in K]: Maybe };`; -export const MAKE_EMPTY_SIGNATURE = `type MakeEmpty = { [_ in K]?: never };`; -export const MAKE_INCREMENTAL_SIGNATURE = `type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never };`; - export class TsVisitor< TRawConfig extends TypeScriptPluginConfig = TypeScriptPluginConfig, TParsedConfig extends TypeScriptPluginParsedConfig = TypeScriptPluginParsedConfig, @@ -160,14 +155,7 @@ export class TsVisitor< public getWrapperDefinitions(): string[] { if (this.config.onlyEnums) return []; - const definitions: string[] = [ - this.getMaybeValue(), - this.getInputMaybeValue(), - this.getMakeOptionalDefinition(), - this.getMakeMaybeDefinition(), - this.getMakeEmptyDefinition(), - this.getIncrementalDefinition(), - ]; + const definitions: string[] = [this.getMaybeValue(), this.getInputMaybeValue()]; if (this.config.wrapFieldDefinitions) { definitions.push(this.getFieldWrapperValue()); @@ -179,24 +167,6 @@ export class TsVisitor< return definitions; } - public getMakeOptionalDefinition(): string { - return `${this.getExportPrefix()}${MAKE_OPTIONAL_SIGNATURE}`; - } - - public getMakeMaybeDefinition(): string { - if (this.config.onlyEnums) return ''; - - return `${this.getExportPrefix()}${MAKE_MAYBE_SIGNATURE}`; - } - - public getMakeEmptyDefinition(): string { - return `${this.getExportPrefix()}${MAKE_EMPTY_SIGNATURE}`; - } - - public getIncrementalDefinition(): string { - return `${this.getExportPrefix()}${MAKE_INCREMENTAL_SIGNATURE}`; - } - public getMaybeValue(): string { return `${this.getExportPrefix()}type Maybe = ${this.config.maybeValue};`; } From 50bee5e0cf0489c1652bed1e29cf560d74ceccf3 Mon Sep 17 00:00:00 2001 From: Igor Kusakov Date: Sun, 11 Jan 2026 05:48:00 -0500 Subject: [PATCH 23/69] Add config extract all fields to types field names only (same as apollo-tooling), v2 (#10568) * add extractAllFieldsToTypesCompact config option * adding changeset * fixing duplication bug * duplication bug fix --------- Co-authored-by: Igor Kusakov --- .changeset/five-cases-sniff.md | 5 + .../src/base-documents-visitor.ts | 47 +++- .../src/selection-set-to-object.ts | 29 ++- .../tests/extract-all-types.spec.ts | 223 ++++++++++++++++++ 4 files changed, 291 insertions(+), 13 deletions(-) create mode 100644 .changeset/five-cases-sniff.md diff --git a/.changeset/five-cases-sniff.md b/.changeset/five-cases-sniff.md new file mode 100644 index 00000000000..148366947bc --- /dev/null +++ b/.changeset/five-cases-sniff.md @@ -0,0 +1,5 @@ +--- +'@graphql-codegen/visitor-plugin-common': minor +--- + +Adding config option extractAllFieldsToTypesCompact, which renders nested types names with field names only (without types) diff --git a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts index d2d31b13497..cca09fb2cb4 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts @@ -7,7 +7,7 @@ import { OperationTypeNode, VariableDefinitionNode, } from 'graphql'; -import { BaseVisitor, type RawConfig, type ParsedConfig } from './base-visitor.js'; +import { BaseVisitor, type ParsedConfig, type RawConfig } from './base-visitor.js'; import { DEFAULT_SCALARS } from './scalars.js'; import { SelectionSetToObject } from './selection-set-to-object.js'; import { CustomDirectivesConfig, NormalizedScalarsMap } from './types.js'; @@ -21,6 +21,7 @@ import { OperationVariablesToObject } from './variables-to-object.js'; export interface ParsedDocumentsConfig extends ParsedConfig { extractAllFieldsToTypes: boolean; + extractAllFieldsToTypesCompact: boolean; operationResultSuffix: string; dedupeOperationSuffix: boolean; omitOperationSuffix: boolean; @@ -224,6 +225,16 @@ export interface RawDocumentsConfig extends RawConfig { * and the typechecking time. */ extractAllFieldsToTypes?: boolean; + /** + * @default false + * @description Generates type names using only field names, omitting GraphQL type names. + * This matches the naming convention used by Apollo Tooling. + * For example, instead of `Query_company_Company_office_Office_location_Location`, + * it generates `Query_company_office_location`. + * + * When this option is enabled, `extractAllFieldsToTypes` is automatically enabled as well. + */ + extractAllFieldsToTypesCompact?: boolean; } export class BaseDocumentsVisitor< @@ -257,7 +268,13 @@ export class BaseDocumentsVisitor< }), generatesOperationTypes: getConfigValue(rawConfig.generatesOperationTypes, true), importSchemaTypesFrom: getConfigValue(rawConfig.importSchemaTypesFrom, ''), - extractAllFieldsToTypes: getConfigValue(rawConfig.extractAllFieldsToTypes, false), + extractAllFieldsToTypes: + getConfigValue(rawConfig.extractAllFieldsToTypes, false) || + getConfigValue(rawConfig.extractAllFieldsToTypesCompact, false), + extractAllFieldsToTypesCompact: getConfigValue( + rawConfig.extractAllFieldsToTypesCompact, + false, + ), ...((additionalConfig || {}) as any), }); @@ -371,15 +388,23 @@ export class BaseDocumentsVisitor< }), ); - const operationResult = new DeclarationBlock(this._declarationBlockConfig) - .export() - .asKind('type') - .withName( - this.convertName(name, { - suffix: operationTypeSuffix + this._parsedConfig.operationResultSuffix, - }), - ) - .withContent(selectionSetObjects.mergedTypeString).string; + const operationResultName = this.convertName(name, { + suffix: operationTypeSuffix + this._parsedConfig.operationResultSuffix, + }); + + // When extractAllFieldsToTypes creates a root type with the same name as the operation result, + // we only need the extracted type and can skip the alias to avoid duplicates + const shouldSkipOperationResult = + this._parsedConfig.extractAllFieldsToTypesCompact && + operationResultName === selectionSetObjects.mergedTypeString; + + const operationResult = shouldSkipOperationResult + ? '' + : new DeclarationBlock(this._declarationBlockConfig) + .export() + .asKind('type') + .withName(operationResultName) + .withContent(selectionSetObjects.mergedTypeString).string; const operationVariables = new DeclarationBlock({ ...this._declarationBlockConfig, diff --git a/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts b/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts index 400c7411e60..9f7bfc3efd9 100644 --- a/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts +++ b/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts @@ -914,7 +914,19 @@ export class SelectionSetToObject< .map(typeName => { const relevant = grouped[typeName].filter(Boolean); return relevant.map(objDefinition => { - const name = fieldName ? `${fieldName}_${typeName}` : typeName; + // In compact mode, we still need to keep the final concrete type name for union/interface types + // to distinguish between different implementations, but we skip it for simple object types + const hasMultipleTypes = Object.keys(grouped).length > 1; + let name: string; + if (fieldName) { + if (this._config.extractAllFieldsToTypesCompact && !hasMultipleTypes) { + name = fieldName; + } else { + name = `${fieldName}_${typeName}`; + } + } else { + name = typeName; + } return { name, content: @@ -1047,9 +1059,17 @@ export class SelectionSetToObject< } protected buildFragmentTypeName(name: string, suffix: string, typeName = ''): string { + // In compact mode, omit typeName from fragment type names + let fragmentSuffix: string; + if (this._config.extractAllFieldsToTypesCompact) { + fragmentSuffix = suffix; + } else { + fragmentSuffix = typeName && suffix ? `_${typeName}_${suffix}` : typeName ? `_${typeName}` : suffix; + } + return this._convertName(name, { useTypesPrefix: true, - suffix: typeName && suffix ? `_${typeName}_${suffix}` : typeName ? `_${typeName}` : suffix, + suffix: fragmentSuffix, }); } @@ -1060,6 +1080,11 @@ export class SelectionSetToObject< return parentName; } + // When compact mode is enabled, skip appending typeName + if (this._config.extractAllFieldsToTypesCompact) { + return parentName; + } + const schemaType = this._schema.getType(typeName); // Check if current selection set has type-narrowing fragments. diff --git a/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts b/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts index 90e191c179a..1d882ae845e 100644 --- a/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts @@ -1600,3 +1600,226 @@ describe('extractAllFieldsToTypes: true', () => { await validate(content); }); }); + +describe('extractAllFieldsToTypesCompact: true', () => { + const validate = async (content: Types.PluginOutput) => { + const m = mergeOutputs([content]); + validateTs(m, undefined, undefined, undefined, []); + + return m; + }; + + const companySchema = buildSchema(/* GraphQL */ ` + type Query { + company(id: ID!): Company + } + type Company { + id: ID! + name: String! + score: Float + reviewCount: Int + office: Office + } + type Office { + id: ID! + location: Location + } + type Location { + formatted: String + } + `); + + const companyDoc = parse(/* GraphQL */ ` + query GetCompanyInfo($id: ID!) { + company(id: $id) { + id + name + score + reviewCount + office { + id + location { + formatted + } + } + } + } + `); + + it('should generate compact type names without GraphQL type names (Apollo Tooling style)', async () => { + const config: TypeScriptDocumentsPluginConfig = { + extractAllFieldsToTypesCompact: true, + nonOptionalTypename: true, + omitOperationSuffix: true, + }; + const { content } = await plugin(companySchema, [{ location: 'test-file.ts', document: companyDoc }], config, { + outputFile: '', + }); + expect(content).toMatchInlineSnapshot(` + "export type GetCompanyInfo_company_office_location = { __typename: 'Location', formatted: string | null }; + + export type GetCompanyInfo_company_office = { __typename: 'Office', id: string, location: GetCompanyInfo_company_office_location | null }; + + export type GetCompanyInfo_company = { __typename: 'Company', id: string, name: string, score: number | null, reviewCount: number | null, office: GetCompanyInfo_company_office | null }; + + export type GetCompanyInfo = { __typename: 'Query', company: GetCompanyInfo_company | null }; + + + export type GetCompanyInfoVariables = Exact<{ + id: string; + }>; + " + `); + + await validate(content); + }); + + it('should work with unions and interfaces in compact mode', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + animals: [Animal!]! + } + interface Animal { + name: String! + owner: Person! + } + type Cat implements Animal { + name: String! + owner: Person! + } + type Dog implements Animal { + name: String! + owner: Person! + } + union Person = Trainer | Veterinarian + type Trainer { + name: String! + } + type Veterinarian { + name: String! + } + `); + + const doc = parse(/* GraphQL */ ` + query GetAnimals { + animals { + name + owner { + ... on Trainer { + name + } + ... on Veterinarian { + name + } + } + } + } + `); + + const config: TypeScriptDocumentsPluginConfig = { + extractAllFieldsToTypesCompact: true, + nonOptionalTypename: true, + omitOperationSuffix: true, + }; + const { content } = await plugin(schema, [{ location: 'test-file.ts', document: doc }], config, { outputFile: '' }); + + // Verify the naming follows Apollo Tooling style (field names only, no intermediate type names) + expect(content).toContain('GetAnimals_animals_owner_Trainer'); + expect(content).toContain('GetAnimals_animals_owner_Veterinarian'); + expect(content).toContain('GetAnimals_animals_owner'); + expect(content).toContain('GetAnimals_animals_Cat'); + expect(content).toContain('GetAnimals_animals_Dog'); + expect(content).toContain('GetAnimals_animals'); + + // Should NOT contain intermediate type names in the field paths (like Animal between animals and owner) + expect(content).not.toContain('GetAnimals_animals_Animal_owner'); + + await validate(content); + }); + + it('should automatically enable extractAllFieldsToTypes when extractAllFieldsToTypesCompact is true', async () => { + const config: TypeScriptDocumentsPluginConfig = { + extractAllFieldsToTypes: false, + extractAllFieldsToTypesCompact: true, + nonOptionalTypename: true, + omitOperationSuffix: true, + }; + const { content } = await plugin(companySchema, [{ location: 'test-file.ts', document: companyDoc }], config, { + outputFile: '', + }); + + // When extractAllFieldsToTypesCompact is true, extractAllFieldsToTypes should be automatically enabled + // So types should be extracted, not inlined + expect(content).toContain('GetCompanyInfo_company_office_location'); + expect(content).toContain('GetCompanyInfo_company_office'); + expect(content).toContain('GetCompanyInfo_company'); + expect(content).toContain('export type GetCompanyInfo'); + + await validate(content); + }); + + it('should apply compact naming to fragments', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + } + interface User { + id: ID! + profile: Profile + } + type AdminUser implements User { + id: ID! + profile: Profile + permissions: [String!]! + } + type RegularUser implements User { + id: ID! + profile: Profile + } + type Profile { + name: String! + contact: Contact + } + type Contact { + email: String + } + `); + + const doc = parse(/* GraphQL */ ` + fragment UserProfile on User { + id + profile { + name + contact { + email + } + } + } + query GetUser($id: ID!) { + user(id: $id) { + ...UserProfile + ... on AdminUser { + permissions + } + } + } + `); + + const config: TypeScriptDocumentsPluginConfig = { + extractAllFieldsToTypesCompact: true, + nonOptionalTypename: true, + omitOperationSuffix: true, + }; + const { content } = await plugin(schema, [{ location: 'test-file.ts', document: doc }], config, { outputFile: '' }); + + // Fragment types should use compact naming (no intermediate type names) + expect(content).toContain('UserProfile_profile_contact'); + expect(content).toContain('UserProfile_profile'); + + // Should NOT contain type names in fragment paths + expect(content).not.toContain('UserProfile_profile_Profile_contact'); + expect(content).not.toContain('UserProfile_profile_Profile_contact_Contact'); + + await validate(content); + }); +}); From a1a5c43125612217cc7f301473f124c03f95f1c7 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Wed, 14 Jan 2026 00:52:11 +1100 Subject: [PATCH 24/69] Only generate `Exact` utility type if documents have operations (#10571) * Remove extraneous test setup * Do not generate Exact utility type of not used * Add default test case to check that Exact is used for Mutation and Subscription variables * Update dev-tests * Add changeset * Remove extraneous config for Exact test --- .changeset/khaki-clubs-say.md | 9 ++ dev-test/star-wars/types.d.ts | 1 - .../typescript/operations/src/visitor.ts | 8 +- .../tests/ts-documents.standalone.spec.ts | 89 ++++++++++++++++--- .../client/tests/client-preset.enum.spec.ts | 1 - 5 files changed, 93 insertions(+), 15 deletions(-) create mode 100644 .changeset/khaki-clubs-say.md diff --git a/.changeset/khaki-clubs-say.md b/.changeset/khaki-clubs-say.md new file mode 100644 index 00000000000..0bbae4c9c99 --- /dev/null +++ b/.changeset/khaki-clubs-say.md @@ -0,0 +1,9 @@ +--- +'@graphql-codegen/typescript-operations': patch +--- + +Only generate `Exact` utility type at the top if it is used + +`Exact` utility is only used to wrap variables types for operations (queries, mutations and subscriptions) if they exist in the document. `Exact` is never used when there are _only_ fragments. + +This is important to conditionally generate as users may use very strict tsconfig that will fail compiling if there are unused types. diff --git a/dev-test/star-wars/types.d.ts b/dev-test/star-wars/types.d.ts index ac440322507..92e0ff02565 100644 --- a/dev-test/star-wars/types.d.ts +++ b/dev-test/star-wars/types.d.ts @@ -1,4 +1,3 @@ -type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index f9490260a62..85281526451 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -76,6 +76,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< TypeScriptDocumentsParsedConfig > { protected _usedNamedInputTypes: UsedNamedInputTypes = {}; + protected _needsExactUtilityType: boolean = false; private _outputPath: string; constructor( @@ -396,7 +397,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< protected applyVariablesWrapper(variablesBlock: string, operationType: string): string { const extraType = this.config.allowUndefinedQueryVariables && operationType === 'Query' ? ' | undefined' : ''; - + this._needsExactUtilityType = true; return `Exact<${variablesBlock === '{}' ? `{ [key: string]: never; }` : variablesBlock}>${extraType}`; } @@ -514,7 +515,10 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< } getExactUtilityType(): string | null { - if (!this.config.generatesOperationTypes) { + if ( + !this.config.generatesOperationTypes || // 1. If we don't generate operation types, definitely do not need `Exact` + !this._needsExactUtilityType // 2. Even if we generate operation types, we may not need `Exact` if there's no operations in the documents i.e. only fragments found + ) { return null; } diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts index 466b11ce8fd..91ed3b431c4 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -11,6 +11,14 @@ describe('TypeScript Operations Plugin - Standalone', () => { users(input: UsersInput!): UsersResponse! } + type Mutation { + makeUserAdmin(id: ID!): User! + } + + type Subscription { + userChanges(id: ID!): User! + } + type ResponseError { error: ResponseErrorType! } @@ -90,6 +98,23 @@ describe('TypeScript Operations Plugin - Standalone', () => { } } } + + mutation MakeAdmin { + makeUserAdmin(id: "100") { + ...UserFragment + } + } + + subscription UserChanges { + makeUserAdmin(id: "100") { + ...UserFragment + } + } + + fragment UserFragment on User { + id + role + } `); const result = mergeOutputs([await plugin(schema, [{ document }], {}, { outputFile: '' })]); @@ -147,6 +172,18 @@ describe('TypeScript Operations Plugin - Standalone', () => { | { result: Array<{ __typename: 'User' }> } | { __typename: 'ResponseError' } }; + + export type MakeAdminMutationVariables = Exact<{ [key: string]: never; }>; + + + export type MakeAdminMutation = { makeUserAdmin: { id: string, role: UserRole } }; + + export type UserChangesSubscriptionVariables = Exact<{ [key: string]: never; }>; + + + export type UserChangesSubscription = Record; + + export type UserFragmentFragment = { id: string, role: UserRole }; " `); @@ -712,17 +749,6 @@ describe('TypeScript Operations Plugin - Standalone', () => { user(id: ID!): User } - type ResponseError { - error: ResponseErrorType! - } - - enum ResponseErrorType { - NOT_FOUND - INPUT_VALIDATION_ERROR - FORBIDDEN_ERROR - UNEXPECTED_ERROR - } - type User { id: ID! name: String! @@ -782,4 +808,45 @@ describe('TypeScript Operations Plugin - Standalone', () => { validateTs(result, undefined, undefined, undefined, undefined, true); }); + + it('does not generate Exact utility type if there are only fragments', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + bestFriend: User + goodFriends: [User!]! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + fragment UserPart on User { + id + name + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], {}, { outputFile: '' })]); + + expect(result).toMatchInlineSnapshot(` + " + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserPartFragment = { id: string, name: string }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); }); diff --git a/packages/presets/client/tests/client-preset.enum.spec.ts b/packages/presets/client/tests/client-preset.enum.spec.ts index c6dcc1897a0..3e55808d024 100644 --- a/packages/presets/client/tests/client-preset.enum.spec.ts +++ b/packages/presets/client/tests/client-preset.enum.spec.ts @@ -23,7 +23,6 @@ describe('client-preset - Enum', () => { const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never };" `); }); From 51e3f116d8ea5aa18ed3811c6ad3cf28759459a1 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Thu, 15 Jan 2026 22:36:25 +1100 Subject: [PATCH 25/69] Make `unknown` instead of `any` the default scalar type (#10566) * Make default scalar unknown, instead of any * Set up defaultScalarType tests * Add changeset * Revert unrelated null | undefined changes * Fix test description * Add a test case for custom scalar in dev-test --- .changeset/every-rooms-camp.md | 9 + dev-test/gql-tag-operations/gql/gql.ts | 8 +- dev-test/gql-tag-operations/gql/graphql.ts | 4 +- dev-test/gql-tag-operations/graphql/gql.ts | 8 +- .../gql-tag-operations/graphql/graphql.ts | 4 +- dev-test/gql-tag-operations/src/index.ts | 1 + dev-test/test-schema/resolvers-federation.ts | 2 +- .../graphql-codegen-cli/tests/codegen.spec.ts | 2 +- .../visitor-plugin-common/src/base-visitor.ts | 4 +- .../other/visitor-plugin-common/src/utils.ts | 4 +- .../src/ts-operation-variables-to-object.ts | 2 +- .../typescript/operations/src/visitor.ts | 10 +- .../__snapshots__/ts-documents.spec.ts.snap | 34 +-- .../tests/extract-all-types.spec.ts | 20 +- .../operations/tests/ts-documents.spec.ts | 2 +- ...ts.standalone.default-scalar-types.spec.ts | 283 ++++++++++++++++++ ...-documents.standalone.import-types.spec.ts | 20 +- .../ts-documents.standalone.input.spec.ts | 29 +- .../tests/ts-documents.standalone.spec.ts | 16 +- .../__snapshots__/ts-resolvers.spec.ts.snap | 4 +- .../typescript/tests/typescript.spec.ts | 20 +- 21 files changed, 399 insertions(+), 87 deletions(-) create mode 100644 .changeset/every-rooms-camp.md create mode 100644 packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts diff --git a/.changeset/every-rooms-camp.md b/.changeset/every-rooms-camp.md new file mode 100644 index 00000000000..89938d2d564 --- /dev/null +++ b/.changeset/every-rooms-camp.md @@ -0,0 +1,9 @@ +--- +'@graphql-codegen/visitor-plugin-common': major +'@graphql-codegen/typescript-operations': major +'@graphql-codegen/typescript': major +'@graphql-codegen/typescript-resolvers': major +'@graphql-codegen/client-preset': major +--- + +BREAKING CHANGE: make `unknown` instead of `any` the default custom scalar type diff --git a/dev-test/gql-tag-operations/gql/gql.ts b/dev-test/gql-tag-operations/gql/gql.ts index fc9ac53a8f3..097e2d716e5 100644 --- a/dev-test/gql-tag-operations/gql/gql.ts +++ b/dev-test/gql-tag-operations/gql/gql.ts @@ -15,12 +15,12 @@ import * as types from './graphql.js'; */ type Documents = { '\n query Foo {\n Tweets {\n id\n }\n }\n': typeof types.FooDocument; - '\n fragment Lel on Tweet {\n id\n body\n }\n': typeof types.LelFragmentDoc; + '\n fragment Lel on Tweet {\n id\n body\n date\n }\n': typeof types.LelFragmentDoc; '\n query Bar {\n Tweets {\n ...Lel\n }\n }\n': typeof types.BarDocument; }; const documents: Documents = { '\n query Foo {\n Tweets {\n id\n }\n }\n': types.FooDocument, - '\n fragment Lel on Tweet {\n id\n body\n }\n': types.LelFragmentDoc, + '\n fragment Lel on Tweet {\n id\n body\n date\n }\n': types.LelFragmentDoc, '\n query Bar {\n Tweets {\n ...Lel\n }\n }\n': types.BarDocument, }; @@ -48,8 +48,8 @@ export function graphql( * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( - source: '\n fragment Lel on Tweet {\n id\n body\n }\n', -): (typeof documents)['\n fragment Lel on Tweet {\n id\n body\n }\n']; + source: '\n fragment Lel on Tweet {\n id\n body\n date\n }\n', +): (typeof documents)['\n fragment Lel on Tweet {\n id\n body\n date\n }\n']; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/dev-test/gql-tag-operations/gql/graphql.ts b/dev-test/gql-tag-operations/gql/graphql.ts index aa5c16c9b1c..c8d4e3a8d5c 100644 --- a/dev-test/gql-tag-operations/gql/graphql.ts +++ b/dev-test/gql-tag-operations/gql/graphql.ts @@ -9,7 +9,7 @@ export type FooQueryVariables = Exact<{ [key: string]: never }>; export type FooQuery = { Tweets: Array<{ id: string } | null> | null }; -export type LelFragment = { id: string; body: string | null } & { +export type LelFragment = { id: string; body: string | null; date: unknown | null } & { ' $fragmentName'?: 'LelFragment'; }; @@ -31,6 +31,7 @@ export const LelFragmentDoc = { selections: [ { kind: 'Field', name: { kind: 'Name', value: 'id' } }, { kind: 'Field', name: { kind: 'Name', value: 'body' } }, + { kind: 'Field', name: { kind: 'Name', value: 'date' } }, ], }, }, @@ -89,6 +90,7 @@ export const BarDocument = { selections: [ { kind: 'Field', name: { kind: 'Name', value: 'id' } }, { kind: 'Field', name: { kind: 'Name', value: 'body' } }, + { kind: 'Field', name: { kind: 'Name', value: 'date' } }, ], }, }, diff --git a/dev-test/gql-tag-operations/graphql/gql.ts b/dev-test/gql-tag-operations/graphql/gql.ts index fc9ac53a8f3..097e2d716e5 100644 --- a/dev-test/gql-tag-operations/graphql/gql.ts +++ b/dev-test/gql-tag-operations/graphql/gql.ts @@ -15,12 +15,12 @@ import * as types from './graphql.js'; */ type Documents = { '\n query Foo {\n Tweets {\n id\n }\n }\n': typeof types.FooDocument; - '\n fragment Lel on Tweet {\n id\n body\n }\n': typeof types.LelFragmentDoc; + '\n fragment Lel on Tweet {\n id\n body\n date\n }\n': typeof types.LelFragmentDoc; '\n query Bar {\n Tweets {\n ...Lel\n }\n }\n': typeof types.BarDocument; }; const documents: Documents = { '\n query Foo {\n Tweets {\n id\n }\n }\n': types.FooDocument, - '\n fragment Lel on Tweet {\n id\n body\n }\n': types.LelFragmentDoc, + '\n fragment Lel on Tweet {\n id\n body\n date\n }\n': types.LelFragmentDoc, '\n query Bar {\n Tweets {\n ...Lel\n }\n }\n': types.BarDocument, }; @@ -48,8 +48,8 @@ export function graphql( * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( - source: '\n fragment Lel on Tweet {\n id\n body\n }\n', -): (typeof documents)['\n fragment Lel on Tweet {\n id\n body\n }\n']; + source: '\n fragment Lel on Tweet {\n id\n body\n date\n }\n', +): (typeof documents)['\n fragment Lel on Tweet {\n id\n body\n date\n }\n']; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ diff --git a/dev-test/gql-tag-operations/graphql/graphql.ts b/dev-test/gql-tag-operations/graphql/graphql.ts index aa5c16c9b1c..c8d4e3a8d5c 100644 --- a/dev-test/gql-tag-operations/graphql/graphql.ts +++ b/dev-test/gql-tag-operations/graphql/graphql.ts @@ -9,7 +9,7 @@ export type FooQueryVariables = Exact<{ [key: string]: never }>; export type FooQuery = { Tweets: Array<{ id: string } | null> | null }; -export type LelFragment = { id: string; body: string | null } & { +export type LelFragment = { id: string; body: string | null; date: unknown | null } & { ' $fragmentName'?: 'LelFragment'; }; @@ -31,6 +31,7 @@ export const LelFragmentDoc = { selections: [ { kind: 'Field', name: { kind: 'Name', value: 'id' } }, { kind: 'Field', name: { kind: 'Name', value: 'body' } }, + { kind: 'Field', name: { kind: 'Name', value: 'date' } }, ], }, }, @@ -89,6 +90,7 @@ export const BarDocument = { selections: [ { kind: 'Field', name: { kind: 'Name', value: 'id' } }, { kind: 'Field', name: { kind: 'Name', value: 'body' } }, + { kind: 'Field', name: { kind: 'Name', value: 'date' } }, ], }, }, diff --git a/dev-test/gql-tag-operations/src/index.ts b/dev-test/gql-tag-operations/src/index.ts index 884fce3543a..b11086cdac7 100644 --- a/dev-test/gql-tag-operations/src/index.ts +++ b/dev-test/gql-tag-operations/src/index.ts @@ -14,6 +14,7 @@ const LelFragment = graphql(/* GraphQL */ ` fragment Lel on Tweet { id body + date } `); diff --git a/dev-test/test-schema/resolvers-federation.ts b/dev-test/test-schema/resolvers-federation.ts index 1fd41a62ebd..8ef6a8ac231 100644 --- a/dev-test/test-schema/resolvers-federation.ts +++ b/dev-test/test-schema/resolvers-federation.ts @@ -9,7 +9,7 @@ export type Scalars = { Boolean: { input: boolean; output: boolean }; Int: { input: number; output: number }; Float: { input: number; output: number }; - _FieldSet: { input: any; output: any }; + _FieldSet: { input: unknown; output: unknown }; }; export type Address = { diff --git a/packages/graphql-codegen-cli/tests/codegen.spec.ts b/packages/graphql-codegen-cli/tests/codegen.spec.ts index 8a692a9fb2a..0f9dcecde3f 100644 --- a/packages/graphql-codegen-cli/tests/codegen.spec.ts +++ b/packages/graphql-codegen-cli/tests/codegen.spec.ts @@ -774,7 +774,7 @@ describe('Codegen Executor', () => { Boolean: { input: boolean; output: boolean; } Int: { input: number; output: number; } Float: { input: number; output: number; } - UniqueID: { input: any; output: any; } + UniqueID: { input: unknown; output: unknown; } };`); }); }); diff --git a/packages/plugins/other/visitor-plugin-common/src/base-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-visitor.ts index f1a8d0a196a..bae5f1b8a07 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-visitor.ts @@ -70,7 +70,7 @@ export interface RawConfig { strictScalars?: boolean; /** * @description Allows you to override the type that unknown scalars will have. - * @default any + * @default unknown * * @exampleMarkdown * ```ts filename="codegen.ts" @@ -82,7 +82,7 @@ export interface RawConfig { * 'path/to/file': { * // plugins... * config: { - * defaultScalarType: 'unknown' + * defaultScalarType: 'any' * }, * }, * }, diff --git a/packages/plugins/other/visitor-plugin-common/src/utils.ts b/packages/plugins/other/visitor-plugin-common/src/utils.ts index 387c0a8bbfa..0e8617b7680 100644 --- a/packages/plugins/other/visitor-plugin-common/src/utils.ts +++ b/packages/plugins/other/visitor-plugin-common/src/utils.ts @@ -291,7 +291,7 @@ export function buildScalarsFromConfig( schema: GraphQLSchema | undefined, config: RawConfig, defaultScalarsMapping: NormalizedScalarsMap = DEFAULT_SCALARS, - defaultScalarType = 'any', + defaultScalarType = 'unknown', ): ParsedScalarsMap { return buildScalars( schema, @@ -305,7 +305,7 @@ export function buildScalars( schema: GraphQLSchema | undefined, scalarsMapping: ScalarsMap, defaultScalarsMapping: NormalizedScalarsMap = DEFAULT_SCALARS, - defaultScalarType: string | null = 'any', + defaultScalarType: string | null = 'unknown', ): ParsedScalarsMap { const result: ParsedScalarsMap = {}; diff --git a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts index d052bbd8c97..82f4c607e65 100644 --- a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts +++ b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts @@ -32,6 +32,6 @@ export class TypeScriptOperationVariablesToObject extends TSOperationVariablesTo } protected getScalar(name: string): string { - return this._scalars?.[name]?.input ?? SCALARS[name] ?? 'any'; + return this._scalars?.[name]?.input ?? SCALARS[name] ?? 'unknown'; } } diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 85281526451..af016195b19 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -103,6 +103,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< }), ignoreEnumValuesFromSchema: getConfigValue(config.ignoreEnumValuesFromSchema, false), futureProofEnums: getConfigValue(config.futureProofEnums, false), + maybeValue: getConfigValue(config.maybeValue, 'T | null'), } as TypeScriptDocumentsParsedConfig, schema, ); @@ -110,9 +111,6 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< this._outputPath = outputPath; autoBind(this); - const defaultMaybeValue = 'T | null'; - const maybeValue = getConfigValue(config.maybeValue, defaultMaybeValue); - const allFragments: LoadedFragment[] = [ ...( documentNode.definitions.filter( @@ -140,7 +138,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< }, wrapTypeWithModifiers: (baseType, type) => { return wrapTypeWithModifiers(baseType, type, { - wrapOptional: type => maybeValue.replace('T', type), + wrapOptional: type => this.config.maybeValue.replace('T', type), wrapArray: type => { const listModifier = this.config.immutableTypes ? 'ReadonlyArray' : 'Array'; return `${listModifier}<${type}>`; @@ -277,7 +275,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< } typePart = usedInputType.tsType; // If the schema is correct, when reversing typeNodes, the first node would be `NamedType`, which means we can safely set it as the base for typePart - if (usedInputType.tsType !== 'any' && !typeNode.isNonNullable) { + if (!typeNode.isNonNullable) { typePart += ' | null | undefined'; } continue; @@ -422,7 +420,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< usedInputTypes[node.name] = { type: 'GraphQLScalarType', node, - tsType: (SCALARS[node.name] || this.config.scalars?.[node.name]?.input.type) ?? 'any', + tsType: (SCALARS[node.name] || this.config.scalars?.[node.name]?.input.type) ?? 'unknown', }; return; } diff --git a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap index 760b49909be..e77992ab326 100644 --- a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap +++ b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap @@ -18,10 +18,10 @@ exports[`TypeScript Operations Plugin > Issues > #2699 - Issues with multiple in export type GetEntityBrandDataQuery = { node: - | { __typename: 'Company', active: boolean, id: string, createdAt: any, updatedAt: any, brandData: { active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null } - | { __typename: 'Theater', active: boolean, id: string, createdAt: any, updatedAt: any, brandData: { active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null } - | { __typename: 'Movie', id: string, createdAt: any, updatedAt: any, brandData: { active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null } - | { __typename: 'User', id: string, createdAt: any, updatedAt: any, brandData: { active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null } + | { __typename: 'Company', active: boolean, id: string, createdAt: unknown, updatedAt: unknown, brandData: { active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null } + | { __typename: 'Theater', active: boolean, id: string, createdAt: unknown, updatedAt: unknown, brandData: { active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null } + | { __typename: 'Movie', id: string, createdAt: unknown, updatedAt: unknown, brandData: { active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null } + | { __typename: 'User', id: string, createdAt: unknown, updatedAt: unknown, brandData: { active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null } }; type EntityBrandData_Company_Fragment = { brandData: { active: boolean, browsable: boolean, title: string, alternateTitle: string | null, description: string } | null }; @@ -39,13 +39,13 @@ export type EntityBrandDataFragment = | EntityBrandData_User_Fragment ; -type ElementMetadata_Company_Fragment = { createdAt: any, updatedAt: any, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null }; +type ElementMetadata_Company_Fragment = { createdAt: unknown, updatedAt: unknown, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null }; -type ElementMetadata_Theater_Fragment = { createdAt: any, updatedAt: any, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null }; +type ElementMetadata_Theater_Fragment = { createdAt: unknown, updatedAt: unknown, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null }; -type ElementMetadata_Movie_Fragment = { createdAt: any, updatedAt: any, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null }; +type ElementMetadata_Movie_Fragment = { createdAt: unknown, updatedAt: unknown, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null }; -type ElementMetadata_User_Fragment = { createdAt: any, updatedAt: any, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null }; +type ElementMetadata_User_Fragment = { createdAt: unknown, updatedAt: unknown, createdBy: { id: string, name: string } | null, updatedBy: { id: string, name: string } | null }; export type ElementMetadataFragment = | ElementMetadata_Company_Fragment @@ -155,9 +155,9 @@ export type AaaQuery = { user: `; exports[`TypeScript Operations Plugin > Selection Set > Should have valid __typename usage and split types according to that (with usage) 1`] = ` -"type NetRoute_Ipv4Route_Fragment = { __typename: 'IPV4Route', ipv4Address: any | null, ipv4Gateway: any | null }; +"type NetRoute_Ipv4Route_Fragment = { __typename: 'IPV4Route', ipv4Address: unknown | null, ipv4Gateway: unknown | null }; -type NetRoute_Ipv6Route_Fragment = { __typename: 'IPV6Route', ipv6Address: any | null, ipv6Gateway: any | null }; +type NetRoute_Ipv6Route_Fragment = { __typename: 'IPV6Route', ipv6Address: unknown | null, ipv6Gateway: unknown | null }; export type NetRouteFragment = | NetRoute_Ipv4Route_Fragment @@ -168,30 +168,30 @@ export type QqQueryVariables = Exact<{ [key: string]: never; }>; export type QqQuery = { routes: Array< - | { __typename: 'IPV4Route', ipv4Address: any | null, ipv4Gateway: any | null } - | { __typename: 'IPV6Route', ipv6Address: any | null, ipv6Gateway: any | null } + | { __typename: 'IPV4Route', ipv4Address: unknown | null, ipv4Gateway: unknown | null } + | { __typename: 'IPV6Route', ipv6Address: unknown | null, ipv6Gateway: unknown | null } > }; " `; exports[`TypeScript Operations Plugin > Selection Set > Should have valid __typename usage and split types according to that (with usage) 2`] = ` -"type NetRoute_Ipv4Route_Fragment = { __typename: 'IPV4Route', ipv4Address: any | null, ipv4Gateway: any | null }; +"type NetRoute_Ipv4Route_Fragment = { __typename: 'IPV4Route', ipv4Address: unknown | null, ipv4Gateway: unknown | null }; -type NetRoute_Ipv6Route_Fragment = { __typename: 'IPV6Route', ipv6Address: any | null, ipv6Gateway: any | null }; +type NetRoute_Ipv6Route_Fragment = { __typename: 'IPV6Route', ipv6Address: unknown | null, ipv6Gateway: unknown | null }; export type NetRouteFragment = | NetRoute_Ipv4Route_Fragment | NetRoute_Ipv6Route_Fragment ; -export type TestFragment = { ipv6Address: any | null, ipv6Gateway: any | null }; +export type TestFragment = { ipv6Address: unknown | null, ipv6Gateway: unknown | null }; export type QqQueryVariables = Exact<{ [key: string]: never; }>; export type QqQuery = { routes: Array< - | { __typename: 'IPV4Route', ipv4Address: any | null, ipv4Gateway: any | null } - | { __typename: 'IPV6Route', ipv6Address: any | null, ipv6Gateway: any | null } + | { __typename: 'IPV4Route', ipv4Address: unknown | null, ipv4Gateway: unknown | null } + | { __typename: 'IPV6Route', ipv6Address: unknown | null, ipv6Gateway: unknown | null } > }; " `; diff --git a/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts b/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts index 1d882ae845e..98417731685 100644 --- a/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts @@ -84,13 +84,13 @@ describe('extractAllFieldsToTypes: true', () => { "type UserFragment_DummyUser = { __typename: 'DummyUser', id: string, - joinDate: any + joinDate: unknown }; type UserFragment_ActiveUser = { __typename: 'ActiveUser', id: string, - joinDate: any + joinDate: unknown }; export type UserFragment = @@ -101,13 +101,13 @@ describe('extractAllFieldsToTypes: true', () => { export type MeFragment_ActiveUser_parentUser_DummyUser = { __typename: 'DummyUser', id: string, - joinDate: any + joinDate: unknown }; export type MeFragment_ActiveUser_parentUser_ActiveUser = { __typename: 'ActiveUser', id: string, - joinDate: any + joinDate: unknown }; export type MeFragment_ActiveUser_parentUser = @@ -118,14 +118,14 @@ describe('extractAllFieldsToTypes: true', () => { type Me_DummyUser_Fragment = { __typename: 'DummyUser', id: string, - joinDate: any + joinDate: unknown }; type Me_ActiveUser_Fragment = { __typename: 'ActiveUser', isActive: boolean, id: string, - joinDate: any, + joinDate: unknown, parentUser: MeFragment_ActiveUser_parentUser }; @@ -137,14 +137,14 @@ describe('extractAllFieldsToTypes: true', () => { export type OverlappingFieldsMergingTestQuery_me_DummyUser = { __typename: 'DummyUser', id: string, - joinDate: any + joinDate: unknown }; export type OverlappingFieldsMergingTestQuery_me_ActiveUser = { __typename: 'ActiveUser', id: string, isActive: boolean, - joinDate: any, + joinDate: unknown, parentUser: MeFragment_ActiveUser_parentUser }; @@ -167,14 +167,14 @@ describe('extractAllFieldsToTypes: true', () => { export type NestedOverlappingFieldsMergingTestQuery_me_DummyUser = { __typename: 'DummyUser', id: string, - joinDate: any + joinDate: unknown }; export type NestedOverlappingFieldsMergingTestQuery_me_ActiveUser = { __typename: 'ActiveUser', isActive: boolean, id: string, - joinDate: any, + joinDate: unknown, parentUser: MeFragment_ActiveUser_parentUser }; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts index ba6e0379c0a..4646a7ed428 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts @@ -2904,7 +2904,7 @@ export type Q2Query = { search: Array< expect(content).toMatchInlineSnapshot( ` "export type TestQueryQueryVariables = Exact<{ - test?: any | null; + test?: unknown | null; }>; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts new file mode 100644 index 00000000000..bb55e79e7ea --- /dev/null +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts @@ -0,0 +1,283 @@ +import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; +import { validateTs } from '@graphql-codegen/testing'; +import { buildSchema, parse } from 'graphql'; +import { plugin } from '../src/index.js'; + +describe('TypeScript Operations Plugin - Default Scalar types', () => { + it('generates `unknown` as the default custom defaultScalarType', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user( + id: ID! + nonNullableDate: DateTime! + nullableDate: DateTime + dateArray1: [DateTime] + dateArray2: [DateTime]! + dateArray3: [DateTime!] + dateArray4: [DateTime!]! + input: UserInput! + ): User + } + + input UserInput { + nonNullableDate: DateTime! + nullableDate: DateTime + dateArray1: [DateTime] + dateArray2: [DateTime]! + dateArray3: [DateTime!] + dateArray4: [DateTime!]! + } + + type User { + id: ID! + nonNullableDate: DateTime! + nullableDate: DateTime + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User( + $nonNullableDate: DateTime! + $nullableDate: DateTime + $dateArray1: [DateTime] + $dateArray2: [DateTime]! + $dateArray3: [DateTime!] + $dateArray4: [DateTime!]! + $input: UserInput! + ) { + user( + id: "1" + nonNullableDate: $nonNullableDate + nullableDate: $nullableDate + dateArray1: $dateArray1 + dateArray2: $dateArray2 + dateArray3: $dateArray3 + dateArray4: $dateArray4 + input: $input + ) { + id + nonNullableDate + nullableDate + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], {}, { outputFile: '' })]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type UserInput = { + nonNullableDate: unknown; + nullableDate?: unknown | null | undefined; + dateArray1?: Array | null | undefined; + dateArray2: Array; + dateArray3?: Array | null | undefined; + dateArray4: Array; + }; + + export type UserQueryVariables = Exact<{ + nonNullableDate: unknown; + nullableDate?: unknown | null; + dateArray1?: Array | unknown | null; + dateArray2: Array | unknown; + dateArray3?: Array | unknown | null; + dateArray4: Array | unknown; + input: UserInput; + }>; + + + export type UserQuery = { user: { id: string, nonNullableDate: unknown, nullableDate: unknown | null } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it("generates `any` when defaultScalarType:'any'", async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user( + id: ID! + nonNullableDate: DateTime! + nullableDate: DateTime + dateArray1: [DateTime] + dateArray2: [DateTime]! + dateArray3: [DateTime!] + dateArray4: [DateTime!]! + input: UserInput! + ): User + } + + input UserInput { + nonNullableDate: DateTime! + nullableDate: DateTime + dateArray1: [DateTime] + dateArray2: [DateTime]! + dateArray3: [DateTime!] + dateArray4: [DateTime!]! + } + + type User { + id: ID! + nonNullableDate: DateTime! + nullableDate: DateTime + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User( + $nonNullableDate: DateTime! + $nullableDate: DateTime + $dateArray1: [DateTime] + $dateArray2: [DateTime]! + $dateArray3: [DateTime!] + $dateArray4: [DateTime!]! + $input: UserInput! + ) { + user( + id: "1" + nonNullableDate: $nonNullableDate + nullableDate: $nullableDate + dateArray1: $dateArray1 + dateArray2: $dateArray2 + dateArray3: $dateArray3 + dateArray4: $dateArray4 + input: $input + ) { + id + nonNullableDate + nullableDate + } + } + `); + + const result = mergeOutputs([ + await plugin(schema, [{ document }], { defaultScalarType: 'any' }, { outputFile: '' }), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type UserInput = { + nonNullableDate: any; + nullableDate?: any | null | undefined; + dateArray1?: Array | null | undefined; + dateArray2: Array; + dateArray3?: Array | null | undefined; + dateArray4: Array; + }; + + export type UserQueryVariables = Exact<{ + nonNullableDate: any; + nullableDate?: any | null; + dateArray1?: Array | any | null; + dateArray2: Array | any; + dateArray3?: Array | any | null; + dateArray4: Array | any; + input: UserInput; + }>; + + + export type UserQuery = { user: { id: string, nonNullableDate: any, nullableDate: any | null } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('generates correct types when defaultScalarType is set to said types', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user( + id: ID! + nonNullableDate: DateTime! + nullableDate: DateTime + dateArray1: [DateTime] + dateArray2: [DateTime]! + dateArray3: [DateTime!] + dateArray4: [DateTime!]! + input: UserInput! + ): User + } + + input UserInput { + nonNullableDate: DateTime! + nullableDate: DateTime + dateArray1: [DateTime] + dateArray2: [DateTime]! + dateArray3: [DateTime!] + dateArray4: [DateTime!]! + } + + type User { + id: ID! + nonNullableDate: DateTime! + nullableDate: DateTime + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User( + $nonNullableDate: DateTime! + $nullableDate: DateTime + $dateArray1: [DateTime] + $dateArray2: [DateTime]! + $dateArray3: [DateTime!] + $dateArray4: [DateTime!]! + $input: UserInput! + ) { + user( + id: "1" + nonNullableDate: $nonNullableDate + nullableDate: $nullableDate + dateArray1: $dateArray1 + dateArray2: $dateArray2 + dateArray3: $dateArray3 + dateArray4: $dateArray4 + input: $input + ) { + id + nonNullableDate + nullableDate + } + } + `); + + const result = mergeOutputs([ + await plugin(schema, [{ document }], { defaultScalarType: 'Date' }, { outputFile: '' }), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type UserInput = { + nonNullableDate: Date; + nullableDate?: Date | null | undefined; + dateArray1?: Array | null | undefined; + dateArray2: Array; + dateArray3?: Array | null | undefined; + dateArray4: Array; + }; + + export type UserQueryVariables = Exact<{ + nonNullableDate: Date; + nullableDate?: Date | null; + dateArray1?: Array | Date | null; + dateArray2: Array | Date; + dateArray3?: Array | Date | null; + dateArray4: Array | Date; + input: UserInput; + }>; + + + export type UserQuery = { user: { id: string, nonNullableDate: Date, nullableDate: Date | null } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); +}); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts index 782fc23d9ec..fd7f2687d21 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts @@ -110,9 +110,9 @@ describe('TypeScript Operations Plugin - Import Types', () => { /** UsersInput Description */ type UsersInput = { /** UsersInput from */ - from?: any; + from?: unknown | null | undefined; /** UsersInput to */ - to?: any; + to?: unknown | null | undefined; role?: UserRole | null | undefined; }; @@ -121,7 +121,7 @@ describe('TypeScript Operations Plugin - Import Types', () => { }>; - export type UserQuery = { user: { id: string, name: string, role: TypeImport.UserRole, createdAt: any } | null }; + export type UserQuery = { user: { id: string, name: string, role: TypeImport.UserRole, createdAt: unknown } | null }; export type UsersQueryVariables = Exact<{ input: TypeImport.UsersInput; @@ -134,8 +134,8 @@ describe('TypeScript Operations Plugin - Import Types', () => { }; export type UsersWithScalarInputQueryVariables = Exact<{ - from: any; - to?: any | null; + from: unknown; + to?: unknown | null; role?: TypeImport.UserRole | null; }>; @@ -254,9 +254,9 @@ describe('TypeScript Operations Plugin - Import Types', () => { /** UsersInput Description */ type UsersInput = { /** UsersInput from */ - from?: any; + from?: unknown | null | undefined; /** UsersInput to */ - to?: any; + to?: unknown | null | undefined; role?: UserRole | null | undefined; }; @@ -265,7 +265,7 @@ describe('TypeScript Operations Plugin - Import Types', () => { }>; - export type UserQuery = { user: { id: string, name: string, role: TypeImport.UserRole, createdAt: any } | null }; + export type UserQuery = { user: { id: string, name: string, role: TypeImport.UserRole, createdAt: unknown } | null }; export type UsersQueryVariables = Exact<{ input: TypeImport.UsersInput; @@ -278,8 +278,8 @@ describe('TypeScript Operations Plugin - Import Types', () => { }; export type UsersWithScalarInputQueryVariables = Exact<{ - from: any; - to?: any | null; + from: unknown; + to?: unknown | null; role?: TypeImport.UserRole | null; }>; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts index 03d33e1d2ec..3dc3b25f127 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts @@ -7,7 +7,7 @@ describe('TypeScript Operations Plugin - Input', () => { it('generates nested input correctly', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { - users(input: UsersInput!): [User!]! + users(input: UsersInput!, ageRange1: [Int], ageRange2: [Int]!, ageRange3: [Int!], ageRange4: [Int!]!): [User!]! } type ResponseError { @@ -61,8 +61,21 @@ describe('TypeScript Operations Plugin - Input', () => { scalar TimeZone `); const document = parse(/* GraphQL */ ` - query UsersWithScalarInput($inputNonNullable: UsersInput!, $inputNullable: UsersInput) { - users(input: $inputNonNullable) { + query UsersWithScalarInput( + $inputNonNullable: UsersInput! + $inputNullable: UsersInput + $ageRange1: [Int] + $ageRange2: [Int]! + $ageRange3: [Int!] + $ageRange4: [Int!]! + ) { + users( + input: $inputNonNullable + ageRange1: $ageRange1 + ageRange2: $ageRange2 + ageRange3: $ageRange3 + ageRange4: $ageRange4 + ) { ageRange1 ageRange2 ageRange3 @@ -100,7 +113,7 @@ describe('TypeScript Operations Plugin - Input', () => { from?: Date | null | undefined; /** UsersInput to */ to?: Date | null | undefined; - timezone?: any; + timezone?: unknown | null | undefined; role?: UserRole | null | undefined; ageRange1?: Array | null | undefined; ageRange2: Array; @@ -117,6 +130,10 @@ describe('TypeScript Operations Plugin - Input', () => { export type UsersWithScalarInputQueryVariables = Exact<{ inputNonNullable: UsersInput; inputNullable?: UsersInput | null; + ageRange1?: Array | number | null; + ageRange2: Array | number; + ageRange3?: Array | number | null; + ageRange4: Array | number; }>; @@ -224,7 +241,7 @@ describe('TypeScript Operations Plugin - Input', () => { readonly from?: Date | null | undefined; /** UsersInput to */ readonly to?: Date | null | undefined; - readonly timezone?: any; + readonly timezone?: unknown | null | undefined; readonly role?: UserRole | null | undefined; readonly ageRange1?: Array | null | undefined; readonly ageRange2: Array; @@ -344,7 +361,7 @@ describe('TypeScript Operations Plugin - Input', () => { from: Date; to?: never; timezone?: never; role?: never; ageRange1?: never; ageRange3?: never; bestFriend?: never; nestedInput?: never; } | { from?: never; /** UsersInput to */ to: Date; timezone?: never; role?: never; ageRange1?: never; ageRange3?: never; bestFriend?: never; nestedInput?: never; } - | { from?: never; to?: never; timezone: any; role?: never; ageRange1?: never; ageRange3?: never; bestFriend?: never; nestedInput?: never; } + | { from?: never; to?: never; timezone: unknown; role?: never; ageRange1?: never; ageRange3?: never; bestFriend?: never; nestedInput?: never; } | { from?: never; to?: never; timezone?: never; role: UserRole; ageRange1?: never; ageRange3?: never; bestFriend?: never; nestedInput?: never; } | { from?: never; to?: never; timezone?: never; role?: never; ageRange1: Array; ageRange3?: never; bestFriend?: never; nestedInput?: never; } | { from?: never; to?: never; timezone?: never; role?: never; ageRange1?: never; ageRange3: Array; bestFriend?: never; nestedInput?: never; } diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts index 91ed3b431c4..a4ce0116403 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -138,9 +138,9 @@ describe('TypeScript Operations Plugin - Standalone', () => { /** UsersInput Description */ type UsersInput = { /** UsersInput from */ - from?: any; + from?: unknown | null | undefined; /** UsersInput to */ - to?: any; + to?: unknown | null | undefined; role?: UserRole | null | undefined; }; @@ -149,7 +149,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { }>; - export type UserQuery = { user: { id: string, name: string, role: UserRole, createdAt: any, nickname: string | null } | null }; + export type UserQuery = { user: { id: string, name: string, role: UserRole, createdAt: unknown, nickname: string | null } | null }; export type UsersQueryVariables = Exact<{ input: UsersInput; @@ -162,8 +162,8 @@ describe('TypeScript Operations Plugin - Standalone', () => { }; export type UsersWithScalarInputQueryVariables = Exact<{ - from: any; - to?: any | null; + from: unknown; + to?: unknown | null; role?: UserRole | null; }>; @@ -654,9 +654,9 @@ describe('TypeScript Operations Plugin - Standalone', () => { /** UsersInput Description */ type UsersInput = { /** UsersInput from */ - from?: any; + from?: unknown | null | undefined; /** UsersInput to */ - to?: any; + to?: unknown | null | undefined; role?: UserRole | null | undefined; }; " @@ -802,7 +802,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { }>; - export type UserQuery = { user: { __typename: 'User', id: string, name: string, createdAt: any, bestFriend: { __typename: 'User', name: string } | null, goodFriends: Array<{ __typename: 'User', id: string }> } | null }; + export type UserQuery = { user: { __typename: 'User', id: string, name: string, createdAt: unknown, bestFriend: { __typename: 'User', name: string } | null, goodFriends: Array<{ __typename: 'User', id: string }> } | null }; " `); diff --git a/packages/plugins/typescript/resolvers/tests/__snapshots__/ts-resolvers.spec.ts.snap b/packages/plugins/typescript/resolvers/tests/__snapshots__/ts-resolvers.spec.ts.snap index 5b2d327f9c2..3960c3ecb53 100644 --- a/packages/plugins/typescript/resolvers/tests/__snapshots__/ts-resolvers.spec.ts.snap +++ b/packages/plugins/typescript/resolvers/tests/__snapshots__/ts-resolvers.spec.ts.snap @@ -13,7 +13,7 @@ export type Scalars = { Boolean: { input: boolean; output: boolean; } Int: { input: number; output: number; } Float: { input: number; output: number; } - MyScalar: { input: any; output: any; } + MyScalar: { input: unknown; output: unknown; } }; export type MyType = { @@ -628,7 +628,7 @@ export type Scalars = { Boolean: { input: boolean; output: boolean; } Int: { input: number; output: number; } Float: { input: number; output: number; } - MyScalar: { input: any; output: any; } + MyScalar: { input: unknown; output: unknown; } }; export type MyType = { diff --git a/packages/plugins/typescript/typescript/tests/typescript.spec.ts b/packages/plugins/typescript/typescript/tests/typescript.spec.ts index a19a185f624..a3e0d191a74 100644 --- a/packages/plugins/typescript/typescript/tests/typescript.spec.ts +++ b/packages/plugins/typescript/typescript/tests/typescript.spec.ts @@ -29,7 +29,7 @@ describe('TypeScript', () => { Int: { input: number; output: number; } Float: { input: number; output: number; } /** My custom scalar */ - A: { input: any; output: any; } + A: { input: unknown; output: unknown; } }; `); }); @@ -354,12 +354,12 @@ describe('TypeScript', () => { expect(result.content).not.toBeSimilarStringTo(`/** My custom scalar */`); expect(result.content).toBeSimilarStringTo(` export type Scalars = { - ID: { input: string; output: string; } - String: { input: string; output: string; } - Boolean: { input: boolean; output: boolean; } - Int: { input: number; output: number; } - Float: { input: number; output: number; } - A: { input: any; output: any; } + ID: { input: string; output: string; } + String: { input: string; output: string; } + Boolean: { input: boolean; output: boolean; } + Int: { input: number; output: number; } + Float: { input: number; output: number; } + A: { input: unknown; output: unknown; } }; `); }); @@ -2193,7 +2193,7 @@ describe('TypeScript', () => { Boolean: { input: boolean; output: boolean; } Int: { input: number; output: number; } Float: { input: number; output: number; } - MyScalar: { input: any; output: any; } + MyScalar: { input: unknown; output: unknown; } };`); expect(result.content).toBeSimilarStringTo(` @@ -2322,7 +2322,7 @@ describe('TypeScript', () => { const result = (await plugin( schema, [], - { defaultScalarType: 'unknown' }, + { defaultScalarType: 'any' }, { outputFile: '' }, )) as Types.ComplexPluginOutput; @@ -2333,7 +2333,7 @@ describe('TypeScript', () => { Boolean: { input: boolean; output: boolean; } Int: { input: number; output: number; } Float: { input: number; output: number; } - MyScalar: { input: unknown; output: unknown; } + MyScalar: { input: any; output: any; } };`); expect(result.content).toBeSimilarStringTo(` From 2efb931cc03fc3ae777460d8f6c1b239b60208de Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Thu, 15 Jan 2026 23:09:03 +1100 Subject: [PATCH 26/69] Decouple `typescript-operations` plugin from `typescript` plugin (#10572) * Decouple TypeScriptOperationVariablesToObject from typescript plugin * Add changeset * Remove typescript plugin dep * chore(dependencies): updated changesets for modified dependencies --------- Co-authored-by: github-actions[bot] --- ...ypescript-operations-10572-dependencies.md | 5 ++ .changeset/khaki-spies-admire.md | 9 +++ .../src/ts-operation-variables-to-object.ts | 77 ++++++++++++++++++- .../typescript/operations/src/visitor.ts | 2 - 4 files changed, 89 insertions(+), 4 deletions(-) create mode 100644 .changeset/@graphql-codegen_typescript-operations-10572-dependencies.md create mode 100644 .changeset/khaki-spies-admire.md diff --git a/.changeset/@graphql-codegen_typescript-operations-10572-dependencies.md b/.changeset/@graphql-codegen_typescript-operations-10572-dependencies.md new file mode 100644 index 00000000000..81018bf6546 --- /dev/null +++ b/.changeset/@graphql-codegen_typescript-operations-10572-dependencies.md @@ -0,0 +1,5 @@ +--- +"@graphql-codegen/typescript-operations": patch +--- +dependencies updates: + - Removed dependency [`@graphql-codegen/typescript@^5.0.7` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.7) (from `dependencies`) diff --git a/.changeset/khaki-spies-admire.md b/.changeset/khaki-spies-admire.md new file mode 100644 index 00000000000..efda9226e8a --- /dev/null +++ b/.changeset/khaki-spies-admire.md @@ -0,0 +1,9 @@ +--- +'@graphql-codegen/typescript-operations': major +--- + +BREAKING CHANGE: Decouple `typescript-operations` plugin from `typescript` plugin + +Previously, `TypeScriptOperationVariablesToObject` from `typescript-operations` was extending from `typescript` plugin. This made it (1) very hard to read, as we need to jump from base class <-> typescript class <-> typescript-operations class to understand the flow and (2) very hard to evolve the two independently (which is the point of this work). + +Since there's not much shared logic anyways, it's simpler to extend the `typescript-operations` class from the base class directly. diff --git a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts index 82f4c607e65..5639c14c2a0 100644 --- a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts +++ b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts @@ -1,4 +1,11 @@ -import { TypeScriptOperationVariablesToObject as TSOperationVariablesToObject } from '@graphql-codegen/typescript'; +import { Kind, TypeNode } from 'graphql'; +import { + ConvertNameFn, + NormalizedAvoidOptionalsConfig, + NormalizedScalarsMap, + OperationVariablesToObject, + ParsedEnumValuesMap, +} from '@graphql-codegen/visitor-plugin-common'; export const SCALARS = { ID: 'string | number', @@ -10,7 +17,40 @@ export const SCALARS = { const MAYBE_SUFFIX = ' | null'; -export class TypeScriptOperationVariablesToObject extends TSOperationVariablesToObject { +export class TypeScriptOperationVariablesToObject extends OperationVariablesToObject { + constructor( + _scalars: NormalizedScalarsMap, + _convertName: ConvertNameFn, + private _avoidOptionals: NormalizedAvoidOptionalsConfig, + private _immutableTypes: boolean, + _namespacedImportName: string | null, + _enumNames: string[], + _enumPrefix: boolean, + _enumSuffix: boolean, + _enumValues: ParsedEnumValuesMap, + _applyCoercion: boolean, + ) { + super( + _scalars, + _convertName, + _namespacedImportName, + _enumNames, + _enumPrefix, + _enumSuffix, + _enumValues, + _applyCoercion, + {}, + ); + } + + protected formatFieldString( + fieldName: string, + isNonNullType: boolean, + hasDefaultValue: boolean, + ): string { + return `${fieldName}${this.getAvoidOption(isNonNullType, hasDefaultValue) ? '?' : ''}`; + } + protected formatTypeString( fieldType: string, _isNonNullType: boolean, @@ -27,6 +67,35 @@ export class TypeScriptOperationVariablesToObject extends TSOperationVariablesTo return str; } + protected getAvoidOption(isNonNullType: boolean, hasDefaultValue: boolean) { + const options = this._avoidOptionals; + return ( + ((options.object || !options.defaultValue) && hasDefaultValue) || + (!options.object && !isNonNullType) + ); + } + + public wrapAstTypeWithModifiers( + baseType: string, + typeNode: TypeNode, + applyCoercion = false, + ): string { + if (typeNode.kind === Kind.NON_NULL_TYPE) { + const type = this.wrapAstTypeWithModifiers(baseType, typeNode.type, applyCoercion); + + return this.clearOptional(type); + } + if (typeNode.kind === Kind.LIST_TYPE) { + const innerType = this.wrapAstTypeWithModifiers(baseType, typeNode.type, applyCoercion); + const listInputCoercionExtension = applyCoercion ? ` | ${innerType}` : ''; + + return this.wrapMaybe( + `${this._immutableTypes ? 'ReadonlyArray' : 'Array'}<${innerType}>${listInputCoercionExtension}`, + ); + } + return this.wrapMaybe(baseType); + } + protected wrapMaybe(type: string): string { return type?.endsWith(MAYBE_SUFFIX) ? type : `${type}${MAYBE_SUFFIX}`; } @@ -34,4 +103,8 @@ export class TypeScriptOperationVariablesToObject extends TSOperationVariablesTo protected getScalar(name: string): string { return this._scalars?.[name]?.input ?? SCALARS[name] ?? 'unknown'; } + + protected getPunctuation(): string { + return ';'; + } } diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index af016195b19..b09d6324237 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -177,8 +177,6 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< this.config.enumSuffix, this.config.enumValues, this.config.arrayInputCoercion, - undefined, - undefined, ), ); this._declarationBlockConfig = { From b09eb0f102d0161b0f42c1b65fe4560e15288be0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 15 Jan 2026 12:09:32 +0000 Subject: [PATCH 27/69] chore(dependencies): updated changesets for modified dependencies --- .../@graphql-codegen_typescript-operations-10496-dependencies.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md b/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md index e66f900bbf7..47502ec48d5 100644 --- a/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md +++ b/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md @@ -3,3 +3,4 @@ --- dependencies updates: - Added dependency [`@graphql-codegen/schema-ast@^5.0.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/schema-ast/v/5.0.0) (to `dependencies`) + - Removed dependency [`@graphql-codegen/typescript@^5.0.7` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.7) (from `dependencies`) From fcff92014b1b5f919c79da44e4fa609b0d53226f Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Fri, 16 Jan 2026 00:55:47 +1100 Subject: [PATCH 28/69] Add `inputMaybeValue` to allow changing Variables and Input nullable types (#10573) * Shuffle methods to group things together, cleanup * Wire up _inputMaybeValue and organise config * Wire up inputMaybeValue * Add inputMaybeValue test * Update tests * Add changeset --- .changeset/fuzzy-poets-doubt.md | 5 + dev-test/githunt/typed-document-nodes.ts | 8 +- dev-test/githunt/types.avoidOptionals.ts | 8 +- dev-test/githunt/types.d.ts | 8 +- dev-test/githunt/types.enumsAsTypes.ts | 8 +- .../githunt/types.flatten.preResolveTypes.ts | 8 +- dev-test/githunt/types.immutableTypes.ts | 8 +- ...ypes.preResolveTypes.onlyOperationTypes.ts | 8 +- dev-test/githunt/types.preResolveTypes.ts | 8 +- dev-test/githunt/types.ts | 8 +- .../import-schema-types/_types.generated.ts | 2 +- dev-test/star-wars/types.avoidOptionals.ts | 20 +-- dev-test/star-wars/types.excludeQueryAlpha.ts | 18 +-- dev-test/star-wars/types.excludeQueryBeta.ts | 18 +-- .../star-wars/types.globallyAvailable.d.ts | 20 +-- dev-test/star-wars/types.immutableTypes.ts | 20 +-- ...ypes.preResolveTypes.onlyOperationTypes.ts | 20 +-- dev-test/star-wars/types.preResolveTypes.ts | 20 +-- dev-test/star-wars/types.skipSchema.ts | 20 +-- dev-test/star-wars/types.ts | 20 +-- .../typescript/operations/src/config.ts | 48 +++--- .../src/ts-operation-variables-to-object.ts | 40 ++--- .../typescript/operations/src/visitor.ts | 24 ++- .../operations/tests/ts-documents.spec.ts | 22 +-- ...ts.standalone.default-scalar-types.spec.ts | 24 +-- ...-documents.standalone.import-types.spec.ts | 18 +-- .../ts-documents.standalone.input.spec.ts | 142 +++++++++++++----- .../tests/ts-documents.standalone.spec.ts | 4 +- .../client/tests/client-preset.enum.spec.ts | 4 +- 29 files changed, 340 insertions(+), 241 deletions(-) create mode 100644 .changeset/fuzzy-poets-doubt.md diff --git a/.changeset/fuzzy-poets-doubt.md b/.changeset/fuzzy-poets-doubt.md new file mode 100644 index 00000000000..8a8e0a30bc7 --- /dev/null +++ b/.changeset/fuzzy-poets-doubt.md @@ -0,0 +1,5 @@ +--- +'@graphql-codegen/typescript-operations': patch +--- + +Re-implement inputMaybeValue diff --git a/dev-test/githunt/typed-document-nodes.ts b/dev-test/githunt/typed-document-nodes.ts index 1bae63e7263..f4908eadb66 100644 --- a/dev-test/githunt/typed-document-nodes.ts +++ b/dev-test/githunt/typed-document-nodes.ts @@ -19,8 +19,8 @@ export type OnCommentAddedSubscription = { export type CommentQueryVariables = Exact<{ repoFullName: string; - limit?: number | null; - offset?: number | null; + limit?: number | null | undefined; + offset?: number | null | undefined; }>; export type CommentQuery = { @@ -78,8 +78,8 @@ export type FeedEntryFragment = { export type FeedQueryVariables = Exact<{ type: FeedType; - offset?: number | null; - limit?: number | null; + offset?: number | null | undefined; + limit?: number | null | undefined; }>; export type FeedQuery = { diff --git a/dev-test/githunt/types.avoidOptionals.ts b/dev-test/githunt/types.avoidOptionals.ts index 36f1197dde8..e59e09522e2 100644 --- a/dev-test/githunt/types.avoidOptionals.ts +++ b/dev-test/githunt/types.avoidOptionals.ts @@ -17,8 +17,8 @@ export type OnCommentAddedSubscription = { export type CommentQueryVariables = Exact<{ repoFullName: string; - limit: number | null; - offset: number | null; + limit: number | null | undefined; + offset: number | null | undefined; }>; export type CommentQuery = { @@ -76,8 +76,8 @@ export type FeedEntryFragment = { export type FeedQueryVariables = Exact<{ type: FeedType; - offset: number | null; - limit: number | null; + offset: number | null | undefined; + limit: number | null | undefined; }>; export type FeedQuery = { diff --git a/dev-test/githunt/types.d.ts b/dev-test/githunt/types.d.ts index 1f81c577172..e5ca456fdf7 100644 --- a/dev-test/githunt/types.d.ts +++ b/dev-test/githunt/types.d.ts @@ -17,8 +17,8 @@ export type OnCommentAddedSubscription = { export type CommentQueryVariables = Exact<{ repoFullName: string; - limit?: number | null; - offset?: number | null; + limit?: number | null | undefined; + offset?: number | null | undefined; }>; export type CommentQuery = { @@ -76,8 +76,8 @@ export type FeedEntryFragment = { export type FeedQueryVariables = Exact<{ type: FeedType; - offset?: number | null; - limit?: number | null; + offset?: number | null | undefined; + limit?: number | null | undefined; }>; export type FeedQuery = { diff --git a/dev-test/githunt/types.enumsAsTypes.ts b/dev-test/githunt/types.enumsAsTypes.ts index 1f81c577172..e5ca456fdf7 100644 --- a/dev-test/githunt/types.enumsAsTypes.ts +++ b/dev-test/githunt/types.enumsAsTypes.ts @@ -17,8 +17,8 @@ export type OnCommentAddedSubscription = { export type CommentQueryVariables = Exact<{ repoFullName: string; - limit?: number | null; - offset?: number | null; + limit?: number | null | undefined; + offset?: number | null | undefined; }>; export type CommentQuery = { @@ -76,8 +76,8 @@ export type FeedEntryFragment = { export type FeedQueryVariables = Exact<{ type: FeedType; - offset?: number | null; - limit?: number | null; + offset?: number | null | undefined; + limit?: number | null | undefined; }>; export type FeedQuery = { diff --git a/dev-test/githunt/types.flatten.preResolveTypes.ts b/dev-test/githunt/types.flatten.preResolveTypes.ts index 94e9f8bb1c4..4689bd339ce 100644 --- a/dev-test/githunt/types.flatten.preResolveTypes.ts +++ b/dev-test/githunt/types.flatten.preResolveTypes.ts @@ -17,8 +17,8 @@ export type OnCommentAddedSubscription = { export type CommentQueryVariables = Exact<{ repoFullName: string; - limit?: number | null; - offset?: number | null; + limit?: number | null | undefined; + offset?: number | null | undefined; }>; export type CommentQuery = { @@ -52,8 +52,8 @@ export type CurrentUserForProfileQuery = { export type FeedQueryVariables = Exact<{ type: FeedType; - offset?: number | null; - limit?: number | null; + offset?: number | null | undefined; + limit?: number | null | undefined; }>; export type FeedQuery = { diff --git a/dev-test/githunt/types.immutableTypes.ts b/dev-test/githunt/types.immutableTypes.ts index d98b6ab7b81..9b38ec4a08a 100644 --- a/dev-test/githunt/types.immutableTypes.ts +++ b/dev-test/githunt/types.immutableTypes.ts @@ -17,8 +17,8 @@ export type OnCommentAddedSubscription = { export type CommentQueryVariables = Exact<{ repoFullName: string; - limit?: number | null; - offset?: number | null; + limit?: number | null | undefined; + offset?: number | null | undefined; }>; export type CommentQuery = { @@ -76,8 +76,8 @@ export type FeedEntryFragment = { export type FeedQueryVariables = Exact<{ type: FeedType; - offset?: number | null; - limit?: number | null; + offset?: number | null | undefined; + limit?: number | null | undefined; }>; export type FeedQuery = { diff --git a/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts index 1f81c577172..e5ca456fdf7 100644 --- a/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts @@ -17,8 +17,8 @@ export type OnCommentAddedSubscription = { export type CommentQueryVariables = Exact<{ repoFullName: string; - limit?: number | null; - offset?: number | null; + limit?: number | null | undefined; + offset?: number | null | undefined; }>; export type CommentQuery = { @@ -76,8 +76,8 @@ export type FeedEntryFragment = { export type FeedQueryVariables = Exact<{ type: FeedType; - offset?: number | null; - limit?: number | null; + offset?: number | null | undefined; + limit?: number | null | undefined; }>; export type FeedQuery = { diff --git a/dev-test/githunt/types.preResolveTypes.ts b/dev-test/githunt/types.preResolveTypes.ts index 1f81c577172..e5ca456fdf7 100644 --- a/dev-test/githunt/types.preResolveTypes.ts +++ b/dev-test/githunt/types.preResolveTypes.ts @@ -17,8 +17,8 @@ export type OnCommentAddedSubscription = { export type CommentQueryVariables = Exact<{ repoFullName: string; - limit?: number | null; - offset?: number | null; + limit?: number | null | undefined; + offset?: number | null | undefined; }>; export type CommentQuery = { @@ -76,8 +76,8 @@ export type FeedEntryFragment = { export type FeedQueryVariables = Exact<{ type: FeedType; - offset?: number | null; - limit?: number | null; + offset?: number | null | undefined; + limit?: number | null | undefined; }>; export type FeedQuery = { diff --git a/dev-test/githunt/types.ts b/dev-test/githunt/types.ts index 1f81c577172..e5ca456fdf7 100644 --- a/dev-test/githunt/types.ts +++ b/dev-test/githunt/types.ts @@ -17,8 +17,8 @@ export type OnCommentAddedSubscription = { export type CommentQueryVariables = Exact<{ repoFullName: string; - limit?: number | null; - offset?: number | null; + limit?: number | null | undefined; + offset?: number | null | undefined; }>; export type CommentQuery = { @@ -76,8 +76,8 @@ export type FeedEntryFragment = { export type FeedQueryVariables = Exact<{ type: FeedType; - offset?: number | null; - limit?: number | null; + offset?: number | null | undefined; + limit?: number | null | undefined; }>; export type FeedQuery = { diff --git a/dev-test/standalone-operations/import-schema-types/_types.generated.ts b/dev-test/standalone-operations/import-schema-types/_types.generated.ts index d1815ba4796..e45c3e222b3 100644 --- a/dev-test/standalone-operations/import-schema-types/_types.generated.ts +++ b/dev-test/standalone-operations/import-schema-types/_types.generated.ts @@ -5,7 +5,7 @@ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type WithVariablesQueryVariables = Exact<{ - role?: Types.UserRole | null; + role?: Types.UserRole | null | undefined; }>; export type WithVariablesQuery = { user: { id: string; name: string } | null }; diff --git a/dev-test/star-wars/types.avoidOptionals.ts b/dev-test/star-wars/types.avoidOptionals.ts index da39a5549a9..7b6ff963688 100644 --- a/dev-test/star-wars/types.avoidOptionals.ts +++ b/dev-test/star-wars/types.avoidOptionals.ts @@ -21,19 +21,19 @@ export type CreateReviewForEpisodeMutation = { }; export type ExcludeQueryAlphaQueryVariables = Exact<{ - episode: Episode | null; + episode: Episode | null | undefined; }>; export type ExcludeQueryAlphaQuery = { hero: { name: string } | { name: string } | null }; export type ExcludeQueryBetaQueryVariables = Exact<{ - episode: Episode | null; + episode: Episode | null | undefined; }>; export type ExcludeQueryBetaQuery = { hero: { name: string } | { name: string } | null }; export type HeroAndFriendsNamesQueryVariables = Exact<{ - episode: Episode | null; + episode: Episode | null | undefined; }>; export type HeroAndFriendsNamesQuery = { @@ -53,7 +53,7 @@ export type HeroAppearsInQuery = { }; export type HeroDetailsQueryVariables = Exact<{ - episode: Episode | null; + episode: Episode | null | undefined; }>; export type HeroDetailsQuery = { @@ -70,7 +70,7 @@ type HeroDetails_Human_Fragment = { height: number | null; name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; export type HeroDetailsWithFragmentQueryVariables = Exact<{ - episode: Episode | null; + episode: Episode | null | undefined; }>; export type HeroDetailsWithFragmentQuery = { @@ -81,13 +81,13 @@ export type HeroDetailsWithFragmentQuery = { }; export type HeroNameQueryVariables = Exact<{ - episode: Episode | null; + episode: Episode | null | undefined; }>; export type HeroNameQuery = { hero: { name: string } | { name: string } | null }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ - episode: Episode | null; + episode: Episode | null | undefined; includeName: boolean; }>; @@ -96,7 +96,7 @@ export type HeroNameConditionalInclusionQuery = { }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ - episode: Episode | null; + episode: Episode | null | undefined; skipName: boolean; }>; @@ -105,7 +105,7 @@ export type HeroNameConditionalExclusionQuery = { }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ - episode: Episode | null; + episode: Episode | null | undefined; }>; export type HeroParentTypeDependentFieldQuery = { @@ -122,7 +122,7 @@ export type HeroParentTypeDependentFieldQuery = { }; export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ - episode: Episode | null; + episode: Episode | null | undefined; }>; export type HeroTypeDependentAliasedFieldQuery = { diff --git a/dev-test/star-wars/types.excludeQueryAlpha.ts b/dev-test/star-wars/types.excludeQueryAlpha.ts index 9e39464ddf0..eb57ff98370 100644 --- a/dev-test/star-wars/types.excludeQueryAlpha.ts +++ b/dev-test/star-wars/types.excludeQueryAlpha.ts @@ -21,13 +21,13 @@ export type CreateReviewForEpisodeMutation = { }; export type ExcludeQueryBetaQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type ExcludeQueryBetaQuery = { hero: { name: string } | { name: string } | null }; export type HeroAndFriendsNamesQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroAndFriendsNamesQuery = { @@ -47,7 +47,7 @@ export type HeroAppearsInQuery = { }; export type HeroDetailsQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroDetailsQuery = { @@ -64,7 +64,7 @@ type HeroDetails_Human_Fragment = { height: number | null; name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; export type HeroDetailsWithFragmentQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroDetailsWithFragmentQuery = { @@ -75,13 +75,13 @@ export type HeroDetailsWithFragmentQuery = { }; export type HeroNameQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroNameQuery = { hero: { name: string } | { name: string } | null }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; includeName: boolean; }>; @@ -90,7 +90,7 @@ export type HeroNameConditionalInclusionQuery = { }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; skipName: boolean; }>; @@ -99,7 +99,7 @@ export type HeroNameConditionalExclusionQuery = { }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroParentTypeDependentFieldQuery = { @@ -116,7 +116,7 @@ export type HeroParentTypeDependentFieldQuery = { }; export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroTypeDependentAliasedFieldQuery = { diff --git a/dev-test/star-wars/types.excludeQueryBeta.ts b/dev-test/star-wars/types.excludeQueryBeta.ts index ee1d68ff899..e34e9d26455 100644 --- a/dev-test/star-wars/types.excludeQueryBeta.ts +++ b/dev-test/star-wars/types.excludeQueryBeta.ts @@ -21,13 +21,13 @@ export type CreateReviewForEpisodeMutation = { }; export type ExcludeQueryAlphaQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type ExcludeQueryAlphaQuery = { hero: { name: string } | { name: string } | null }; export type HeroAndFriendsNamesQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroAndFriendsNamesQuery = { @@ -47,7 +47,7 @@ export type HeroAppearsInQuery = { }; export type HeroDetailsQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroDetailsQuery = { @@ -64,7 +64,7 @@ type HeroDetails_Human_Fragment = { height: number | null; name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; export type HeroDetailsWithFragmentQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroDetailsWithFragmentQuery = { @@ -75,13 +75,13 @@ export type HeroDetailsWithFragmentQuery = { }; export type HeroNameQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroNameQuery = { hero: { name: string } | { name: string } | null }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; includeName: boolean; }>; @@ -90,7 +90,7 @@ export type HeroNameConditionalInclusionQuery = { }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; skipName: boolean; }>; @@ -99,7 +99,7 @@ export type HeroNameConditionalExclusionQuery = { }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroParentTypeDependentFieldQuery = { @@ -116,7 +116,7 @@ export type HeroParentTypeDependentFieldQuery = { }; export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroTypeDependentAliasedFieldQuery = { diff --git a/dev-test/star-wars/types.globallyAvailable.d.ts b/dev-test/star-wars/types.globallyAvailable.d.ts index 36d3f1a7b10..aab799829d6 100644 --- a/dev-test/star-wars/types.globallyAvailable.d.ts +++ b/dev-test/star-wars/types.globallyAvailable.d.ts @@ -21,19 +21,19 @@ type CreateReviewForEpisodeMutation = { }; type ExcludeQueryAlphaQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; type ExcludeQueryAlphaQuery = { hero: { name: string } | { name: string } | null }; type ExcludeQueryBetaQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; type ExcludeQueryBetaQuery = { hero: { name: string } | { name: string } | null }; type HeroAndFriendsNamesQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; type HeroAndFriendsNamesQuery = { @@ -53,7 +53,7 @@ type HeroAppearsInQuery = { }; type HeroDetailsQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; type HeroDetailsQuery = { @@ -70,7 +70,7 @@ type HeroDetails_Human_Fragment = { height: number | null; name: string }; type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; type HeroDetailsWithFragmentQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; type HeroDetailsWithFragmentQuery = { @@ -81,27 +81,27 @@ type HeroDetailsWithFragmentQuery = { }; type HeroNameQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; type HeroNameQuery = { hero: { name: string } | { name: string } | null }; type HeroNameConditionalInclusionQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; includeName: boolean; }>; type HeroNameConditionalInclusionQuery = { hero: { name?: string } | { name?: string } | null }; type HeroNameConditionalExclusionQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; skipName: boolean; }>; type HeroNameConditionalExclusionQuery = { hero: { name?: string } | { name?: string } | null }; type HeroParentTypeDependentFieldQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; type HeroParentTypeDependentFieldQuery = { @@ -118,7 +118,7 @@ type HeroParentTypeDependentFieldQuery = { }; type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; type HeroTypeDependentAliasedFieldQuery = { diff --git a/dev-test/star-wars/types.immutableTypes.ts b/dev-test/star-wars/types.immutableTypes.ts index d8335653496..3e72e723968 100644 --- a/dev-test/star-wars/types.immutableTypes.ts +++ b/dev-test/star-wars/types.immutableTypes.ts @@ -21,7 +21,7 @@ export type CreateReviewForEpisodeMutation = { }; export type ExcludeQueryAlphaQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type ExcludeQueryAlphaQuery = { @@ -29,7 +29,7 @@ export type ExcludeQueryAlphaQuery = { }; export type ExcludeQueryBetaQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type ExcludeQueryBetaQuery = { @@ -37,7 +37,7 @@ export type ExcludeQueryBetaQuery = { }; export type HeroAndFriendsNamesQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroAndFriendsNamesQuery = { @@ -67,7 +67,7 @@ export type HeroAppearsInQuery = { }; export type HeroDetailsQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroDetailsQuery = { @@ -87,7 +87,7 @@ type HeroDetails_Human_Fragment = { readonly height: number | null; readonly nam export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; export type HeroDetailsWithFragmentQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroDetailsWithFragmentQuery = { @@ -98,7 +98,7 @@ export type HeroDetailsWithFragmentQuery = { }; export type HeroNameQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroNameQuery = { @@ -106,7 +106,7 @@ export type HeroNameQuery = { }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; includeName: boolean; }>; @@ -115,7 +115,7 @@ export type HeroNameConditionalInclusionQuery = { }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; skipName: boolean; }>; @@ -124,7 +124,7 @@ export type HeroNameConditionalExclusionQuery = { }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroParentTypeDependentFieldQuery = { @@ -149,7 +149,7 @@ export type HeroParentTypeDependentFieldQuery = { }; export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroTypeDependentAliasedFieldQuery = { diff --git a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts index 53346ac22c3..01475ff009f 100644 --- a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts @@ -21,19 +21,19 @@ export type CreateReviewForEpisodeMutation = { }; export type ExcludeQueryAlphaQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type ExcludeQueryAlphaQuery = { hero: { name: string } | { name: string } | null }; export type ExcludeQueryBetaQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type ExcludeQueryBetaQuery = { hero: { name: string } | { name: string } | null }; export type HeroAndFriendsNamesQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroAndFriendsNamesQuery = { @@ -53,7 +53,7 @@ export type HeroAppearsInQuery = { }; export type HeroDetailsQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroDetailsQuery = { @@ -70,7 +70,7 @@ type HeroDetails_Human_Fragment = { height: number | null; name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; export type HeroDetailsWithFragmentQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroDetailsWithFragmentQuery = { @@ -81,13 +81,13 @@ export type HeroDetailsWithFragmentQuery = { }; export type HeroNameQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroNameQuery = { hero: { name: string } | { name: string } | null }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; includeName: boolean; }>; @@ -96,7 +96,7 @@ export type HeroNameConditionalInclusionQuery = { }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; skipName: boolean; }>; @@ -105,7 +105,7 @@ export type HeroNameConditionalExclusionQuery = { }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroParentTypeDependentFieldQuery = { @@ -122,7 +122,7 @@ export type HeroParentTypeDependentFieldQuery = { }; export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroTypeDependentAliasedFieldQuery = { diff --git a/dev-test/star-wars/types.preResolveTypes.ts b/dev-test/star-wars/types.preResolveTypes.ts index 53346ac22c3..01475ff009f 100644 --- a/dev-test/star-wars/types.preResolveTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.ts @@ -21,19 +21,19 @@ export type CreateReviewForEpisodeMutation = { }; export type ExcludeQueryAlphaQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type ExcludeQueryAlphaQuery = { hero: { name: string } | { name: string } | null }; export type ExcludeQueryBetaQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type ExcludeQueryBetaQuery = { hero: { name: string } | { name: string } | null }; export type HeroAndFriendsNamesQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroAndFriendsNamesQuery = { @@ -53,7 +53,7 @@ export type HeroAppearsInQuery = { }; export type HeroDetailsQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroDetailsQuery = { @@ -70,7 +70,7 @@ type HeroDetails_Human_Fragment = { height: number | null; name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; export type HeroDetailsWithFragmentQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroDetailsWithFragmentQuery = { @@ -81,13 +81,13 @@ export type HeroDetailsWithFragmentQuery = { }; export type HeroNameQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroNameQuery = { hero: { name: string } | { name: string } | null }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; includeName: boolean; }>; @@ -96,7 +96,7 @@ export type HeroNameConditionalInclusionQuery = { }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; skipName: boolean; }>; @@ -105,7 +105,7 @@ export type HeroNameConditionalExclusionQuery = { }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroParentTypeDependentFieldQuery = { @@ -122,7 +122,7 @@ export type HeroParentTypeDependentFieldQuery = { }; export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroTypeDependentAliasedFieldQuery = { diff --git a/dev-test/star-wars/types.skipSchema.ts b/dev-test/star-wars/types.skipSchema.ts index 53346ac22c3..01475ff009f 100644 --- a/dev-test/star-wars/types.skipSchema.ts +++ b/dev-test/star-wars/types.skipSchema.ts @@ -21,19 +21,19 @@ export type CreateReviewForEpisodeMutation = { }; export type ExcludeQueryAlphaQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type ExcludeQueryAlphaQuery = { hero: { name: string } | { name: string } | null }; export type ExcludeQueryBetaQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type ExcludeQueryBetaQuery = { hero: { name: string } | { name: string } | null }; export type HeroAndFriendsNamesQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroAndFriendsNamesQuery = { @@ -53,7 +53,7 @@ export type HeroAppearsInQuery = { }; export type HeroDetailsQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroDetailsQuery = { @@ -70,7 +70,7 @@ type HeroDetails_Human_Fragment = { height: number | null; name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; export type HeroDetailsWithFragmentQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroDetailsWithFragmentQuery = { @@ -81,13 +81,13 @@ export type HeroDetailsWithFragmentQuery = { }; export type HeroNameQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroNameQuery = { hero: { name: string } | { name: string } | null }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; includeName: boolean; }>; @@ -96,7 +96,7 @@ export type HeroNameConditionalInclusionQuery = { }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; skipName: boolean; }>; @@ -105,7 +105,7 @@ export type HeroNameConditionalExclusionQuery = { }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroParentTypeDependentFieldQuery = { @@ -122,7 +122,7 @@ export type HeroParentTypeDependentFieldQuery = { }; export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroTypeDependentAliasedFieldQuery = { diff --git a/dev-test/star-wars/types.ts b/dev-test/star-wars/types.ts index 53346ac22c3..01475ff009f 100644 --- a/dev-test/star-wars/types.ts +++ b/dev-test/star-wars/types.ts @@ -21,19 +21,19 @@ export type CreateReviewForEpisodeMutation = { }; export type ExcludeQueryAlphaQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type ExcludeQueryAlphaQuery = { hero: { name: string } | { name: string } | null }; export type ExcludeQueryBetaQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type ExcludeQueryBetaQuery = { hero: { name: string } | { name: string } | null }; export type HeroAndFriendsNamesQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroAndFriendsNamesQuery = { @@ -53,7 +53,7 @@ export type HeroAppearsInQuery = { }; export type HeroDetailsQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroDetailsQuery = { @@ -70,7 +70,7 @@ type HeroDetails_Human_Fragment = { height: number | null; name: string }; export type HeroDetailsFragment = HeroDetails_Droid_Fragment | HeroDetails_Human_Fragment; export type HeroDetailsWithFragmentQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroDetailsWithFragmentQuery = { @@ -81,13 +81,13 @@ export type HeroDetailsWithFragmentQuery = { }; export type HeroNameQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroNameQuery = { hero: { name: string } | { name: string } | null }; export type HeroNameConditionalInclusionQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; includeName: boolean; }>; @@ -96,7 +96,7 @@ export type HeroNameConditionalInclusionQuery = { }; export type HeroNameConditionalExclusionQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; skipName: boolean; }>; @@ -105,7 +105,7 @@ export type HeroNameConditionalExclusionQuery = { }; export type HeroParentTypeDependentFieldQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroParentTypeDependentFieldQuery = { @@ -122,7 +122,7 @@ export type HeroParentTypeDependentFieldQuery = { }; export type HeroTypeDependentAliasedFieldQueryVariables = Exact<{ - episode?: Episode | null; + episode?: Episode | null | undefined; }>; export type HeroTypeDependentAliasedFieldQuery = { diff --git a/packages/plugins/typescript/operations/src/config.ts b/packages/plugins/typescript/operations/src/config.ts index 9dcbcb6ce01..b7f3edb545b 100644 --- a/packages/plugins/typescript/operations/src/config.ts +++ b/packages/plugins/typescript/operations/src/config.ts @@ -230,11 +230,13 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { */ addOperationExport?: boolean; /** - * @description Allow to override the type value of `Maybe`. + * @description Allows overriding the type value of nullable fields to match GraphQL client's runtime behaviour. * @default T | null * * @exampleMarkdown * ## Allow undefined + * By default, a GraphQL server will return either the expected type or `null` for a nullable field. + * `maybeValue` option could be used to change this behaviour if your GraphQL client does something different such as returning `undefined`. * ```ts filename="codegen.ts" * import type { CodegenConfig } from '@graphql-codegen/cli'; * @@ -242,7 +244,7 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { * // ... * generates: { * 'path/to/file.ts': { - * plugins: ['typescript'], + * plugins: ['typescript-operations'], * config: { * maybeValue: 'T | null | undefined' * }, @@ -251,26 +253,38 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { * }; * export default config; * ``` + */ + maybeValue?: string; + + /** + * @description Allows overriding the type of Input and Variables nullable types. + * @default T | null | undefined + * + * @exampleMarkdown + * ## Disallow `undefined` + * Disallowing `undefined` is useful if you want to force explicit null to be passed in as Variables to the server. Use `inputMaybeValue: 'T | null'` with `avoidOptionals.inputValue: true` to achieve this. * - * ## Allow `null` in resolvers: * ```ts filename="codegen.ts" - * import type { CodegenConfig } from '@graphql-codegen/cli'; + * import type { CodegenConfig } from '@graphql-codegen/cli' * - * const config: CodegenConfig = { - * // ... - * generates: { - * 'path/to/file.ts': { - * plugins: ['typescript'], - * config: { - * maybeValue: 'T extends PromiseLike ? Promise : T | null' - * }, - * }, - * }, - * }; - * export default config; + * const config: CodegenConfig = { + * // ... + * generates: { + * 'path/to/file.ts': { + * plugins: ['typescript-operations'], + * config: { + * avoidOptionals: { + * inputValue: true, + * }, + * inputMaybeValue: 'T | null' + * } + * } + * } + * } + * export default config * ``` */ - maybeValue?: string; + inputMaybeValue?: string; /** * @description Adds undefined as a possible type for query variables diff --git a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts index 5639c14c2a0..8bad09fb74e 100644 --- a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts +++ b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts @@ -15,14 +15,16 @@ export const SCALARS = { Boolean: 'boolean', }; -const MAYBE_SUFFIX = ' | null'; - export class TypeScriptOperationVariablesToObject extends OperationVariablesToObject { constructor( + private _config: { + avoidOptionals: NormalizedAvoidOptionalsConfig; + immutableTypes: boolean; + inputMaybeValue: string; + inputMaybeValueSuffix: string; + }, _scalars: NormalizedScalarsMap, _convertName: ConvertNameFn, - private _avoidOptionals: NormalizedAvoidOptionalsConfig, - private _immutableTypes: boolean, _namespacedImportName: string | null, _enumNames: string[], _enumPrefix: boolean, @@ -60,21 +62,31 @@ export class TypeScriptOperationVariablesToObject extends OperationVariablesToOb } protected clearOptional(str: string): string { - if (str?.endsWith(MAYBE_SUFFIX)) { - return (str = str.substring(0, str.length - MAYBE_SUFFIX.length)); + const maybeSuffix = this._config.inputMaybeValueSuffix; + + if (str.endsWith(maybeSuffix)) { + return (str = str.substring(0, str.length - maybeSuffix.length)); } return str; } - protected getAvoidOption(isNonNullType: boolean, hasDefaultValue: boolean) { - const options = this._avoidOptionals; + protected getAvoidOption(isNonNullType: boolean, hasDefaultValue: boolean): boolean { + const options = this._config.avoidOptionals; return ( ((options.object || !options.defaultValue) && hasDefaultValue) || (!options.object && !isNonNullType) ); } + protected getScalar(name: string): string { + return this._scalars[name]?.input ?? SCALARS[name] ?? 'unknown'; + } + + protected getPunctuation(): string { + return ';'; + } + public wrapAstTypeWithModifiers( baseType: string, typeNode: TypeNode, @@ -90,21 +102,15 @@ export class TypeScriptOperationVariablesToObject extends OperationVariablesToOb const listInputCoercionExtension = applyCoercion ? ` | ${innerType}` : ''; return this.wrapMaybe( - `${this._immutableTypes ? 'ReadonlyArray' : 'Array'}<${innerType}>${listInputCoercionExtension}`, + `${this._config.immutableTypes ? 'ReadonlyArray' : 'Array'}<${innerType}>${listInputCoercionExtension}`, ); } return this.wrapMaybe(baseType); } protected wrapMaybe(type: string): string { - return type?.endsWith(MAYBE_SUFFIX) ? type : `${type}${MAYBE_SUFFIX}`; - } + const maybeSuffix = this._config.inputMaybeValueSuffix; - protected getScalar(name: string): string { - return this._scalars?.[name]?.input ?? SCALARS[name] ?? 'unknown'; - } - - protected getPunctuation(): string { - return ';'; + return type.endsWith(maybeSuffix) ? type : `${type}${maybeSuffix}`; } } diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index b09d6324237..706a54e7811 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -57,6 +57,7 @@ export interface TypeScriptDocumentsParsedConfig extends ParsedDocumentsConfig { immutableTypes: boolean; noExport: boolean; maybeValue: string; + inputMaybeValue: string; allowUndefinedQueryVariables: boolean; enumType: ConvertSchemaEnumToDeclarationBlockString['outputType']; enumValues: ParsedEnumValuesMap; @@ -78,6 +79,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< protected _usedNamedInputTypes: UsedNamedInputTypes = {}; protected _needsExactUtilityType: boolean = false; private _outputPath: string; + private _inputMaybeValueSuffix: string; constructor( schema: GraphQLSchema, @@ -104,6 +106,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< ignoreEnumValuesFromSchema: getConfigValue(config.ignoreEnumValuesFromSchema, false), futureProofEnums: getConfigValue(config.futureProofEnums, false), maybeValue: getConfigValue(config.maybeValue, 'T | null'), + inputMaybeValue: getConfigValue(config.inputMaybeValue, 'T | null | undefined'), } as TypeScriptDocumentsParsedConfig, schema, ); @@ -159,18 +162,25 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< this.config, ), ); + + this._inputMaybeValueSuffix = this.config.inputMaybeValue.replace('T', ''); // e.g. turns `T | null | undefined` to ` | null | undefined` + const enumsNames = Object.keys(schema.getTypeMap()).filter(typeName => isEnumType(schema.getType(typeName)), ); this.setVariablesTransformer( new TypeScriptOperationVariablesToObject( + { + // FIXME: this is the legacy avoidOptionals which was used to make Result fields non-optional. This use case is no longer valid. + // It's also being used for Variables so people could already be using it. + // Maybe it's better to deprecate and remove, to see what users think. + avoidOptionals: this.config.avoidOptionals, + immutableTypes: this.config.immutableTypes, + inputMaybeValue: this.config.inputMaybeValue, + inputMaybeValueSuffix: this._inputMaybeValueSuffix, + }, this.scalars, this.convertName.bind(this), - // FIXME: this is the legacy avoidOptionals which was used to make Result fields non-optional. This use case is no longer valid. - // It's also being used for Variables so people could already be using it. - // Maybe it's better to deprecate and remove, to see what users think. - this.config.avoidOptionals, - this.config.immutableTypes, this.config.namespacedImportName, enumsNames, this.config.enumPrefix, @@ -274,7 +284,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< typePart = usedInputType.tsType; // If the schema is correct, when reversing typeNodes, the first node would be `NamedType`, which means we can safely set it as the base for typePart if (!typeNode.isNonNullable) { - typePart += ' | null | undefined'; + typePart += this._inputMaybeValueSuffix; } continue; } @@ -282,7 +292,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< if (typeNode.type === 'ListType') { typePart = `Array<${typePart}>`; if (!typeNode.isNonNullable) { - typePart += ' | null | undefined'; + typePart += this._inputMaybeValueSuffix; } } } diff --git a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts index 4646a7ed428..8dd5618a78a 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts @@ -2869,13 +2869,13 @@ export type Q2Query = { search: Array< }; export type TestQueryQueryVariables = Exact<{ - username?: string | null; - email?: string | null; + username?: string | null | undefined; + email?: string | null | undefined; password: string; - input?: InputType | null; + input?: InputType | null | undefined; mandatoryInput: InputType; - testArray?: Array | string | null; - requireString: Array | string; + testArray?: Array | string | null | undefined; + requireString: Array | string; innerRequired: Array | string; }>; @@ -2904,7 +2904,7 @@ export type Q2Query = { search: Array< expect(content).toMatchInlineSnapshot( ` "export type TestQueryQueryVariables = Exact<{ - test?: unknown | null; + test?: unknown | null | undefined; }>; @@ -3179,7 +3179,7 @@ export type Q2Query = { search: Array< expect(content).toMatchInlineSnapshot(` "export type UsersQueryVariables = Exact<{ - reverse?: boolean | null; + reverse?: boolean | null | undefined; }>; @@ -5158,8 +5158,8 @@ function test(q: GetEntityBrandDataQuery): void { expect(content).toMatchInlineSnapshot(` "export type UserQueryVariables = Exact<{ - testArray?: Array | string | null; - requireString: Array | string; + testArray?: Array | string | null | undefined; + requireString: Array | string; innerRequired: Array | string; }>; @@ -5202,8 +5202,8 @@ function test(q: GetEntityBrandDataQuery): void { expect(content).toMatchInlineSnapshot(` "export type UserQueryVariables = Exact<{ - testArray?: Array | null; - requireString: Array; + testArray?: Array | null | undefined; + requireString: Array; innerRequired: Array; }>; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts index bb55e79e7ea..ecb60c75d73 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts @@ -79,10 +79,10 @@ describe('TypeScript Operations Plugin - Default Scalar types', () => { export type UserQueryVariables = Exact<{ nonNullableDate: unknown; - nullableDate?: unknown | null; - dateArray1?: Array | unknown | null; - dateArray2: Array | unknown; - dateArray3?: Array | unknown | null; + nullableDate?: unknown | null | undefined; + dateArray1?: Array | unknown | null | undefined; + dateArray2: Array | unknown; + dateArray3?: Array | unknown | null | undefined; dateArray4: Array | unknown; input: UserInput; }>; @@ -172,10 +172,10 @@ describe('TypeScript Operations Plugin - Default Scalar types', () => { export type UserQueryVariables = Exact<{ nonNullableDate: any; - nullableDate?: any | null; - dateArray1?: Array | any | null; - dateArray2: Array | any; - dateArray3?: Array | any | null; + nullableDate?: any | null | undefined; + dateArray1?: Array | any | null | undefined; + dateArray2: Array | any; + dateArray3?: Array | any | null | undefined; dateArray4: Array | any; input: UserInput; }>; @@ -265,10 +265,10 @@ describe('TypeScript Operations Plugin - Default Scalar types', () => { export type UserQueryVariables = Exact<{ nonNullableDate: Date; - nullableDate?: Date | null; - dateArray1?: Array | Date | null; - dateArray2: Array | Date; - dateArray3?: Array | Date | null; + nullableDate?: Date | null | undefined; + dateArray1?: Array | Date | null | undefined; + dateArray2: Array | Date; + dateArray3?: Array | Date | null | undefined; dateArray4: Array | Date; input: UserInput; }>; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts index fd7f2687d21..7f09e1440d0 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts @@ -135,8 +135,8 @@ describe('TypeScript Operations Plugin - Import Types', () => { export type UsersWithScalarInputQueryVariables = Exact<{ from: unknown; - to?: unknown | null; - role?: TypeImport.UserRole | null; + to?: unknown | null | undefined; + role?: TypeImport.UserRole | null | undefined; }>; @@ -279,8 +279,8 @@ describe('TypeScript Operations Plugin - Import Types', () => { export type UsersWithScalarInputQueryVariables = Exact<{ from: unknown; - to?: unknown | null; - role?: TypeImport.UserRole | null; + to?: unknown | null | undefined; + role?: TypeImport.UserRole | null | undefined; }>; @@ -375,11 +375,11 @@ describe('TypeScript Operations Plugin - Import Types', () => { "type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ - id?: string | null; - name?: string | null; - bool?: boolean | null; - int?: number | null; - float?: number | null; + id?: string | null | undefined; + name?: string | null | undefined; + bool?: boolean | null | undefined; + int?: number | null | undefined; + float?: number | null | undefined; }>; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts index 3dc3b25f127..a67c55b8f09 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts @@ -10,17 +10,6 @@ describe('TypeScript Operations Plugin - Input', () => { users(input: UsersInput!, ageRange1: [Int], ageRange2: [Int]!, ageRange3: [Int!], ageRange4: [Int!]!): [User!]! } - type ResponseError { - error: ResponseErrorType! - } - - enum ResponseErrorType { - NOT_FOUND - INPUT_VALIDATION_ERROR - FORBIDDEN_ERROR - UNEXPECTED_ERROR - } - type User { id: ID! ageRange1: [Int] @@ -129,10 +118,10 @@ describe('TypeScript Operations Plugin - Input', () => { export type UsersWithScalarInputQueryVariables = Exact<{ inputNonNullable: UsersInput; - inputNullable?: UsersInput | null; - ageRange1?: Array | number | null; - ageRange2: Array | number; - ageRange3?: Array | number | null; + inputNullable?: UsersInput | null | undefined; + ageRange1?: Array | number | null | undefined; + ageRange2: Array | number; + ageRange3?: Array | number | null | undefined; ageRange4: Array | number; }>; @@ -150,17 +139,6 @@ describe('TypeScript Operations Plugin - Input', () => { users(input: UsersInput!): [User!]! } - type ResponseError { - error: ResponseErrorType! - } - - enum ResponseErrorType { - NOT_FOUND - INPUT_VALIDATION_ERROR - FORBIDDEN_ERROR - UNEXPECTED_ERROR - } - type User { id: ID! ageRange1: [Int] @@ -257,7 +235,7 @@ describe('TypeScript Operations Plugin - Input', () => { export type UsersWithScalarInputQueryVariables = Exact<{ inputNonNullable: UsersInput; - inputNullable?: UsersInput | null; + inputNullable?: UsersInput | null | undefined; }>; @@ -276,17 +254,6 @@ describe('TypeScript Operations Plugin - Input', () => { users(input: UsersInput!): [User!]! } - type ResponseError { - error: ResponseErrorType! - } - - enum ResponseErrorType { - NOT_FOUND - INPUT_VALIDATION_ERROR - FORBIDDEN_ERROR - UNEXPECTED_ERROR - } - type User { id: ID! ageRange1: [Int] @@ -374,7 +341,7 @@ describe('TypeScript Operations Plugin - Input', () => { export type UsersQueryVariables = Exact<{ inputNonNullable: UsersInput; - inputNullable?: UsersInput | null; + inputNullable?: UsersInput | null | undefined; }>; @@ -384,4 +351,101 @@ describe('TypeScript Operations Plugin - Input', () => { validateTs(result, undefined, undefined, undefined, undefined, true); }); + + it('generates with custom inputMaybeValue', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(input: UserInput!): User + } + + type User { + id: ID! + } + + input UserInput { + dateRange1: [DateTime] + dateRange2: [DateTime]! + dateRange3: [DateTime!] + dateRange4: [DateTime!]! + bestFriend: UserBestFriendInput + nestedInput: UserInput + } + + input UserBestFriendInput { + name: String + bestFriendDateRange1: [DateTime] + bestFriendDateRange2: [DateTime]! + bestFriendDateRange3: [DateTime!] + bestFriendDateRange4: [DateTime!]! + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query Users( + $input: UserInput + $dateTime1: DateTime + $dateTime2: DateTime! + $dateTimeArray1: [DateTime] + $dateTimeArray2: [DateTime]! + $dateTimeArray3: [DateTime!] + $dateTimeArray4: [DateTime!]! + ) { + user { + __typename + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + inputMaybeValue: 'T | null', + scalars: { + DateTime: 'Date', + }, + }, + { outputFile: '' } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + type UserInput = { + dateRange1?: Array | null; + dateRange2: Array; + dateRange3?: Array | null; + dateRange4: Array; + bestFriend?: UserBestFriendInput | null; + nestedInput?: UserInput | null; + }; + + type UserBestFriendInput = { + name?: string | null; + bestFriendDateRange1?: Array | null; + bestFriendDateRange2: Array; + bestFriendDateRange3?: Array | null; + bestFriendDateRange4: Array; + }; + + export type UsersQueryVariables = Exact<{ + input?: UserInput | null; + dateTime1?: Date | null; + dateTime2: Date; + dateTimeArray1?: Array | Date | null; + dateTimeArray2: Array | Date; + dateTimeArray3?: Array | Date | null; + dateTimeArray4: Array | Date; + }>; + + + export type UsersQuery = { user: { __typename: 'User' } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); }); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts index a4ce0116403..45f5fc3f578 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -163,8 +163,8 @@ describe('TypeScript Operations Plugin - Standalone', () => { export type UsersWithScalarInputQueryVariables = Exact<{ from: unknown; - to?: unknown | null; - role?: UserRole | null; + to?: unknown | null | undefined; + role?: UserRole | null | undefined; }>; diff --git a/packages/presets/client/tests/client-preset.enum.spec.ts b/packages/presets/client/tests/client-preset.enum.spec.ts index 3e55808d024..8ea0aa1a047 100644 --- a/packages/presets/client/tests/client-preset.enum.spec.ts +++ b/packages/presets/client/tests/client-preset.enum.spec.ts @@ -77,7 +77,7 @@ describe('client-preset - Enum', () => { | 'SQUARE'; export type ShapeQueryVariables = Exact<{ - shape?: Shape | null; + shape?: Shape | null | undefined; }>; @@ -198,7 +198,7 @@ describe('client-preset - Enum', () => { export type Shape = typeof Shape[keyof typeof Shape]; export type ShapeQueryVariables = Exact<{ - shape?: Shape | null; + shape?: Shape | null | undefined; }>; From 859833a4290fba2704b6786f42823d81bd22c70d Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Sun, 18 Jan 2026 22:26:46 +1100 Subject: [PATCH 29/69] [typescript-operations] Handle printing "Maybe" types consistently when types are `any` and `unknown` (#10574) * Use printTypeScriptType to handle printing typescript types consistently, especially for any and unknown * Update tests * Add changeset * Make printTypeScriptMaybeType scope smaller * Update tests --- .changeset/free-fans-dance.md | 6 ++++ dev-test/gql-tag-operations/gql/graphql.ts | 4 +-- .../gql-tag-operations/graphql/graphql.ts | 4 +-- .../other/visitor-plugin-common/src/utils.ts | 22 +++++++++++++++ .../src/ts-operation-variables-to-object.ts | 11 ++++---- .../typescript/operations/src/visitor.ts | 21 +++++++++----- .../__snapshots__/ts-documents.spec.ts.snap | 18 ++++++------ .../operations/tests/ts-documents.spec.ts | 2 +- ...ts.standalone.default-scalar-types.spec.ts | 28 +++++++++---------- ...-documents.standalone.import-types.spec.ts | 12 ++++---- .../ts-documents.standalone.input.spec.ts | 4 +-- .../tests/ts-documents.standalone.spec.ts | 10 +++---- 12 files changed, 87 insertions(+), 55 deletions(-) create mode 100644 .changeset/free-fans-dance.md diff --git a/.changeset/free-fans-dance.md b/.changeset/free-fans-dance.md new file mode 100644 index 00000000000..0dbbfd76c20 --- /dev/null +++ b/.changeset/free-fans-dance.md @@ -0,0 +1,6 @@ +--- +'@graphql-codegen/visitor-plugin-common': patch +'@graphql-codegen/typescript-operations': patch +--- + +Add `printTypeScriptMaybeType` to handle printing TS types, as there are special cases like `any` and `unknown` diff --git a/dev-test/gql-tag-operations/gql/graphql.ts b/dev-test/gql-tag-operations/gql/graphql.ts index c8d4e3a8d5c..700a96ddbee 100644 --- a/dev-test/gql-tag-operations/gql/graphql.ts +++ b/dev-test/gql-tag-operations/gql/graphql.ts @@ -9,9 +9,7 @@ export type FooQueryVariables = Exact<{ [key: string]: never }>; export type FooQuery = { Tweets: Array<{ id: string } | null> | null }; -export type LelFragment = { id: string; body: string | null; date: unknown | null } & { - ' $fragmentName'?: 'LelFragment'; -}; +export type LelFragment = { id: string; body: string | null; date: unknown } & { ' $fragmentName'?: 'LelFragment' }; export type BarQueryVariables = Exact<{ [key: string]: never }>; diff --git a/dev-test/gql-tag-operations/graphql/graphql.ts b/dev-test/gql-tag-operations/graphql/graphql.ts index c8d4e3a8d5c..700a96ddbee 100644 --- a/dev-test/gql-tag-operations/graphql/graphql.ts +++ b/dev-test/gql-tag-operations/graphql/graphql.ts @@ -9,9 +9,7 @@ export type FooQueryVariables = Exact<{ [key: string]: never }>; export type FooQuery = { Tweets: Array<{ id: string } | null> | null }; -export type LelFragment = { id: string; body: string | null; date: unknown | null } & { - ' $fragmentName'?: 'LelFragment'; -}; +export type LelFragment = { id: string; body: string | null; date: unknown } & { ' $fragmentName'?: 'LelFragment' }; export type BarQueryVariables = Exact<{ [key: string]: never }>; diff --git a/packages/plugins/other/visitor-plugin-common/src/utils.ts b/packages/plugins/other/visitor-plugin-common/src/utils.ts index 0e8617b7680..32654d4f48e 100644 --- a/packages/plugins/other/visitor-plugin-common/src/utils.ts +++ b/packages/plugins/other/visitor-plugin-common/src/utils.ts @@ -741,3 +741,25 @@ const getDeprecationReason = (directive: DirectiveNode): string | void => { return reason; } }; + +/** + * @description Utility function to print a TypeScript type that is `Maybe`. + * We need this since some TypeScript types have special handling. + * e.g. `unknown | null | undefined` is treated as `unknown` + * + * Note: we currently have two types of handling nullable: `Maybe` or `T | null | undefined` + * This function only handles the latter case at the moment, but could be extended if needed. + * + * @param {Object} params + * @param {string} params.type - The TypeScript type e.g. `any`, `unknown`, `string`, `Something` + * @param {string} params.pattern - The pattern of the Maybe type. This is usually `T | null | undefined` or `T | null` + * @returns {string} The TypeScript type as string + */ +export const printTypeScriptMaybeType = ({ type, pattern }: { type: string; pattern: string }): string => { + if (type === 'any' || type === 'unknown') { + return type; + } + + const nullableSuffix = pattern.replace('T', ''); + return type.endsWith(nullableSuffix) ? type : `${type}${nullableSuffix}`; +}; diff --git a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts index 8bad09fb74e..8d469c69cca 100644 --- a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts +++ b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts @@ -5,6 +5,7 @@ import { NormalizedScalarsMap, OperationVariablesToObject, ParsedEnumValuesMap, + printTypeScriptMaybeType, } from '@graphql-codegen/visitor-plugin-common'; export const SCALARS = { @@ -21,7 +22,6 @@ export class TypeScriptOperationVariablesToObject extends OperationVariablesToOb avoidOptionals: NormalizedAvoidOptionalsConfig; immutableTypes: boolean; inputMaybeValue: string; - inputMaybeValueSuffix: string; }, _scalars: NormalizedScalarsMap, _convertName: ConvertNameFn, @@ -62,7 +62,7 @@ export class TypeScriptOperationVariablesToObject extends OperationVariablesToOb } protected clearOptional(str: string): string { - const maybeSuffix = this._config.inputMaybeValueSuffix; + const maybeSuffix = this._config.inputMaybeValue.replace('T', ''); // e.g. turns `T | null | undefined` to ` | null | undefined` if (str.endsWith(maybeSuffix)) { return (str = str.substring(0, str.length - maybeSuffix.length)); @@ -109,8 +109,9 @@ export class TypeScriptOperationVariablesToObject extends OperationVariablesToOb } protected wrapMaybe(type: string): string { - const maybeSuffix = this._config.inputMaybeValueSuffix; - - return type.endsWith(maybeSuffix) ? type : `${type}${maybeSuffix}`; + return printTypeScriptMaybeType({ + type, + pattern: this._config.inputMaybeValue, + }); } } diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 706a54e7811..7f3a3629b42 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -39,6 +39,7 @@ import { ParsedDocumentsConfig, parseEnumValues, PreResolveTypesProcessor, + printTypeScriptMaybeType, SelectionSetProcessorConfig, SelectionSetToObject, wrapTypeWithModifiers, @@ -79,7 +80,6 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< protected _usedNamedInputTypes: UsedNamedInputTypes = {}; protected _needsExactUtilityType: boolean = false; private _outputPath: string; - private _inputMaybeValueSuffix: string; constructor( schema: GraphQLSchema, @@ -141,7 +141,11 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< }, wrapTypeWithModifiers: (baseType, type) => { return wrapTypeWithModifiers(baseType, type, { - wrapOptional: type => this.config.maybeValue.replace('T', type), + wrapOptional: type => + printTypeScriptMaybeType({ + type, + pattern: this.config.maybeValue, + }), wrapArray: type => { const listModifier = this.config.immutableTypes ? 'ReadonlyArray' : 'Array'; return `${listModifier}<${type}>`; @@ -163,8 +167,6 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< ), ); - this._inputMaybeValueSuffix = this.config.inputMaybeValue.replace('T', ''); // e.g. turns `T | null | undefined` to ` | null | undefined` - const enumsNames = Object.keys(schema.getTypeMap()).filter(typeName => isEnumType(schema.getType(typeName)), ); @@ -177,7 +179,6 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< avoidOptionals: this.config.avoidOptionals, immutableTypes: this.config.immutableTypes, inputMaybeValue: this.config.inputMaybeValue, - inputMaybeValueSuffix: this._inputMaybeValueSuffix, }, this.scalars, this.convertName.bind(this), @@ -284,7 +285,10 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< typePart = usedInputType.tsType; // If the schema is correct, when reversing typeNodes, the first node would be `NamedType`, which means we can safely set it as the base for typePart if (!typeNode.isNonNullable) { - typePart += this._inputMaybeValueSuffix; + typePart = printTypeScriptMaybeType({ + type: typePart, + pattern: this.config.inputMaybeValue, + }); } continue; } @@ -292,7 +296,10 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< if (typeNode.type === 'ListType') { typePart = `Array<${typePart}>`; if (!typeNode.isNonNullable) { - typePart += this._inputMaybeValueSuffix; + typePart = printTypeScriptMaybeType({ + type: typePart, + pattern: this.config.inputMaybeValue, + }); } } } diff --git a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap index e77992ab326..0832c48df20 100644 --- a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap +++ b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap @@ -155,9 +155,9 @@ export type AaaQuery = { user: `; exports[`TypeScript Operations Plugin > Selection Set > Should have valid __typename usage and split types according to that (with usage) 1`] = ` -"type NetRoute_Ipv4Route_Fragment = { __typename: 'IPV4Route', ipv4Address: unknown | null, ipv4Gateway: unknown | null }; +"type NetRoute_Ipv4Route_Fragment = { __typename: 'IPV4Route', ipv4Address: unknown, ipv4Gateway: unknown }; -type NetRoute_Ipv6Route_Fragment = { __typename: 'IPV6Route', ipv6Address: unknown | null, ipv6Gateway: unknown | null }; +type NetRoute_Ipv6Route_Fragment = { __typename: 'IPV6Route', ipv6Address: unknown, ipv6Gateway: unknown }; export type NetRouteFragment = | NetRoute_Ipv4Route_Fragment @@ -168,30 +168,30 @@ export type QqQueryVariables = Exact<{ [key: string]: never; }>; export type QqQuery = { routes: Array< - | { __typename: 'IPV4Route', ipv4Address: unknown | null, ipv4Gateway: unknown | null } - | { __typename: 'IPV6Route', ipv6Address: unknown | null, ipv6Gateway: unknown | null } + | { __typename: 'IPV4Route', ipv4Address: unknown, ipv4Gateway: unknown } + | { __typename: 'IPV6Route', ipv6Address: unknown, ipv6Gateway: unknown } > }; " `; exports[`TypeScript Operations Plugin > Selection Set > Should have valid __typename usage and split types according to that (with usage) 2`] = ` -"type NetRoute_Ipv4Route_Fragment = { __typename: 'IPV4Route', ipv4Address: unknown | null, ipv4Gateway: unknown | null }; +"type NetRoute_Ipv4Route_Fragment = { __typename: 'IPV4Route', ipv4Address: unknown, ipv4Gateway: unknown }; -type NetRoute_Ipv6Route_Fragment = { __typename: 'IPV6Route', ipv6Address: unknown | null, ipv6Gateway: unknown | null }; +type NetRoute_Ipv6Route_Fragment = { __typename: 'IPV6Route', ipv6Address: unknown, ipv6Gateway: unknown }; export type NetRouteFragment = | NetRoute_Ipv4Route_Fragment | NetRoute_Ipv6Route_Fragment ; -export type TestFragment = { ipv6Address: unknown | null, ipv6Gateway: unknown | null }; +export type TestFragment = { ipv6Address: unknown, ipv6Gateway: unknown }; export type QqQueryVariables = Exact<{ [key: string]: never; }>; export type QqQuery = { routes: Array< - | { __typename: 'IPV4Route', ipv4Address: unknown | null, ipv4Gateway: unknown | null } - | { __typename: 'IPV6Route', ipv6Address: unknown | null, ipv6Gateway: unknown | null } + | { __typename: 'IPV4Route', ipv4Address: unknown, ipv4Gateway: unknown } + | { __typename: 'IPV6Route', ipv6Address: unknown, ipv6Gateway: unknown } > }; " `; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts index 8dd5618a78a..88823a7db49 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts @@ -2904,7 +2904,7 @@ export type Q2Query = { search: Array< expect(content).toMatchInlineSnapshot( ` "export type TestQueryQueryVariables = Exact<{ - test?: unknown | null | undefined; + test?: unknown; }>; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts index ecb60c75d73..cbfb79d8f0e 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts @@ -70,25 +70,25 @@ describe('TypeScript Operations Plugin - Default Scalar types', () => { export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type UserInput = { nonNullableDate: unknown; - nullableDate?: unknown | null | undefined; - dateArray1?: Array | null | undefined; - dateArray2: Array; + nullableDate?: unknown; + dateArray1?: Array | null | undefined; + dateArray2: Array; dateArray3?: Array | null | undefined; dateArray4: Array; }; export type UserQueryVariables = Exact<{ nonNullableDate: unknown; - nullableDate?: unknown | null | undefined; - dateArray1?: Array | unknown | null | undefined; - dateArray2: Array | unknown; + nullableDate?: unknown; + dateArray1?: Array | unknown | null | undefined; + dateArray2: Array | unknown; dateArray3?: Array | unknown | null | undefined; dateArray4: Array | unknown; input: UserInput; }>; - export type UserQuery = { user: { id: string, nonNullableDate: unknown, nullableDate: unknown | null } | null }; + export type UserQuery = { user: { id: string, nonNullableDate: unknown, nullableDate: unknown } | null }; " `); @@ -163,25 +163,25 @@ describe('TypeScript Operations Plugin - Default Scalar types', () => { export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type UserInput = { nonNullableDate: any; - nullableDate?: any | null | undefined; - dateArray1?: Array | null | undefined; - dateArray2: Array; + nullableDate?: any; + dateArray1?: Array | null | undefined; + dateArray2: Array; dateArray3?: Array | null | undefined; dateArray4: Array; }; export type UserQueryVariables = Exact<{ nonNullableDate: any; - nullableDate?: any | null | undefined; - dateArray1?: Array | any | null | undefined; - dateArray2: Array | any; + nullableDate?: any; + dateArray1?: Array | any | null | undefined; + dateArray2: Array | any; dateArray3?: Array | any | null | undefined; dateArray4: Array | any; input: UserInput; }>; - export type UserQuery = { user: { id: string, nonNullableDate: any, nullableDate: any | null } | null }; + export type UserQuery = { user: { id: string, nonNullableDate: any, nullableDate: any } | null }; " `); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts index 7f09e1440d0..a75ebd0f397 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts @@ -110,9 +110,9 @@ describe('TypeScript Operations Plugin - Import Types', () => { /** UsersInput Description */ type UsersInput = { /** UsersInput from */ - from?: unknown | null | undefined; + from?: unknown; /** UsersInput to */ - to?: unknown | null | undefined; + to?: unknown; role?: UserRole | null | undefined; }; @@ -135,7 +135,7 @@ describe('TypeScript Operations Plugin - Import Types', () => { export type UsersWithScalarInputQueryVariables = Exact<{ from: unknown; - to?: unknown | null | undefined; + to?: unknown; role?: TypeImport.UserRole | null | undefined; }>; @@ -254,9 +254,9 @@ describe('TypeScript Operations Plugin - Import Types', () => { /** UsersInput Description */ type UsersInput = { /** UsersInput from */ - from?: unknown | null | undefined; + from?: unknown; /** UsersInput to */ - to?: unknown | null | undefined; + to?: unknown; role?: UserRole | null | undefined; }; @@ -279,7 +279,7 @@ describe('TypeScript Operations Plugin - Import Types', () => { export type UsersWithScalarInputQueryVariables = Exact<{ from: unknown; - to?: unknown | null | undefined; + to?: unknown; role?: TypeImport.UserRole | null | undefined; }>; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts index a67c55b8f09..a6cc40fd9e2 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts @@ -102,7 +102,7 @@ describe('TypeScript Operations Plugin - Input', () => { from?: Date | null | undefined; /** UsersInput to */ to?: Date | null | undefined; - timezone?: unknown | null | undefined; + timezone?: unknown; role?: UserRole | null | undefined; ageRange1?: Array | null | undefined; ageRange2: Array; @@ -219,7 +219,7 @@ describe('TypeScript Operations Plugin - Input', () => { readonly from?: Date | null | undefined; /** UsersInput to */ readonly to?: Date | null | undefined; - readonly timezone?: unknown | null | undefined; + readonly timezone?: unknown; readonly role?: UserRole | null | undefined; readonly ageRange1?: Array | null | undefined; readonly ageRange2: Array; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts index 45f5fc3f578..f048786fee7 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -138,9 +138,9 @@ describe('TypeScript Operations Plugin - Standalone', () => { /** UsersInput Description */ type UsersInput = { /** UsersInput from */ - from?: unknown | null | undefined; + from?: unknown; /** UsersInput to */ - to?: unknown | null | undefined; + to?: unknown; role?: UserRole | null | undefined; }; @@ -163,7 +163,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { export type UsersWithScalarInputQueryVariables = Exact<{ from: unknown; - to?: unknown | null | undefined; + to?: unknown; role?: UserRole | null | undefined; }>; @@ -654,9 +654,9 @@ describe('TypeScript Operations Plugin - Standalone', () => { /** UsersInput Description */ type UsersInput = { /** UsersInput from */ - from?: unknown | null | undefined; + from?: unknown; /** UsersInput to */ - to?: unknown | null | undefined; + to?: unknown; role?: UserRole | null | undefined; }; " From cbbbc23a7804a50ad9b84342333a86ac05f6fdf1 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Sun, 18 Jan 2026 23:39:30 +1100 Subject: [PATCH 30/69] [typescript-operations] Fix Input generation when using `importSchemaTypesFrom` (#10575) * Fix importing issue when using importSchemaTypesFrom * Add dev-tests for usage with typescript plugin * Update unit test * Add changeset --- .changeset/twenty-buckets-brush.md | 5 ++ dev-test/codegen.ts | 17 ++++++- .../import-schema-types/_base.generated.ts | 6 +++ .../import-schema-types/_types.generated.ts | 6 +++ .../import-schema-types/query.graphql | 6 +++ dev-test/standalone-operations/schema.graphql | 12 +++++ .../with-typescript-plugin/_base.generated.ts | 51 +++++++++++++++++++ .../_types.generated.ts | 15 ++++++ .../with-typescript-plugin/query.graphql | 12 +++++ .../typescript/operations/src/visitor.ts | 20 ++++++-- .../operations/tests/ts-documents.spec.ts | 4 +- ...ts.standalone.default-scalar-types.spec.ts | 6 +-- ...-documents.standalone.import-types.spec.ts | 18 ------- .../ts-documents.standalone.input.spec.ts | 16 +++--- .../tests/ts-documents.standalone.spec.ts | 8 +-- 15 files changed, 162 insertions(+), 40 deletions(-) create mode 100644 .changeset/twenty-buckets-brush.md create mode 100644 dev-test/standalone-operations/with-typescript-plugin/_base.generated.ts create mode 100644 dev-test/standalone-operations/with-typescript-plugin/_types.generated.ts create mode 100644 dev-test/standalone-operations/with-typescript-plugin/query.graphql diff --git a/.changeset/twenty-buckets-brush.md b/.changeset/twenty-buckets-brush.md new file mode 100644 index 00000000000..92cda5aef3d --- /dev/null +++ b/.changeset/twenty-buckets-brush.md @@ -0,0 +1,5 @@ +--- +'@graphql-codegen/typescript-operations': patch +--- + +Fix importing issue of Input when importSchemaTypesFrom is used diff --git a/dev-test/codegen.ts b/dev-test/codegen.ts index 604deca956e..c6525522c64 100644 --- a/dev-test/codegen.ts +++ b/dev-test/codegen.ts @@ -273,7 +273,7 @@ const config: CodegenConfig = { }, // #endregion - // standalone-operations + // standalone-operations/import-schema-types './dev-test/standalone-operations/import-schema-types/_base.generated.ts': { schema: './dev-test/standalone-operations/schema.graphql', documents: ['./dev-test/standalone-operations/import-schema-types/*.graphql'], @@ -292,6 +292,21 @@ const config: CodegenConfig = { namespacedImportName: 'Types', }, }, + + // standalone-operations/with-typescript-plugin + './dev-test/standalone-operations/with-typescript-plugin/_base.generated.ts': { + schema: './dev-test/standalone-operations/schema.graphql', + plugins: ['typescript'], + }, + './dev-test/standalone-operations/with-typescript-plugin/_types.generated.ts': { + schema: './dev-test/standalone-operations/schema.graphql', + documents: ['./dev-test/standalone-operations/with-typescript-plugin/*.graphql'], + plugins: ['typescript-operations'], + config: { + importSchemaTypesFrom: './dev-test/standalone-operations/with-typescript-plugin/_base.generated.ts', + namespacedImportName: 'Types', + }, + }, }, }; diff --git a/dev-test/standalone-operations/import-schema-types/_base.generated.ts b/dev-test/standalone-operations/import-schema-types/_base.generated.ts index 8df53ac5f67..f0dd411ab38 100644 --- a/dev-test/standalone-operations/import-schema-types/_base.generated.ts +++ b/dev-test/standalone-operations/import-schema-types/_base.generated.ts @@ -4,3 +4,9 @@ export type UserRole = | 'ADMIN' /** UserRole CUSTOMER */ | 'CUSTOMER'; + +export type UsersInput = { + name?: string | null | undefined; + nestedInput?: UsersInput | null | undefined; + role?: UserRole | null | undefined; +}; diff --git a/dev-test/standalone-operations/import-schema-types/_types.generated.ts b/dev-test/standalone-operations/import-schema-types/_types.generated.ts index e45c3e222b3..954a5cffd3b 100644 --- a/dev-test/standalone-operations/import-schema-types/_types.generated.ts +++ b/dev-test/standalone-operations/import-schema-types/_types.generated.ts @@ -9,3 +9,9 @@ export type WithVariablesQueryVariables = Exact<{ }>; export type WithVariablesQuery = { user: { id: string; name: string } | null }; + +export type UsersQueryVariables = Exact<{ + input: Types.UsersInput; +}>; + +export type UsersQuery = { users: Array<{ id: string }> }; diff --git a/dev-test/standalone-operations/import-schema-types/query.graphql b/dev-test/standalone-operations/import-schema-types/query.graphql index e8de0b4506d..ddf5351bc36 100644 --- a/dev-test/standalone-operations/import-schema-types/query.graphql +++ b/dev-test/standalone-operations/import-schema-types/query.graphql @@ -4,3 +4,9 @@ query WithVariables($role: UserRole) { name } } + +query Users($input: UsersInput!) { + users(input: $input) { + id + } +} diff --git a/dev-test/standalone-operations/schema.graphql b/dev-test/standalone-operations/schema.graphql index 2fd2cb04bc6..0f7ac081d36 100644 --- a/dev-test/standalone-operations/schema.graphql +++ b/dev-test/standalone-operations/schema.graphql @@ -1,5 +1,6 @@ type Query { user(id: ID!, role: UserRole): User + users(input: UsersInput!): [User!]! } type User { @@ -15,3 +16,14 @@ enum UserRole { "UserRole CUSTOMER" CUSTOMER } + +enum UserStatus { + ACTIVE + INACTIVE +} + +input UsersInput { + name: String + role: UserRole + nestedInput: UsersInput +} diff --git a/dev-test/standalone-operations/with-typescript-plugin/_base.generated.ts b/dev-test/standalone-operations/with-typescript-plugin/_base.generated.ts new file mode 100644 index 00000000000..30664af7c84 --- /dev/null +++ b/dev-test/standalone-operations/with-typescript-plugin/_base.generated.ts @@ -0,0 +1,51 @@ +export type Maybe = T | null; +export type InputMaybe = Maybe; +/** All built-in and custom scalars, mapped to their actual values */ +export type Scalars = { + ID: { input: string; output: string }; + String: { input: string; output: string }; + Boolean: { input: boolean; output: boolean }; + Int: { input: number; output: number }; + Float: { input: number; output: number }; +}; + +export type Query = { + __typename?: 'Query'; + user?: Maybe; + users: Array; +}; + +export type QueryUserArgs = { + id: Scalars['ID']['input']; + role?: InputMaybe; +}; + +export type QueryUsersArgs = { + input: UsersInput; +}; + +export type User = { + __typename?: 'User'; + id: Scalars['ID']['output']; + name: Scalars['String']['output']; + role: UserRole; +}; + +/** UserRole Description */ +export enum UserRole { + /** UserRole ADMIN */ + Admin = 'ADMIN', + /** UserRole CUSTOMER */ + Customer = 'CUSTOMER', +} + +export enum UserStatus { + Active = 'ACTIVE', + Inactive = 'INACTIVE', +} + +export type UsersInput = { + name?: InputMaybe; + nestedInput?: InputMaybe; + role?: InputMaybe; +}; diff --git a/dev-test/standalone-operations/with-typescript-plugin/_types.generated.ts b/dev-test/standalone-operations/with-typescript-plugin/_types.generated.ts new file mode 100644 index 00000000000..6a222027557 --- /dev/null +++ b/dev-test/standalone-operations/with-typescript-plugin/_types.generated.ts @@ -0,0 +1,15 @@ +import type * as Types from './_base.generated.js'; + +type Exact = { [K in keyof T]: T[K] }; +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +export type WithVariablesQueryVariables = Exact<{ + role?: Types.UserRole | null | undefined; +}>; + +export type WithVariablesQuery = { user: { id: string; name: string } | null }; + +export type UsersQueryVariables = Exact<{ + input: Types.UsersInput; +}>; + +export type UsersQuery = { users: Array<{ id: string }> }; diff --git a/dev-test/standalone-operations/with-typescript-plugin/query.graphql b/dev-test/standalone-operations/with-typescript-plugin/query.graphql new file mode 100644 index 00000000000..ddf5351bc36 --- /dev/null +++ b/dev-test/standalone-operations/with-typescript-plugin/query.graphql @@ -0,0 +1,12 @@ +query WithVariables($role: UserRole) { + user(id: "100") { + id + name + } +} + +query Users($input: UsersInput!) { + users(input: $input) { + id + } +} diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 7f3a3629b42..59b617ec080 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -198,8 +198,11 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< EnumTypeDefinition(node: EnumTypeDefinitionNode): string | null { const enumName = node.name.value; - if (!this._usedNamedInputTypes[enumName] || this.config.importSchemaTypesFrom) { - return null; + if ( + !this._usedNamedInputTypes[enumName] || // If not used... + this.config.importSchemaTypesFrom // ... Or, is imported from a shared file + ) { + return null; // ... then, don't generate in this file } return convertSchemaEnumToDeclarationBlockString({ @@ -223,12 +226,20 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< InputObjectTypeDefinition(node: InputObjectTypeDefinitionNode): string | null { const inputTypeName = node.name.value; - if (!this._usedNamedInputTypes[inputTypeName]) { - return null; + if ( + !this._usedNamedInputTypes[inputTypeName] || // If not used... + this.config.importSchemaTypesFrom // ... Or, is imported from a shared file + ) { + return null; // ... then, don't generate in this file } + // Note: we usually don't need to export this type, + // however, it's not possible to know if another file is using this type e.g. using `importSchemaTypesFrom`, + // so it's better export the types. + if (isOneOfInputObjectType(this._schema.getType(inputTypeName))) { return new DeclarationBlock(this._declarationBlockConfig) + .export() .asKind('type') .withName(this.convertName(node)) .withComment(node.description?.value) @@ -236,6 +247,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< } return new DeclarationBlock(this._declarationBlockConfig) + .export() .asKind('type') .withName(this.convertName(node)) .withComment(node.description?.value) diff --git a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts index 88823a7db49..9857dc6c37f 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts @@ -2864,7 +2864,7 @@ export type Q2Query = { search: Array< expect(content).toMatchInlineSnapshot( ` - "type InputType = { + "export type InputType = { t?: string | null | undefined; }; @@ -3139,7 +3139,7 @@ export type Q2Query = { search: Array< | 'Write' | 'All'; - type PREFIX_Filter = { + export type PREFIX_Filter = { match: string; }; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts index cbfb79d8f0e..057605180e6 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts @@ -68,7 +68,7 @@ describe('TypeScript Operations Plugin - Default Scalar types', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - type UserInput = { + export type UserInput = { nonNullableDate: unknown; nullableDate?: unknown; dateArray1?: Array | null | undefined; @@ -161,7 +161,7 @@ describe('TypeScript Operations Plugin - Default Scalar types', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - type UserInput = { + export type UserInput = { nonNullableDate: any; nullableDate?: any; dateArray1?: Array | null | undefined; @@ -254,7 +254,7 @@ describe('TypeScript Operations Plugin - Default Scalar types', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - type UserInput = { + export type UserInput = { nonNullableDate: Date; nullableDate?: Date | null | undefined; dateArray1?: Array | null | undefined; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts index a75ebd0f397..20a634d0820 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts @@ -107,15 +107,6 @@ describe('TypeScript Operations Plugin - Import Types', () => { type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - /** UsersInput Description */ - type UsersInput = { - /** UsersInput from */ - from?: unknown; - /** UsersInput to */ - to?: unknown; - role?: UserRole | null | undefined; - }; - export type UserQueryVariables = Exact<{ id: string; }>; @@ -251,15 +242,6 @@ describe('TypeScript Operations Plugin - Import Types', () => { type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - /** UsersInput Description */ - type UsersInput = { - /** UsersInput from */ - from?: unknown; - /** UsersInput to */ - to?: unknown; - role?: UserRole | null | undefined; - }; - export type UserQueryVariables = Exact<{ id: string; }>; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts index a6cc40fd9e2..c77972b6537 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts @@ -97,7 +97,7 @@ describe('TypeScript Operations Plugin - Input', () => { | 'CUSTOMER'; /** UsersInput Description */ - type UsersInput = { + export type UsersInput = { /** UsersInput from */ from?: Date | null | undefined; /** UsersInput to */ @@ -112,7 +112,7 @@ describe('TypeScript Operations Plugin - Input', () => { nestedInput?: UsersInput | null | undefined; }; - type UsersBestFriendInput = { + export type UsersBestFriendInput = { name?: string | null | undefined; }; @@ -214,7 +214,7 @@ describe('TypeScript Operations Plugin - Input', () => { | 'CUSTOMER'; /** UsersInput Description */ - type UsersInput = { + export type UsersInput = { /** UsersInput from */ readonly from?: Date | null | undefined; /** UsersInput to */ @@ -229,7 +229,7 @@ describe('TypeScript Operations Plugin - Input', () => { readonly nestedInput?: UsersInput | null | undefined; }; - type UsersBestFriendInput = { + export type UsersBestFriendInput = { readonly name?: string | null | undefined; }; @@ -323,7 +323,7 @@ describe('TypeScript Operations Plugin - Input', () => { | 'CUSTOMER'; /** UsersInput Description */ - type UsersInput = + export type UsersInput = { /** UsersInput from */ from: Date; to?: never; timezone?: never; role?: never; ageRange1?: never; ageRange3?: never; bestFriend?: never; nestedInput?: never; } | { from?: never; /** UsersInput to */ @@ -335,7 +335,7 @@ describe('TypeScript Operations Plugin - Input', () => { | { from?: never; to?: never; timezone?: never; role?: never; ageRange1?: never; ageRange3?: never; bestFriend: UsersBestFriendInput; nestedInput?: never; } | { from?: never; to?: never; timezone?: never; role?: never; ageRange1?: never; ageRange3?: never; bestFriend?: never; nestedInput: UsersInput; }; - type UsersBestFriendInput = { + export type UsersBestFriendInput = { name?: string | null | undefined; }; @@ -414,7 +414,7 @@ describe('TypeScript Operations Plugin - Input', () => { expect(result).toMatchInlineSnapshot(` "type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - type UserInput = { + export type UserInput = { dateRange1?: Array | null; dateRange2: Array; dateRange3?: Array | null; @@ -423,7 +423,7 @@ describe('TypeScript Operations Plugin - Input', () => { nestedInput?: UserInput | null; }; - type UserBestFriendInput = { + export type UserBestFriendInput = { name?: string | null; bestFriendDateRange1?: Array | null; bestFriendDateRange2: Array; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts index f048786fee7..86ade3e739a 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -136,7 +136,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { | 'CUSTOMER'; /** UsersInput Description */ - type UsersInput = { + export type UsersInput = { /** UsersInput from */ from?: unknown; /** UsersInput to */ @@ -251,11 +251,11 @@ describe('TypeScript Operations Plugin - Standalone', () => { | 'ENUM_E' | 'ENUM_F'; - type EnumsInner = { + export type EnumsInner = { enumsDeep: Array; }; - type UsersInput = { + export type UsersInput = { enum: EnumRoot; enums: Array; innerEnums: EnumsInner; @@ -652,7 +652,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { | 'CUSTOMER'; /** UsersInput Description */ - type UsersInput = { + export type UsersInput = { /** UsersInput from */ from?: unknown; /** UsersInput to */ From b43eb8b86c4979c889f585c3849695d66237f828 Mon Sep 17 00:00:00 2001 From: Igor Kusakov Date: Mon, 19 Jan 2026 06:21:01 -0500 Subject: [PATCH 31/69] Bugfix: enums from external fragments were not generated along with operations (#10565) * integration test * cleanups * cleanups2 * fixed a bug with external fragments * cleanup * keep generated files, refactored visitorwq * cleanup * changeset * adding missing dependency * delete temporary files * cleanup * cleanups * Adding back the integration tests + fix them * merged + fixes * cleanup * cleanup * patching near-operation-file preset * cleanup * adding duplicates case to integration tests * Fixing bug with duplicates generated when using extractAllFieldsToTypesCompact * cleanup * prevent running prettier on generated code * cleanups * cleanup * adding unit tests * update changeset * cleanups * try resolving graphql 16 error * remove unused deps * remove unused deps * cleanups * Revert and apply minimal yarn.lock changes --------- Co-authored-by: ikusakov Co-authored-by: Igor Kusakov Co-authored-by: Eddy Nguyen Co-authored-by: Eddy Nguyen --- .changeset/upset-bars-call.md | 6 + dev-test-apollo-tooling/README.md | 20 + dev-test-apollo-tooling/cli/index.ts | 91 ++++ dev-test-apollo-tooling/package.json | 30 ++ dev-test-apollo-tooling/schema.graphql | 338 ++++++++++++ dev-test-apollo-tooling/src/Component.ts | 26 + dev-test-apollo-tooling/src/Duplicates.ts | 82 +++ dev-test-apollo-tooling/src/Helper.ts | 27 + .../src/__generated__/Component.ts | 54 ++ .../src/__generated__/Duplicates.ts | 163 ++++++ .../src/__generated__/Helper.ts | 34 ++ .../tests/Component.test.ts | 20 + .../tests/Duplicates.test.ts | 31 ++ dev-test-apollo-tooling/tsconfig.json | 11 + dev-test-apollo-tooling/vitest.config.ts | 12 + package.json | 4 +- .../src/selection-set-to-object.ts | 45 +- .../typescript/operations/src/visitor.ts | 11 +- ...tract-all-types-compact-duplicates.spec.ts | 339 +++++++++++++ ...-documents.external-fragments-enum.spec.ts | 479 ++++++++++++++++++ yarn.lock | 312 +++++++++++- 21 files changed, 2104 insertions(+), 31 deletions(-) create mode 100644 .changeset/upset-bars-call.md create mode 100644 dev-test-apollo-tooling/README.md create mode 100644 dev-test-apollo-tooling/cli/index.ts create mode 100644 dev-test-apollo-tooling/package.json create mode 100644 dev-test-apollo-tooling/schema.graphql create mode 100644 dev-test-apollo-tooling/src/Component.ts create mode 100644 dev-test-apollo-tooling/src/Duplicates.ts create mode 100644 dev-test-apollo-tooling/src/Helper.ts create mode 100644 dev-test-apollo-tooling/src/__generated__/Component.ts create mode 100644 dev-test-apollo-tooling/src/__generated__/Duplicates.ts create mode 100644 dev-test-apollo-tooling/src/__generated__/Helper.ts create mode 100644 dev-test-apollo-tooling/tests/Component.test.ts create mode 100644 dev-test-apollo-tooling/tests/Duplicates.test.ts create mode 100644 dev-test-apollo-tooling/tsconfig.json create mode 100644 dev-test-apollo-tooling/vitest.config.ts create mode 100644 packages/plugins/typescript/operations/tests/extract-all-types-compact-duplicates.spec.ts create mode 100644 packages/plugins/typescript/operations/tests/ts-documents.external-fragments-enum.spec.ts diff --git a/.changeset/upset-bars-call.md b/.changeset/upset-bars-call.md new file mode 100644 index 00000000000..1b09fb593e8 --- /dev/null +++ b/.changeset/upset-bars-call.md @@ -0,0 +1,6 @@ +--- +'@graphql-codegen/typescript-operations': minor +'@graphql-codegen/visitor-plugin-common': minor +--- + +Fixing 2 bugs: 1) including enums from external fragments; 2) extractAllFieldsToTypesCompact does not create duplicates diff --git a/dev-test-apollo-tooling/README.md b/dev-test-apollo-tooling/README.md new file mode 100644 index 00000000000..69e815dce45 --- /dev/null +++ b/dev-test-apollo-tooling/README.md @@ -0,0 +1,20 @@ +The `dev-test-apollo-tooling` package is an example of migrating from Apollo tooling to GraphQL Codegen. It attempts to generate output as close as possible to Apollo tooling’s output. Note: **this package is a work in progress** and currently requires a patch to `near-operation-file`. We will fix this package soon. + +How to run this package: + +1. Make sure you have the correct Yarn version installed (check the root package.json, `packageManager` entry). Otherwise, you might run into unexplained bugs. +2. In the monorepo root, run: + +yarn clean && yarn install && yarn build + +3. Patch `near-operation-file` manually (the automatic patch doesn’t always work). In the monorepo root, run: + +yarn postinstall + +4. Go to the `dev-test-apollo-tooling` directory and run: + +cd dev-test-apollo-tooling +yarn install +yarn start + +This will generate type files in `dev-test-apollo-tooling/src/__generated__/*`. diff --git a/dev-test-apollo-tooling/cli/index.ts b/dev-test-apollo-tooling/cli/index.ts new file mode 100644 index 00000000000..72994ab2d47 --- /dev/null +++ b/dev-test-apollo-tooling/cli/index.ts @@ -0,0 +1,91 @@ +#!/usr/bin/env ts-node + +import { generate } from '@graphql-codegen/cli'; +import type { Types } from '@graphql-codegen/plugin-helpers'; + +export const GENERATED = '__generated__'; +export const GLOBAL_TYPES_FILE = 'globalTypes.ts'; +export const TS_GENERATED_FILE_HEADER = `\ +/* tslint:disable */ +/* eslint-disable */ +// @generated +// This file was automatically generated and should not be edited. +`; + +/** + * The following GraphQL Codegen config matches as closely as possible + * to the old apollo-tooling codegen + * @see https://github.com/apollographql/apollo-tooling/issues/2053 + * */ +const GRAPHQL_CODEGEN_CONFIG = { + useTypeImports: true, + namingConvention: 'keep', // Keeps naming as-is + avoidOptionals: false, // Allow '?' on variables fields + nonOptionalTypename: true, // Forces `__typename` on all selection sets + skipTypeNameForRoot: true, // Don't generate __typename for root types + omitOperationSuffix: true, // Don't add 'Query', 'Mutation' or 'Subscription' suffixes to operation result types + fragmentSuffix: '', // Don't add 'Fragment' suffix to fragment result types + extractAllFieldsToTypesCompact: true, // Extracts all fields to separate types (similar to apollo-codegen behavior) + printFieldsOnNewLines: true, // Prints each field on a new line (similar to apollo-codegen behavior) + importTypesNamespace: '', // Disable namespace prefix on imported types (preset config) + enumType: 'native', + generatesOperationTypes: true, +}; + +export const main = async () => { + const cwd = process.cwd(); + + const localSchemaFilePath = `${cwd}/schema.graphql`; + + const includes = ['src']; + + const generateFiles: { [scanPath: string]: Types.ConfiguredOutput } = {}; + + // Prepare the required structure for GraphQL Codegen + includes.forEach((include: string) => { + generateFiles[include] = { + preset: 'near-operation-file', // This preset tells the codegen to generate multiple files instead of one + presetConfig: { + extension: '.ts', // Matches the existing Apollo-Codegen file naming + // FIXME: The following config is required, but it is not needed with the recent version of typescript-operations. + // So - when the new version of near-operation-file' is available - fix this. + baseTypesPath: 'unused', + folder: GENERATED, // Output folder for generated files + importTypesNamespace: '', // Disable namespace prefix on imported types + }, + plugins: [ + 'typescript-operations', + { + add: { + content: TS_GENERATED_FILE_HEADER, + }, + }, + ], + }; + }); + + await generate( + { + schema: localSchemaFilePath, + documents: [ + // matching js extensins as well - there are cases where js files are not converted to typescript yet + // (but the package is typescript) + ...includes.map((include: any) => `${include}/**/*.{js,jsx,ts,tsx}`), + `!**/${GENERATED}/**`, + ], + config: GRAPHQL_CODEGEN_CONFIG, + generates: generateFiles, + silent: false, + debug: true, + verbose: true, + }, + true // overwrite existing files + ); +}; + +if (import.meta.url === process.argv[1] || import.meta.url === `file://${process.argv[1]}`) { + main().catch(e => { + console.error(e); + process.exit(1); + }); +} diff --git a/dev-test-apollo-tooling/package.json b/dev-test-apollo-tooling/package.json new file mode 100644 index 00000000000..164edd8d7cf --- /dev/null +++ b/dev-test-apollo-tooling/package.json @@ -0,0 +1,30 @@ +{ + "name": "dev-test-apollo-tooling", + "description": "A setup which mimics Apollo tooling generation as close as possible", + "version": "0.0.1", + "type": "module", + "dependencies": { + "@apollo/client": "3.13.8", + "@graphql-codegen/cli": "*", + "@graphql-codegen/plugin-helpers": "*", + "@graphql-codegen/typescript-operations": "*", + "@graphql-codegen/visitor-plugin-common": "*", + "@graphql-codegen/typed-document-node": "*" + }, + "devDependencies": { + "@types/node": "^25.0.3", + "tsx": "4.7.0", + "typescript": "^5.9.3", + "vitest": "4.0.4" + }, + "files": [ + "cli" + ], + "scripts": { + "start": "tsx cli/index.ts", + "start:debug": "NODE_OPTIONS='--trace-warnings' tsx cli/index.ts", + "start:verbose": "DEBUG='*' tsx cli/index.ts", + "test": "vitest --no-watch" + }, + "sideEffects": false +} diff --git a/dev-test-apollo-tooling/schema.graphql b/dev-test-apollo-tooling/schema.graphql new file mode 100644 index 00000000000..68909ce7a6e --- /dev/null +++ b/dev-test-apollo-tooling/schema.graphql @@ -0,0 +1,338 @@ +schema + @link(url: "https://specs.apollo.dev/link/v1.0") + @link(url: "https://specs.apollo.dev/join/v0.4", for: EXECUTION) + @link(url: "https://specs.apollo.dev/tag/v0.3") { + query: Query +} + +directive @join__graph(name: String!, url: String!) on ENUM_VALUE + +directive @join__enumValue(graph: join__Graph!) repeatable on ENUM_VALUE + +directive @join__field( + graph: join__Graph + requires: join__FieldSet + provides: join__FieldSet + type: String + external: Boolean + override: String + usedOverridden: Boolean + overrideLabel: String +) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION + +directive @join__implements(graph: join__Graph!, interface: String!) repeatable on OBJECT | INTERFACE + +directive @join__type( + graph: join__Graph! + key: join__FieldSet + extension: Boolean! = false + resolvable: Boolean! = true + isInterfaceObject: Boolean! = false +) repeatable on OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT | SCALAR + +directive @join__unionMember(graph: join__Graph!, member: String!) repeatable on UNION + +directive @link(url: String, as: String, for: link__Purpose, import: [link__Import]) repeatable on SCHEMA + +directive @tag( + name: String! +) repeatable on FIELD_DEFINITION | OBJECT | INTERFACE | UNION | ARGUMENT_DEFINITION | SCALAR | ENUM | ENUM_VALUE | INPUT_OBJECT | INPUT_FIELD_DEFINITION | SCHEMA + +scalar join__FieldSet + +scalar link__Import + +enum link__Purpose { + EXECUTION +} + +enum join__Graph { + SUPER_USER_MANAGER @join__graph(name: "super_user_management", url: "http://i.am.not.used.example.com") + GRAPHQL_MAIN__SHARD__BASE @join__graph(name: "graphql_main__shard__base", url: "http://i.am.not.used.example.com") + GRAPHQL_MAIN__SHARD__INTERNAL_TESTING + @join__graph(name: "graphql_main__shard__internal_testing", url: "http://i.am.not.used.example.com") +} + +type Query { + superUser: SuperUser! @join__field(graph: GRAPHQL_MAIN__SHARD__BASE) + organization(id: String!): Organization @join__field(graph: GRAPHQL_MAIN__SHARD__BASE) +} + +enum UserManagerRoleType @join__type(graph: SUPER_USER_MANAGER) { + ROLE_TYPE_1 @join__enumValue(graph: SUPER_USER_MANAGER) + + ROLE_TYPE_2 @join__enumValue(graph: SUPER_USER_MANAGER) + + ROLE_TYPE_3 @join__enumValue(graph: SUPER_USER_MANAGER) +} + +type UserManager @join__type(graph: SUPER_USER_MANAGER) { + fooUser: User! + + roleType: UserManagerRoleType! +} + +type User { + id: ID! + profilePhoto: UserProfilePhoto @join__field(graph: GRAPHQL_MAIN__SHARD__BASE) +} + +type AdminUser { + id: ID! + profilePhoto: UserProfilePhoto @join__field(graph: GRAPHQL_MAIN__SHARD__BASE) +} + +type UserProfilePhoto @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + id: ID! + photoUrl: UserPhotoUrl +} + +type UserPhotoUrl @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + url(size: UserPhotoSize!): String +} + +enum UserPhotoSize + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__type(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) { + SQUARE_300 + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) +} + +type SuperUser @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + groupFromAlias(alias: String!): SuperUserGroup! +} + +type SuperUserGroup + @join__type(graph: SUPER_USER_MANAGER, key: "id") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE, key: "id") { + id: ID! + + managers(onlyPublic: Boolean! = false): [UserManager!] @join__field(graph: SUPER_USER_MANAGER) +} + +# Schema definitions for Duplicates.ts examples + +interface ConfigTypeDefinition @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + identifier: String! +} + +type ConfigActionId implements ConfigTypeDefinition + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "ConfigTypeDefinition") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + identifier: String! +} + +type ConfigString implements ConfigTypeDefinition + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "ConfigTypeDefinition") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + identifier: String! + supportedHtmlTags: [String!] +} + +type ConfigEnum implements ConfigTypeDefinition + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "ConfigTypeDefinition") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + identifier: String! + values: [String!]! +} + +type ConfigIconResource implements ConfigTypeDefinition + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "ConfigTypeDefinition") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + identifier: String! + parameters: [ConfigParameterDefinition!]! +} + +type ConfigIllustrationResource implements ConfigTypeDefinition + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "ConfigTypeDefinition") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + identifier: String! + parameters: [ConfigParameterDefinition!]! +} + +type ConfigStruct implements ConfigTypeDefinition + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "ConfigTypeDefinition") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + identifier: String! + parameters: [ConfigParameterDefinition!]! +} + +type ConfigParameterDefinition @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + name: String! + typeId: String! + isRequired: Boolean! + defaultValue: String +} + +type Organization implements Node + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "Node") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE, key: "id") { + id: ID! + internalOrgData: InternalOrgData @join__field(graph: GRAPHQL_MAIN__SHARD__BASE) +} + +type InternalOrgData @join__type(graph: GRAPHQL_MAIN__SHARD__BASE, key: "id") { + id: ID! + processableFeedback( + first: Int + after: String + sortBy: ProcessableFeedbackSortBy + sortOrder: ProcessableFeedbackSortOrder + scoreFilter: [Int] + ): FeedbackConnection @join__field(graph: GRAPHQL_MAIN__SHARD__BASE) +} + +enum ProcessableFeedbackSortBy + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__type(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) { + OPTION_1 + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) + OPTION_2 + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) + OPTION_3 + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) + OPTION_4 + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) +} + +enum ProcessableFeedbackSortOrder + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__type(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) { + ASC @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) + DESC @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) +} + +type FeedbackConnection @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + edges: [FeedbackEdge] + pageInfo: PageInfo! + totalCount: Int +} + +type FeedbackEdge @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + cursor: String! + node: Feedback +} + +type Feedback implements Node + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "Node") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE, key: "id") { + id: ID! + orgMemberThread: Thread @join__field(graph: GRAPHQL_MAIN__SHARD__BASE) +} + +type Thread implements Node + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "Node") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + id: ID! + posts(after: String, first: Int): ThreadPostConnection @join__field(graph: GRAPHQL_MAIN__SHARD__BASE) +} + +type ThreadPostConnection @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + edges: [ThreadPostEdge] + pageInfo: PageInfo! +} + +type ThreadPostEdge @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + cursor: String! + node: ThreadPost +} + +type ThreadPost @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + id: ID! + creator: ThreadPostCreator + text: String + createdAt: DateTime +} + +union ThreadPostCreator + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__unionMember(graph: GRAPHQL_MAIN__SHARD__BASE, member: "OrgMember") + @join__unionMember(graph: GRAPHQL_MAIN__SHARD__BASE, member: "EndUser") = + OrgMember + | EndUser + +type OrgMember @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + id: ID! + fullName: String + avatar: OrgMemberAvatar +} + +type EndUser @join__type(graph: GRAPHQL_MAIN__SHARD__BASE, key: "id") { + id: ID! + fullName: String + avatar: EndUserAvatar +} + +type OrgMemberAvatar implements Photo & Node + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "Photo") + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "Node") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + id: ID! + imageUrl: OrgMemberImageUrl +} + +type OrgMemberImageUrl @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + url(size: OrgMemberImageSize!): String +} + +enum OrgMemberImageSize + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__type(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) { + LARGE + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) + MEDIUM + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) + SMALL + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) +} + +type EndUserAvatar implements Photo & Node + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "Photo") + @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "Node") + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + id: ID! + imageUrl: EndUserImageUrl +} + +type EndUserImageUrl @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { + url(size: EndUserImageSize!): String +} + +enum EndUserImageSize + @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__type(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) { + LARGE + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) + MEDIUM + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) + SMALL + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) +} + +interface Photo { + id: ID! +} + +interface Node { + id: ID! +} + +type PageInfo { + hasNextPage: Boolean! + hasPreviousPage: Boolean! + startCursor: String + endCursor: String +} + +scalar DateTime diff --git a/dev-test-apollo-tooling/src/Component.ts b/dev-test-apollo-tooling/src/Component.ts new file mode 100644 index 00000000000..251f14a354d --- /dev/null +++ b/dev-test-apollo-tooling/src/Component.ts @@ -0,0 +1,26 @@ +/** + * This file tests generating enum from external fragement from another file. + * Check that UserManagerRoleType enum is generated in __generated__/Component.ts + */ + +import { useQuery, gql } from '@apollo/client'; +import Helper from './Helper'; + +export const getFooQuery = gql` + ${Helper.fragments.query} + query GetFoo($alias: String!, $collectionId: String!) { + superUser { + groupFromAlias(alias: $alias) { + managers(onlyPublic: true) { + ...HelperFields + } + } + } + } +`; + +const Component = () => { + useQuery(getFooQuery, {}); +}; + +export default Component; diff --git a/dev-test-apollo-tooling/src/Duplicates.ts b/dev-test-apollo-tooling/src/Duplicates.ts new file mode 100644 index 00000000000..54a4397a0db --- /dev/null +++ b/dev-test-apollo-tooling/src/Duplicates.ts @@ -0,0 +1,82 @@ +/** + * This file tests handing duplicates when using extractAllFieldsToTypesCompact: true + * Check the resultring __generated__/Duplicates.ts file - it should not contain any duplicate names. + */ + +import { gql } from '@apollo/client'; + +export const getTypeDefinitionsFragment = gql` + fragment ConfigTypeDefinitions on ConfigTypeDefinition { + __typename + ... on ConfigActionId { + identifier + } + ... on ConfigString { + identifier + supportedHtmlTags + } + ... on ConfigEnum { + identifier + values + } + } +`; + +export const GET_FEEDBACK_DATA = gql` + query GetFeedbackData( + $organizationId: String! + $first: Int + $after: String + $scoreFilter: [Int] + $sortBy: ProcessableFeedbackSortBy + $sortOrder: ProcessableFeedbackSortOrder + ) { + organization(id: $organizationId) { + internalOrgData { + processableFeedback( + first: $first + after: $after + sortBy: $sortBy + sortOrder: $sortOrder + scoreFilter: $scoreFilter + ) { + edges { + node { + id + orgMemberThread { + id + posts(first: 1, after: "") { + edges { + node { + creator { + __typename + ... on OrgMember { + id + fullName + avatar { + imageUrl { + url(size: SMALL) + } + } + } + ... on EndUser { + id + fullName + avatar { + imageUrl { + url(size: SMALL) + } + } + } + } + } + } + } + } + } + } + } + } + } + } +`; diff --git a/dev-test-apollo-tooling/src/Helper.ts b/dev-test-apollo-tooling/src/Helper.ts new file mode 100644 index 00000000000..c562fc0eb0a --- /dev/null +++ b/dev-test-apollo-tooling/src/Helper.ts @@ -0,0 +1,27 @@ +import { gql } from '@apollo/client'; + +const getHelperFieldsFragment = gql` + fragment HelperFields on UserManager { + roleType + fooUser { + profilePhoto { + photoUrl { + url(size: SQUARE_300) + } + } + } + } +`; + +export const helperPropsFromFragment = (fragment: any) => ({ + profilePhotoUrl: fragment.fooUser.profilePhoto?.photoUrl.url, + roleType: fragment.roleType, +}); + +const Helper = { fragments: { query: {} } }; + +Helper.fragments = { + query: getHelperFieldsFragment, +}; + +export default Helper; diff --git a/dev-test-apollo-tooling/src/__generated__/Component.ts b/dev-test-apollo-tooling/src/__generated__/Component.ts new file mode 100644 index 00000000000..72d65a65725 --- /dev/null +++ b/dev-test-apollo-tooling/src/__generated__/Component.ts @@ -0,0 +1,54 @@ +/* tslint:disable */ +/* eslint-disable */ +// @generated +// This file was automatically generated and should not be edited. + +import type * as Types from '../unused'; + +type Exact = { [K in keyof T]: T[K] }; +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +export enum UserManagerRoleType { + ROLE_TYPE_1 = 'ROLE_TYPE_1', + ROLE_TYPE_2 = 'ROLE_TYPE_2', + ROLE_TYPE_3 = 'ROLE_TYPE_3', +} + +export type GetFoo_superUser_groupFromAlias_managers_fooUser_profilePhoto_photoUrl = { + __typename: 'UserPhotoUrl'; + url: string | null; +}; + +export type GetFoo_superUser_groupFromAlias_managers_fooUser_profilePhoto = { + __typename: 'UserProfilePhoto'; + photoUrl: GetFoo_superUser_groupFromAlias_managers_fooUser_profilePhoto_photoUrl | null; +}; + +export type GetFoo_superUser_groupFromAlias_managers_fooUser = { + __typename: 'User'; + profilePhoto: GetFoo_superUser_groupFromAlias_managers_fooUser_profilePhoto | null; +}; + +export type GetFoo_superUser_groupFromAlias_managers = { + __typename: 'UserManager'; + roleType: Types.UserManagerRoleType; + fooUser: GetFoo_superUser_groupFromAlias_managers_fooUser; +}; + +export type GetFoo_superUser_groupFromAlias = { + __typename: 'SuperUserGroup'; + managers: Array | null; +}; + +export type GetFoo_superUser = { + __typename: 'SuperUser'; + groupFromAlias: GetFoo_superUser_groupFromAlias; +}; + +export type GetFoo = { + superUser: GetFoo_superUser; +}; + +export type GetFooVariables = Exact<{ + alias: string; + collectionId: string; +}>; diff --git a/dev-test-apollo-tooling/src/__generated__/Duplicates.ts b/dev-test-apollo-tooling/src/__generated__/Duplicates.ts new file mode 100644 index 00000000000..48cecf574a6 --- /dev/null +++ b/dev-test-apollo-tooling/src/__generated__/Duplicates.ts @@ -0,0 +1,163 @@ +/* tslint:disable */ +/* eslint-disable */ +// @generated +// This file was automatically generated and should not be edited. + +import type * as Types from '../unused'; + +type Exact = { [K in keyof T]: T[K] }; +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +export enum ProcessableFeedbackSortBy { + OPTION_1 = 'OPTION_1', + OPTION_2 = 'OPTION_2', + OPTION_3 = 'OPTION_3', + OPTION_4 = 'OPTION_4', +} + +export enum ProcessableFeedbackSortOrder { + ASC = 'ASC', + DESC = 'DESC', +} + +export type ConfigTypeDefinitions_ConfigActionId = { + __typename: 'ConfigActionId'; + identifier: string; +}; + +export type ConfigTypeDefinitions_ConfigEnum = { + __typename: 'ConfigEnum'; + identifier: string; + values: Array; +}; + +export type ConfigTypeDefinitions_ConfigIconResource = { + __typename: 'ConfigIconResource'; +}; + +export type ConfigTypeDefinitions_ConfigIllustrationResource = { + __typename: 'ConfigIllustrationResource'; +}; + +export type ConfigTypeDefinitions_ConfigString = { + __typename: 'ConfigString'; + identifier: string; + supportedHtmlTags: Array | null; +}; + +export type ConfigTypeDefinitions_ConfigStruct = { + __typename: 'ConfigStruct'; +}; + +export type ConfigTypeDefinitions = + | ConfigTypeDefinitions_ConfigActionId + | ConfigTypeDefinitions_ConfigEnum + | ConfigTypeDefinitions_ConfigIconResource + | ConfigTypeDefinitions_ConfigIllustrationResource + | ConfigTypeDefinitions_ConfigString + | ConfigTypeDefinitions_ConfigStruct; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_avatar_imageUrl = + { + __typename: 'EndUserImageUrl'; + url: string | null; + }; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_avatar = + { + __typename: 'EndUserAvatar'; + imageUrl: GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_avatar_imageUrl | null; + }; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_OrgMember_avatar_imageUrl = + { + __typename: 'OrgMemberImageUrl'; + url: string | null; + }; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_OrgMember_avatar = + { + __typename: 'OrgMemberAvatar'; + imageUrl: GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_OrgMember_avatar_imageUrl | null; + }; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_EndUser = + { + __typename: 'EndUser'; + id: string; + fullName: string | null; + avatar: GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_avatar | null; + }; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_OrgMember = + { + __typename: 'OrgMember'; + id: string; + fullName: string | null; + avatar: GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_OrgMember_avatar | null; + }; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator = + + | GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_EndUser + | GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_OrgMember; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node = + { + __typename: 'ThreadPost'; + creator: GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator | null; + }; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges = { + __typename: 'ThreadPostEdge'; + node: GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node | null; +}; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts = { + __typename: 'ThreadPostConnection'; + edges: Array | null; +}; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread = { + __typename: 'Thread'; + id: string; + posts: GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts | null; +}; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node = { + __typename: 'Feedback'; + id: string; + orgMemberThread: GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread | null; +}; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges = { + __typename: 'FeedbackEdge'; + node: GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node | null; +}; + +export type GetFeedbackData_organization_internalOrgData_processableFeedback = { + __typename: 'FeedbackConnection'; + edges: Array | null; +}; + +export type GetFeedbackData_organization_internalOrgData = { + __typename: 'InternalOrgData'; + processableFeedback: GetFeedbackData_organization_internalOrgData_processableFeedback | null; +}; + +export type GetFeedbackData_organization = { + __typename: 'Organization'; + internalOrgData: GetFeedbackData_organization_internalOrgData | null; +}; + +export type GetFeedbackData = { + organization: GetFeedbackData_organization | null; +}; + +export type GetFeedbackDataVariables = Exact<{ + organizationId: string; + first?: number | null | undefined; + after?: string | null | undefined; + scoreFilter?: Array | number | null | undefined; + sortBy?: Types.ProcessableFeedbackSortBy | null | undefined; + sortOrder?: Types.ProcessableFeedbackSortOrder | null | undefined; +}>; diff --git a/dev-test-apollo-tooling/src/__generated__/Helper.ts b/dev-test-apollo-tooling/src/__generated__/Helper.ts new file mode 100644 index 00000000000..96087fb8869 --- /dev/null +++ b/dev-test-apollo-tooling/src/__generated__/Helper.ts @@ -0,0 +1,34 @@ +/* tslint:disable */ +/* eslint-disable */ +// @generated +// This file was automatically generated and should not be edited. + +import type * as Types from '../unused'; + +export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +export enum UserManagerRoleType { + ROLE_TYPE_1 = 'ROLE_TYPE_1', + ROLE_TYPE_2 = 'ROLE_TYPE_2', + ROLE_TYPE_3 = 'ROLE_TYPE_3', +} + +export type HelperFields_fooUser_profilePhoto_photoUrl = { + __typename: 'UserPhotoUrl'; + url: string | null; +}; + +export type HelperFields_fooUser_profilePhoto = { + __typename: 'UserProfilePhoto'; + photoUrl: HelperFields_fooUser_profilePhoto_photoUrl | null; +}; + +export type HelperFields_fooUser = { + __typename: 'User'; + profilePhoto: HelperFields_fooUser_profilePhoto | null; +}; + +export type HelperFields = { + __typename: 'UserManager'; + roleType: Types.UserManagerRoleType; + fooUser: HelperFields_fooUser; +}; diff --git a/dev-test-apollo-tooling/tests/Component.test.ts b/dev-test-apollo-tooling/tests/Component.test.ts new file mode 100644 index 00000000000..2ce5f6fa4c2 --- /dev/null +++ b/dev-test-apollo-tooling/tests/Component.test.ts @@ -0,0 +1,20 @@ +import { describe, it, expect } from 'vitest'; +import { readFileSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname, join } from 'node:path'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +describe('Component.ts', () => { + it('UserManagerRoleType enum should be exported', () => { + const fileContent = readFileSync(join(__dirname, '../src/__generated__/Component.ts'), 'utf-8'); + + expect(fileContent).toMatch(/export enum UserManagerRoleType/); + }); + + it('UserManagerRoleType should be referenced without any prefix', () => { + const fileContent = readFileSync(join(__dirname, '../src/__generated__/Component.ts'), 'utf-8'); + + expect(fileContent).toMatch(/roleType:\s*UserManagerRoleType;/); + }); +}); diff --git a/dev-test-apollo-tooling/tests/Duplicates.test.ts b/dev-test-apollo-tooling/tests/Duplicates.test.ts new file mode 100644 index 00000000000..9a7843a2e64 --- /dev/null +++ b/dev-test-apollo-tooling/tests/Duplicates.test.ts @@ -0,0 +1,31 @@ +import { describe, it, expect } from 'vitest'; +import { readFileSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname, join } from 'node:path'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +describe('Duplicates.ts', () => { + it('ConfigTypeDefinitions types should be exported', () => { + const fileContent = readFileSync(join(__dirname, '../src/__generated__/Duplicates.ts'), 'utf-8'); + + expect(fileContent).toMatch(/export type ConfigTypeDefinitions_ConfigActionId\s*=/); + expect(fileContent).toMatch(/export type ConfigTypeDefinitions_ConfigEnum\s*=/); + expect(fileContent).toMatch(/export type ConfigTypeDefinitions_ConfigIconResource\s*=/); + expect(fileContent).toMatch(/export type ConfigTypeDefinitions\s*=/); + }); + + it('GetFeedbackData creator union type exports should exist', () => { + const fileContent = readFileSync(join(__dirname, '../src/__generated__/Duplicates.ts'), 'utf-8'); + + expect(fileContent).toMatch( + /export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator\s*=/ + ); + expect(fileContent).toMatch( + /export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_EndUser\s*=/ + ); + expect(fileContent).toMatch( + /export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_OrgMember\s*=/ + ); + }); +}); diff --git a/dev-test-apollo-tooling/tsconfig.json b/dev-test-apollo-tooling/tsconfig.json new file mode 100644 index 00000000000..39e2b63b53d --- /dev/null +++ b/dev-test-apollo-tooling/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "verbatimModuleSyntax": true, + "esModuleInterop": true, + "resolveJsonModule": true, + "strict": true + } +} diff --git a/dev-test-apollo-tooling/vitest.config.ts b/dev-test-apollo-tooling/vitest.config.ts new file mode 100644 index 00000000000..b0ef9b2bc35 --- /dev/null +++ b/dev-test-apollo-tooling/vitest.config.ts @@ -0,0 +1,12 @@ +import { defineProject, mergeConfig } from 'vitest/config'; +import { sharedConfig } from '../vitest.config.js'; + +export default mergeConfig( + sharedConfig, + defineProject({ + test: { + name: 'dev-test-apollo-tooling', + include: ['tests/**/*.spec.ts', 'tests/**/*.test.ts'], + }, + }) +); diff --git a/package.json b/package.json index 293f1fbb277..d1344cde659 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "packages/plugins/other/*", "packages/presets/*", "website", - "examples/**/*" + "examples/**/*", + "dev-test-apollo-tooling" ], "packageManager": "yarn@1.22.22", "engines": { @@ -94,6 +95,7 @@ "**/*.{js,jsx,cjs,mjs,ts,tsx,graphql,gql,yml,yaml,json,md}": [ "prettier --write" ], + "**/__generated__/**": [], "yarn.lock": [ "npx yarn-deduplicate" ] diff --git a/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts b/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts index 9f7bfc3efd9..5eb6083c729 100644 --- a/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts +++ b/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts @@ -92,6 +92,10 @@ export class SelectionSetToObject< protected _primitiveAliasedFields: PrimitiveAliasedFields[] = []; protected _linksFields: LinkField[] = []; protected _queriedForTypename = false; + // Enables resolving conflics in extractAllFieldsToTypesCompact mode: + // key === GetFoo_user <-- full field name + // value === User <-- last field type + protected _seenFieldNames: Map = new Map(); constructor( protected _processor: BaseSelectionSetProcessor, @@ -111,7 +115,7 @@ export class SelectionSetToObject< parentSchemaType: GraphQLNamedType, selectionSet: SelectionSetNode, ): SelectionSetToObject { - return new SelectionSetToObject( + const next = new SelectionSetToObject( this._processor, this._scalars, this._schema, @@ -122,6 +126,8 @@ export class SelectionSetToObject< parentSchemaType, selectionSet, ); + next._seenFieldNames = this._seenFieldNames; + return next; } /** @@ -977,9 +983,15 @@ export class SelectionSetToObject< const mergedTypeString = this.buildFragmentTypeName(fragmentName, fragmentSuffix); const { grouped, dependentTypes } = this._buildGroupedSelections(mergedTypeString); + const hasMultipleTypes = Object.keys(grouped).length > 1; + const subTypes: DependentType[] = Object.keys(grouped).flatMap(typeName => { const possibleFields = grouped[typeName].filter(Boolean); - const declarationName = this.buildFragmentTypeName(fragmentName, fragmentSuffix, typeName); + // In compact mode, pass typeName only when there are multiple types + const declarationName = + this._config.extractAllFieldsToTypesCompact && !hasMultipleTypes + ? this.buildFragmentTypeName(fragmentName, fragmentSuffix) + : this.buildFragmentTypeName(fragmentName, fragmentSuffix, typeName); if (possibleFields.length === 0) { return []; @@ -1059,14 +1071,8 @@ export class SelectionSetToObject< } protected buildFragmentTypeName(name: string, suffix: string, typeName = ''): string { - // In compact mode, omit typeName from fragment type names - let fragmentSuffix: string; - if (this._config.extractAllFieldsToTypesCompact) { - fragmentSuffix = suffix; - } else { - fragmentSuffix = typeName && suffix ? `_${typeName}_${suffix}` : typeName ? `_${typeName}` : suffix; - } - + const fragmentSuffix = + typeName && suffix ? `_${typeName}_${suffix}` : typeName ? `_${typeName}` : suffix; return this._convertName(name, { useTypesPrefix: true, suffix: fragmentSuffix, @@ -1074,14 +1080,31 @@ export class SelectionSetToObject< } protected buildParentFieldName(typeName: string, parentName: string): string { + // Sample input: + // typeName = User <-- last field type + // parentName = GetFoo_user <-- full field name + // queries/mutations/fragments are guaranteed to be unique type names, // so we can skip affixing the field names with typeName if (operationTypes.includes(typeName)) { return parentName; } - // When compact mode is enabled, skip appending typeName + // When compact mode is enabled, skip appending typeName initially + // but check for conflicts if (this._config.extractAllFieldsToTypesCompact) { + const existingTypeName = this._seenFieldNames.get(parentName); + if (!existingTypeName) { + // First time seeing this field name, record it's type + this._seenFieldNames.set(parentName, typeName); + return parentName; + } + if (existingTypeName !== typeName) { + // Conflict detected: same field name but different type + // Return field name with type suffix + return `${parentName}_${typeName}`; + } + // Same field name and same type, just return the plain name return parentName; } diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 59b617ec080..b8162b5fce1 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -128,7 +128,16 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< ...(config.externalFragments || []), ]; - this._usedNamedInputTypes = this.collectUsedInputTypes({ schema, documentNode }); + // Create a combined document that includes operations, internal and external fragments for enum collection + const documentWithAllFragments: DocumentNode = { + ...documentNode, + definitions: [ + ...documentNode.definitions.filter(d => d.kind !== Kind.FRAGMENT_DEFINITION), + ...allFragments.map(f => f.node), + ], + }; + + this._usedNamedInputTypes = this.collectUsedInputTypes({ schema, documentNode: documentWithAllFragments }); const processorConfig: SelectionSetProcessorConfig = { namespacedImportName: this.config.namespacedImportName, diff --git a/packages/plugins/typescript/operations/tests/extract-all-types-compact-duplicates.spec.ts b/packages/plugins/typescript/operations/tests/extract-all-types-compact-duplicates.spec.ts new file mode 100644 index 00000000000..03daec54d3d --- /dev/null +++ b/packages/plugins/typescript/operations/tests/extract-all-types-compact-duplicates.spec.ts @@ -0,0 +1,339 @@ +import { mergeOutputs, Types } from '@graphql-codegen/plugin-helpers'; +import { validateTs } from '@graphql-codegen/testing'; +import { buildSchema, parse } from 'graphql'; +import { plugin, type TypeScriptDocumentsPluginConfig } from '../src/index.js'; + +describe('extractAllFieldsToTypesCompact: duplicate type names', () => { + const validate = async (content: Types.PluginOutput) => { + const m = mergeOutputs([content]); + validateTs(m, undefined, undefined, undefined, []); + + return m; + }; + + it('should add type suffix to disambiguate duplicate fragment type names in union types', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + typeDefinitions: [TypeDefinition!]! + } + + interface TypeDefinition { + identifier: String! + } + + type StringType implements TypeDefinition { + identifier: String! + } + + type IntType implements TypeDefinition { + identifier: String! + min: Int + max: Int + } + + type ArrayType implements TypeDefinition { + identifier: String! + elementTypeId: String! + } + + type BooleanType implements TypeDefinition { + identifier: String! + } + `); + + const document = parse(/* GraphQL */ ` + fragment TypeDefinitions on TypeDefinition { + __typename + ... on StringType { + identifier + } + ... on IntType { + identifier + min + max + } + ... on ArrayType { + identifier + elementTypeId + } + ... on BooleanType { + identifier + } + } + `); + + const config: TypeScriptDocumentsPluginConfig = { + extractAllFieldsToTypesCompact: true, + printFieldsOnNewLines: true, + nonOptionalTypename: true, + fragmentSuffix: '', + }; + + const { content } = await plugin(schema, [{ location: 'test-file.ts', document }], config, { outputFile: '' }); + + await validate(content); + + // Should generate unique type names with type suffixes + expect(content).toContain('type TypeDefinitions_StringType_Fragment = {'); + expect(content).toContain('type TypeDefinitions_IntType_Fragment = {'); + expect(content).toContain('type TypeDefinitions_ArrayType_Fragment = {'); + expect(content).toContain('type TypeDefinitions_BooleanType_Fragment = {'); + + // Should generate a union type referencing the unique names + expect(content).toContain('export type TypeDefinitionsFragment ='); + expect(content).toContain('| TypeDefinitions_StringType_Fragment'); + expect(content).toContain('| TypeDefinitions_IntType_Fragment'); + expect(content).toContain('| TypeDefinitions_ArrayType_Fragment'); + expect(content).toContain('| TypeDefinitions_BooleanType_Fragment'); + + // Should NOT have duplicate type declarations with the same name + const typeDeclarationRegex = /type TypeDefinitions_StringType_Fragment = \{/g; + const matches = content.match(typeDeclarationRegex); + expect(matches).toHaveLength(1); // Should appear exactly once + }); + + it('should handle nested fields with parameters in union fragments', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + typeDefinitions: [TypeDefinition!]! + } + + interface TypeDefinition { + identifier: String! + } + + type Parameter { + name: String! + } + + type StructType implements TypeDefinition { + identifier: String! + parameters: [Parameter!]! + } + + type FunctionType implements TypeDefinition { + identifier: String! + parameters: [Parameter!]! + } + `); + + const document = parse(/* GraphQL */ ` + fragment ParameterDetails on Parameter { + __typename + } + + fragment TypeDefinitions on TypeDefinition { + __typename + ... on StructType { + identifier + parameters { + ...ParameterDetails + } + } + ... on FunctionType { + identifier + parameters { + ...ParameterDetails + } + } + } + `); + + const config: TypeScriptDocumentsPluginConfig = { + extractAllFieldsToTypesCompact: true, + printFieldsOnNewLines: true, + nonOptionalTypename: true, + fragmentSuffix: '', + }; + + const { content } = await plugin(schema, [{ location: 'test-file.ts', document }], config, { outputFile: '' }); + + await validate(content); + + // Should generate unique names for the main types + expect(content).toContain('type TypeDefinitions_StructType_Fragment = {'); + expect(content).toContain('type TypeDefinitions_FunctionType_Fragment = {'); + + // Should generate a union type + expect(content).toContain('export type TypeDefinitionsFragment ='); + expect(content).toContain('| TypeDefinitions_StructType_Fragment'); + expect(content).toContain('| TypeDefinitions_FunctionType_Fragment'); + + // Verify there are no duplicate type declarations + const structTypeRegex = /type TypeDefinitions_StructType_Fragment = \{/g; + const structMatches = content.match(structTypeRegex); + expect(structMatches).toHaveLength(1); + + const functionTypeRegex = /type TypeDefinitions_FunctionType_Fragment = \{/g; + const functionMatches = content.match(functionTypeRegex); + expect(functionMatches).toHaveLength(1); + }); + + it('should not add type suffix when there is only one inline fragment', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User + } + + interface User { + id: ID! + } + + type PremiumUser implements User { + id: ID! + isPremium: Boolean! + } + `); + + const document = parse(/* GraphQL */ ` + fragment UserFragment on User { + __typename + ... on PremiumUser { + id + isPremium + } + } + `); + + const config: TypeScriptDocumentsPluginConfig = { + extractAllFieldsToTypesCompact: true, + printFieldsOnNewLines: true, + nonOptionalTypename: true, + fragmentSuffix: '', + }; + + const { content } = await plugin(schema, [{ location: 'test-file.ts', document }], config, { outputFile: '' }); + + await validate(content); + + // With only one inline fragment, should use the base name without type suffix + expect(content).toContain('export type UserFragmentFragment = {'); + expect(content).not.toContain('UserFragment_PremiumUser_Fragment'); + }); + + it('should handle complex union with many types', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + shapes: [Shape!]! + } + + interface Shape { + id: ID! + } + + type Circle implements Shape { + id: ID! + radius: Float! + } + + type Rectangle implements Shape { + id: ID! + width: Float! + height: Float! + } + + type Triangle implements Shape { + id: ID! + base: Float! + height: Float! + } + + type Square implements Shape { + id: ID! + side: Float! + } + + type Polygon implements Shape { + id: ID! + sides: Int! + vertices: [Float!]! + } + + type Ellipse implements Shape { + id: ID! + majorAxis: Float! + minorAxis: Float! + } + + type Pentagon implements Shape { + id: ID! + side: Float! + } + `); + + const document = parse(/* GraphQL */ ` + fragment ShapeDetails on Shape { + __typename + ... on Circle { + id + radius + } + ... on Rectangle { + id + width + height + } + ... on Triangle { + id + base + height + } + ... on Square { + id + side + } + ... on Polygon { + id + sides + vertices + } + ... on Ellipse { + id + majorAxis + minorAxis + } + ... on Pentagon { + id + side + } + } + `); + + const config: TypeScriptDocumentsPluginConfig = { + extractAllFieldsToTypesCompact: true, + printFieldsOnNewLines: true, + nonOptionalTypename: true, + fragmentSuffix: '', + }; + + const { content } = await plugin(schema, [{ location: 'test-file.ts', document }], config, { outputFile: '' }); + + await validate(content); + + // Verify all unique type names exist + expect(content).toContain('type ShapeDetails_Circle_Fragment'); + expect(content).toContain('type ShapeDetails_Rectangle_Fragment'); + expect(content).toContain('type ShapeDetails_Triangle_Fragment'); + expect(content).toContain('type ShapeDetails_Square_Fragment'); + expect(content).toContain('type ShapeDetails_Polygon_Fragment'); + expect(content).toContain('type ShapeDetails_Ellipse_Fragment'); + expect(content).toContain('type ShapeDetails_Pentagon_Fragment'); + + // Verify union type exists + expect(content).toContain('export type ShapeDetailsFragment ='); + + // Verify all types are in the union + expect(content).toContain('| ShapeDetails_Circle_Fragment'); + expect(content).toContain('| ShapeDetails_Rectangle_Fragment'); + expect(content).toContain('| ShapeDetails_Triangle_Fragment'); + expect(content).toContain('| ShapeDetails_Square_Fragment'); + expect(content).toContain('| ShapeDetails_Polygon_Fragment'); + expect(content).toContain('| ShapeDetails_Ellipse_Fragment'); + expect(content).toContain('| ShapeDetails_Pentagon_Fragment'); + + // Verify there are no duplicate type declarations + const circleTypeRegex = /type ShapeDetails_Circle_Fragment = \{/g; + const circleMatches = content.match(circleTypeRegex); + expect(circleMatches).toHaveLength(1); + }); +}); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.external-fragments-enum.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.external-fragments-enum.spec.ts new file mode 100644 index 00000000000..d1296b56719 --- /dev/null +++ b/packages/plugins/typescript/operations/tests/ts-documents.external-fragments-enum.spec.ts @@ -0,0 +1,479 @@ +import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; +import { validateTs } from '@graphql-codegen/testing'; +import { buildSchema, parse } from 'graphql'; +import { plugin } from '../src/index.js'; + +describe('TypeScript Operations Plugin - External Fragments with Enums', () => { + it('should include enum in document when enum is used in external fragment', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User + } + + type User { + id: ID! + name: String! + role: UserRole! + profile: UserProfile! + } + + type UserProfile { + bio: String! + } + + enum UserRole { + ADMIN + CUSTOMER + GUEST + } + `); + + // Fragment defined separately (external fragment) + const fragmentDocument = parse(/* GraphQL */ ` + fragment UserFields on User { + role + profile { + bio + } + } + `); + + // Query that uses the external fragment + const queryDocument = parse(/* GraphQL */ ` + query GetUser { + user { + id + ...UserFields + } + } + `); + + const fragmentDef = fragmentDocument.definitions[0]; + if (fragmentDef.kind !== 'FragmentDefinition') { + throw new Error('Expected fragment definition'); + } + + const result = mergeOutputs([ + await plugin( + schema, + [{ document: queryDocument }], + { + enumType: 'native', + externalFragments: [ + { + node: fragmentDef, + name: 'UserFields', + onType: 'User', + isExternal: true, + }, + ], + }, + { outputFile: '' } + ), + ]); + + // The enum should be included in the output + expect(result).toContain('export enum UserRole'); + expect(result).toContain("Admin = 'ADMIN'"); + expect(result).toContain("Customer = 'CUSTOMER'"); + expect(result).toContain("Guest = 'GUEST'"); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('should include enum in document when enum is nested deeply in external fragment', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + organization: Organization + } + + type Organization { + id: ID! + users: [User!]! + } + + type User { + id: ID! + manager: Manager! + } + + type Manager { + id: ID! + roleType: ManagerRole! + } + + enum ManagerRole { + SENIOR + JUNIOR + LEAD + } + `); + + const fragmentDocument = parse(/* GraphQL */ ` + fragment ManagerFields on User { + manager { + id + roleType + } + } + `); + + const queryDocument = parse(/* GraphQL */ ` + query GetOrganization { + organization { + id + users { + id + ...ManagerFields + } + } + } + `); + + const fragmentDef = fragmentDocument.definitions[0]; + if (fragmentDef.kind !== 'FragmentDefinition') { + throw new Error('Expected fragment definition'); + } + + const result = mergeOutputs([ + await plugin( + schema, + [{ document: queryDocument }], + { + enumType: 'native', + externalFragments: [ + { + node: fragmentDef, + name: 'ManagerFields', + onType: 'User', + isExternal: true, + }, + ], + }, + { outputFile: '' } + ), + ]); + + // The enum should be included even though it's nested deeply + expect(result).toContain('export enum ManagerRole'); + expect(result).toContain("Senior = 'SENIOR'"); + expect(result).toContain("Junior = 'JUNIOR'"); + expect(result).toContain("Lead = 'LEAD'"); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('should include multiple enums from multiple external fragments', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User + } + + type User { + id: ID! + role: UserRole! + status: UserStatus! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + enum UserStatus { + ACTIVE + INACTIVE + } + `); + + const roleFragmentDocument = parse(/* GraphQL */ ` + fragment RoleFields on User { + role + } + `); + + const statusFragmentDocument = parse(/* GraphQL */ ` + fragment StatusFields on User { + status + } + `); + + const queryDocument = parse(/* GraphQL */ ` + query GetUser { + user { + id + ...RoleFields + ...StatusFields + } + } + `); + + const roleFragmentDef = roleFragmentDocument.definitions[0]; + const statusFragmentDef = statusFragmentDocument.definitions[0]; + + if (roleFragmentDef.kind !== 'FragmentDefinition' || statusFragmentDef.kind !== 'FragmentDefinition') { + throw new Error('Expected fragment definitions'); + } + + const result = mergeOutputs([ + await plugin( + schema, + [{ document: queryDocument }], + { + enumType: 'native', + externalFragments: [ + { + node: roleFragmentDef, + name: 'RoleFields', + onType: 'User', + isExternal: true, + }, + { + node: statusFragmentDef, + name: 'StatusFields', + onType: 'User', + isExternal: true, + }, + ], + }, + { outputFile: '' } + ), + ]); + + // Both enums should be included + expect(result).toContain('export enum UserRole'); + expect(result).toContain("Admin = 'ADMIN'"); + expect(result).toContain("Customer = 'CUSTOMER'"); + + expect(result).toContain('export enum UserStatus'); + expect(result).toContain("Active = 'ACTIVE'"); + expect(result).toContain("Inactive = 'INACTIVE'"); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('should not duplicate enum if it appears in both query and external fragment', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User + admin: User + } + + type User { + id: ID! + role: UserRole! + } + + enum UserRole { + ADMIN + CUSTOMER + } + `); + + const fragmentDocument = parse(/* GraphQL */ ` + fragment UserFields on User { + role + } + `); + + const queryDocument = parse(/* GraphQL */ ` + query GetUsers { + user { + id + ...UserFields + } + admin { + id + role + } + } + `); + + const fragmentDef = fragmentDocument.definitions[0]; + if (fragmentDef.kind !== 'FragmentDefinition') { + throw new Error('Expected fragment definition'); + } + + const result = mergeOutputs([ + await plugin( + schema, + [{ document: queryDocument }], + { + enumType: 'native', + externalFragments: [ + { + node: fragmentDef, + name: 'UserFields', + onType: 'User', + isExternal: true, + }, + ], + }, + { outputFile: '' } + ), + ]); + + // The enum should appear only once + const enumMatches = result.match(/export enum UserRole/g); + expect(enumMatches).toHaveLength(1); + + expect(result).toContain('export enum UserRole'); + expect(result).toContain("Admin = 'ADMIN'"); + expect(result).toContain("Customer = 'CUSTOMER'"); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('should handle external fragment with nested fragment spread containing enum', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User + } + + type User { + id: ID! + profile: UserProfile! + } + + type UserProfile { + id: ID! + visibility: Visibility! + } + + enum Visibility { + PUBLIC + PRIVATE + FRIENDS_ONLY + } + `); + + const profileFragmentDocument = parse(/* GraphQL */ ` + fragment ProfileVisibility on UserProfile { + visibility + } + `); + + const userFragmentDocument = parse(/* GraphQL */ ` + fragment UserWithProfile on User { + id + profile { + ...ProfileVisibility + } + } + `); + + const queryDocument = parse(/* GraphQL */ ` + query GetUser { + user { + ...UserWithProfile + } + } + `); + + const profileFragmentDef = profileFragmentDocument.definitions[0]; + const userFragmentDef = userFragmentDocument.definitions[0]; + + if (profileFragmentDef.kind !== 'FragmentDefinition' || userFragmentDef.kind !== 'FragmentDefinition') { + throw new Error('Expected fragment definitions'); + } + + const result = mergeOutputs([ + await plugin( + schema, + [{ document: queryDocument }], + { + enumType: 'native', + externalFragments: [ + { + node: profileFragmentDef, + name: 'ProfileVisibility', + onType: 'UserProfile', + isExternal: true, + }, + { + node: userFragmentDef, + name: 'UserWithProfile', + onType: 'User', + isExternal: true, + }, + ], + }, + { outputFile: '' } + ), + ]); + + // The enum should be included even with nested fragment spreads + expect(result).toContain('export enum Visibility'); + expect(result).toContain("Public = 'PUBLIC'"); + expect(result).toContain("Private = 'PRIVATE'"); + expect(result).toContain("FriendsOnly = 'FRIENDS_ONLY'"); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('should include enum with const enum type from external fragment', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User + } + + type User { + id: ID! + role: UserRole! + } + + enum UserRole { + ADMIN + CUSTOMER + } + `); + + const fragmentDocument = parse(/* GraphQL */ ` + fragment UserFields on User { + role + } + `); + + const queryDocument = parse(/* GraphQL */ ` + query GetUser { + user { + id + ...UserFields + } + } + `); + + const fragmentDef = fragmentDocument.definitions[0]; + if (fragmentDef.kind !== 'FragmentDefinition') { + throw new Error('Expected fragment definition'); + } + + const result = mergeOutputs([ + await plugin( + schema, + [{ document: queryDocument }], + { + enumType: 'const', + externalFragments: [ + { + node: fragmentDef, + name: 'UserFields', + onType: 'User', + isExternal: true, + }, + ], + }, + { outputFile: '' } + ), + ]); + + // The enum should be included as const object + expect(result).toContain('export const UserRole = {'); + expect(result).toContain("Admin: 'ADMIN'"); + expect(result).toContain("Customer: 'CUSTOMER'"); + expect(result).toContain('} as const;'); + expect(result).toContain('export type UserRole = typeof UserRole[keyof typeof UserRole];'); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); +}); diff --git a/yarn.lock b/yarn.lock index 70e9963c646..9c893aa777a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -20,10 +20,10 @@ package-manager-detector "^1.3.0" tinyexec "^1.0.1" -"@apollo/client@^3.7.10": - version "3.14.1" - resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.14.1.tgz#98931c8feea4a50c89c32ec0c8ffd04ccaa9416f" - integrity sha512-SgGX6E23JsZhUdG2anxiyHvEvvN6CUaI4ZfMsndZFeuHPXL3H0IsaiNAhLITSISbeyeYd+CBd9oERXQDdjXWZw== +"@apollo/client@3.13.8", "@apollo/client@^3.7.10": + version "3.13.8" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.13.8.tgz#ef1d49a5b134c69a55e3f137164a8e323aef4e2a" + integrity sha512-YM9lQpm0VfVco4DSyKooHS/fDTiKQcCHfxr7i3iL6a0kP/jNO5+4NFK6vtRDxaYisd5BrwOZHLJpPBnvRVpKPg== dependencies: "@graphql-typed-document-node/core" "^3.1.1" "@wry/caches" "^1.0.0" @@ -1437,86 +1437,171 @@ "@whatwg-node/promise-helpers" "^1.0.0" tslib "^2.5.0" +"@esbuild/aix-ppc64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz#d1bc06aedb6936b3b6d313bf809a5a40387d2b7f" + integrity sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA== + "@esbuild/aix-ppc64@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz#815b39267f9bffd3407ea6c376ac32946e24f8d2" integrity sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg== +"@esbuild/android-arm64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz#7ad65a36cfdb7e0d429c353e00f680d737c2aed4" + integrity sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA== + "@esbuild/android-arm64@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz#19b882408829ad8e12b10aff2840711b2da361e8" integrity sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg== +"@esbuild/android-arm@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.19.12.tgz#b0c26536f37776162ca8bde25e42040c203f2824" + integrity sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w== + "@esbuild/android-arm@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.27.3.tgz#90be58de27915efa27b767fcbdb37a4470627d7b" integrity sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA== +"@esbuild/android-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.19.12.tgz#cb13e2211282012194d89bf3bfe7721273473b3d" + integrity sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew== + "@esbuild/android-x64@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.27.3.tgz#d7dcc976f16e01a9aaa2f9b938fbec7389f895ac" integrity sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ== +"@esbuild/darwin-arm64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz#cbee41e988020d4b516e9d9e44dd29200996275e" + integrity sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g== + "@esbuild/darwin-arm64@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz#9f6cac72b3a8532298a6a4493ed639a8988e8abd" integrity sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg== +"@esbuild/darwin-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz#e37d9633246d52aecf491ee916ece709f9d5f4cd" + integrity sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A== + "@esbuild/darwin-x64@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz#ac61d645faa37fd650340f1866b0812e1fb14d6a" integrity sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg== +"@esbuild/freebsd-arm64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz#1ee4d8b682ed363b08af74d1ea2b2b4dbba76487" + integrity sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA== + "@esbuild/freebsd-arm64@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz#b8625689d73cf1830fe58c39051acdc12474ea1b" integrity sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w== +"@esbuild/freebsd-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz#37a693553d42ff77cd7126764b535fb6cc28a11c" + integrity sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg== + "@esbuild/freebsd-x64@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz#07be7dd3c9d42fe0eccd2ab9f9ded780bc53bead" integrity sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA== +"@esbuild/linux-arm64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz#be9b145985ec6c57470e0e051d887b09dddb2d4b" + integrity sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA== + "@esbuild/linux-arm64@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz#bf31918fe5c798586460d2b3d6c46ed2c01ca0b6" integrity sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg== +"@esbuild/linux-arm@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz#207ecd982a8db95f7b5279207d0ff2331acf5eef" + integrity sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w== + "@esbuild/linux-arm@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz#28493ee46abec1dc3f500223cd9f8d2df08f9d11" integrity sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw== +"@esbuild/linux-ia32@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz#d0d86b5ca1562523dc284a6723293a52d5860601" + integrity sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA== + "@esbuild/linux-ia32@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz#750752a8b30b43647402561eea764d0a41d0ee29" integrity sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg== +"@esbuild/linux-loong64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz#9a37f87fec4b8408e682b528391fa22afd952299" + integrity sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA== + "@esbuild/linux-loong64@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz#a5a92813a04e71198c50f05adfaf18fc1e95b9ed" integrity sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA== +"@esbuild/linux-mips64el@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz#4ddebd4e6eeba20b509d8e74c8e30d8ace0b89ec" + integrity sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w== + "@esbuild/linux-mips64el@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz#deb45d7fd2d2161eadf1fbc593637ed766d50bb1" integrity sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw== +"@esbuild/linux-ppc64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz#adb67dadb73656849f63cd522f5ecb351dd8dee8" + integrity sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg== + "@esbuild/linux-ppc64@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz#6f39ae0b8c4d3d2d61a65b26df79f6e12a1c3d78" integrity sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA== +"@esbuild/linux-riscv64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz#11bc0698bf0a2abf8727f1c7ace2112612c15adf" + integrity sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg== + "@esbuild/linux-riscv64@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz#4c5c19c3916612ec8e3915187030b9df0b955c1d" integrity sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ== +"@esbuild/linux-s390x@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz#e86fb8ffba7c5c92ba91fc3b27ed5a70196c3cc8" + integrity sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg== + "@esbuild/linux-s390x@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz#9ed17b3198fa08ad5ccaa9e74f6c0aff7ad0156d" integrity sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw== +"@esbuild/linux-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz#5f37cfdc705aea687dfe5dfbec086a05acfe9c78" + integrity sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg== + "@esbuild/linux-x64@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz#12383dcbf71b7cf6513e58b4b08d95a710bf52a5" @@ -1527,6 +1612,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz#dd0cb2fa543205fcd931df44f4786bfcce6df7d7" integrity sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA== +"@esbuild/netbsd-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz#29da566a75324e0d0dd7e47519ba2f7ef168657b" + integrity sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA== + "@esbuild/netbsd-x64@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz#028ad1807a8e03e155153b2d025b506c3787354b" @@ -1537,6 +1627,11 @@ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz#e3c16ff3490c9b59b969fffca87f350ffc0e2af5" integrity sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw== +"@esbuild/openbsd-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz#306c0acbdb5a99c95be98bdd1d47c916e7dc3ff0" + integrity sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw== + "@esbuild/openbsd-x64@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz#c5a4693fcb03d1cbecbf8b422422468dfc0d2a8b" @@ -1547,27 +1642,54 @@ resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz#082082444f12db564a0775a41e1991c0e125055e" integrity sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g== +"@esbuild/sunos-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz#0933eaab9af8b9b2c930236f62aae3fc593faf30" + integrity sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA== + "@esbuild/sunos-x64@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz#5ab036c53f929e8405c4e96e865a424160a1b537" integrity sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA== +"@esbuild/win32-arm64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz#773bdbaa1971b36db2f6560088639ccd1e6773ae" + integrity sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A== + "@esbuild/win32-arm64@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz#38de700ef4b960a0045370c171794526e589862e" integrity sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA== +"@esbuild/win32-ia32@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz#000516cad06354cc84a73f0943a4aa690ef6fd67" + integrity sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ== + "@esbuild/win32-ia32@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz#451b93dc03ec5d4f38619e6cd64d9f9eff06f55c" integrity sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q== +"@esbuild/win32-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz#c57c8afbb4054a3ab8317591a0b7320360b444ae" + integrity sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA== + "@esbuild/win32-x64@0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz#0eaf705c941a218a43dba8e09f1df1d6cd2f1f17" integrity sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA== -"@eslint-community/eslint-utils@^4.1.2", "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0", "@eslint-community/eslint-utils@^4.4.1", "@eslint-community/eslint-utils@^4.8.0", "@eslint-community/eslint-utils@^4.9.1": +"@eslint-community/eslint-utils@^4.1.2", "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0", "@eslint-community/eslint-utils@^4.4.1": + version "4.4.1" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56" + integrity sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA== + dependencies: + eslint-visitor-keys "^3.4.3" + +"@eslint-community/eslint-utils@^4.8.0", "@eslint-community/eslint-utils@^4.9.1": version "4.9.1" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz#4e90af67bc51ddee6cdef5284edf572ec376b595" integrity sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ== @@ -4268,7 +4390,7 @@ resolved "https://registry.yarnpkg.com/@speed-highlight/core/-/core-1.2.15.tgz#88c45609a2b5c2293a2e1935417c507f98f39d0b" integrity sha512-BMq1K3DsElxDWawkX6eLg9+CKJrTVGCBAWVuHXVUV2u0s2711qiChLSId6ikYPfxhdYocLNt3wWwSvDiTvFabw== -"@standard-schema/spec@^1.1.0": +"@standard-schema/spec@^1.0.0", "@standard-schema/spec@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.1.0.tgz#a79b55dbaf8604812f52d140b2c9ab41bc150bb8" integrity sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w== @@ -4910,7 +5032,14 @@ dependencies: "@types/unist" "*" -"@types/node@*", "@types/node@24.12.2", "@types/node@^24.0.0": +"@types/node@*", "@types/node@^25.0.3": + version "25.0.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-25.0.9.tgz#81ce3579ddf67cae812a9d49c8a0ab90c82e7782" + integrity sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw== + dependencies: + undici-types "~7.16.0" + +"@types/node@24.12.2", "@types/node@^24.0.0": version "24.12.2" resolved "https://registry.yarnpkg.com/@types/node/-/node-24.12.2.tgz#353cb161dbf1785ea25e8829ba7ec574c5c629ac" integrity sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g== @@ -5370,6 +5499,18 @@ dependencies: "@rolldown/pluginutils" "1.0.0-rc.2" +"@vitest/expect@4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-4.0.4.tgz#ba98573c19f568ce8ad0377ebbb5689883a2f053" + integrity sha512-0ioMscWJtfpyH7+P82sGpAi3Si30OVV73jD+tEqXm5+rIx9LgnfdaOn45uaFkKOncABi/PHL00Yn0oW/wK4cXw== + dependencies: + "@standard-schema/spec" "^1.0.0" + "@types/chai" "^5.2.2" + "@vitest/spy" "4.0.4" + "@vitest/utils" "4.0.4" + chai "^6.0.1" + tinyrainbow "^3.0.3" + "@vitest/expect@4.1.4": version "4.1.4" resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-4.1.4.tgz#1507e51c53969723c99e8a7f054aa12cfa7c1a4d" @@ -5382,6 +5523,15 @@ chai "^6.2.2" tinyrainbow "^3.1.0" +"@vitest/mocker@4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-4.0.4.tgz#d3366047e1f075874d35d40218e49266dfa2e561" + integrity sha512-UTtKgpjWj+pvn3lUM55nSg34098obGhSHH+KlJcXesky8b5wCUgg7s60epxrS6yAG8slZ9W8T9jGWg4PisMf5Q== + dependencies: + "@vitest/spy" "4.0.4" + estree-walker "^3.0.3" + magic-string "^0.30.19" + "@vitest/mocker@4.1.4": version "4.1.4" resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-4.1.4.tgz#5d22e99d8dbacf2f77f7a4c30a6e17eece7f25ef" @@ -5391,6 +5541,13 @@ estree-walker "^3.0.3" magic-string "^0.30.21" +"@vitest/pretty-format@4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-4.0.4.tgz#19ffa9fb35853554e272799b68743717dc2ec1b7" + integrity sha512-lHI2rbyrLVSd1TiHGJYyEtbOBo2SDndIsN3qY4o4xe2pBxoJLD6IICghNCvD7P+BFin6jeyHXiUICXqgl6vEaQ== + dependencies: + tinyrainbow "^3.0.3" + "@vitest/pretty-format@4.1.4": version "4.1.4" resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-4.1.4.tgz#0ee79cd2ef8321330dabb8cc57ba9bce237e7183" @@ -5398,6 +5555,14 @@ dependencies: tinyrainbow "^3.1.0" +"@vitest/runner@4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-4.0.4.tgz#ca0eb9de67bdfe6c6cb0841a23f47474af92dbf9" + integrity sha512-99EDqiCkncCmvIZj3qJXBZbyoQ35ghOwVWNnQ5nj0Hnsv4Qm40HmrMJrceewjLVvsxV/JSU4qyx2CGcfMBmXJw== + dependencies: + "@vitest/utils" "4.0.4" + pathe "^2.0.3" + "@vitest/runner@4.1.4": version "4.1.4" resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-4.1.4.tgz#8f884f265efabfdd8a5ee393cfe622a01ec849c2" @@ -5406,6 +5571,15 @@ "@vitest/utils" "4.1.4" pathe "^2.0.3" +"@vitest/snapshot@4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-4.0.4.tgz#ea90222f94da640481c8809e87597171b049c727" + integrity sha512-XICqf5Gi4648FGoBIeRgnHWSNDp+7R5tpclGosFaUUFzY6SfcpsfHNMnC7oDu/iOLBxYfxVzaQpylEvpgii3zw== + dependencies: + "@vitest/pretty-format" "4.0.4" + magic-string "^0.30.19" + pathe "^2.0.3" + "@vitest/snapshot@4.1.4": version "4.1.4" resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-4.1.4.tgz#600c04ee1c598d4e6ce219afae684ff21c3e187d" @@ -5416,11 +5590,24 @@ magic-string "^0.30.21" pathe "^2.0.3" +"@vitest/spy@4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-4.0.4.tgz#b20b8736cdfd1774e38bceeadac1936d9b7653bf" + integrity sha512-G9L13AFyYECo40QG7E07EdYnZZYCKMTSp83p9W8Vwed0IyCG1GnpDLxObkx8uOGPXfDpdeVf24P1Yka8/q1s9g== + "@vitest/spy@4.1.4": version "4.1.4" resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-4.1.4.tgz#b955fcef98bcc746e7fc61d17d4725b43b33fa6d" integrity sha512-XxNdAsKW7C+FLydqFJLb5KhJtl3PGCMmYwFRfhvIgxJvLSXhhVI1zM8f1qD3Zg7RCjTSzDVyct6sghs9UEgBEQ== +"@vitest/utils@4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-4.0.4.tgz#90d355d0f21596a06eca83f84783a29467513d6a" + integrity sha512-4bJLmSvZLyVbNsYFRpPYdJViG9jZyRvMZ35IF4ymXbRZoS+ycYghmwTGiscTXduUg2lgKK7POWIyXJNute1hjw== + dependencies: + "@vitest/pretty-format" "4.0.4" + tinyrainbow "^3.0.3" + "@vitest/utils@4.1.4": version "4.1.4" resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-4.1.4.tgz#9518fb0ad0903ae455e82e063fa18e7558aa6065" @@ -6371,7 +6558,7 @@ ccount@^2.0.0: resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5" integrity sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg== -chai@^6.2.2: +chai@^6.0.1, chai@^6.2.2: version "6.2.2" resolved "https://registry.yarnpkg.com/chai/-/chai-6.2.2.tgz#ae41b52c9aca87734505362717f3255facda360e" integrity sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg== @@ -7693,6 +7880,11 @@ es-iterator-helpers@^1.2.1: iterator.prototype "^1.1.5" math-intrinsics "^1.1.0" +es-module-lexer@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.7.0.tgz#9159601561880a85f2734560a9099b2c31e5372a" + integrity sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA== + es-module-lexer@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-2.0.0.tgz#f657cd7a9448dcdda9c070a3cb75e5dc1e85f5b1" @@ -7783,6 +7975,35 @@ esbuild@0.27.3, esbuild@^0.27.0, esbuild@~0.27.0: "@esbuild/win32-ia32" "0.27.3" "@esbuild/win32-x64" "0.27.3" +esbuild@~0.19.10: + version "0.19.12" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.12.tgz#dc82ee5dc79e82f5a5c3b4323a2a641827db3e04" + integrity sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg== + optionalDependencies: + "@esbuild/aix-ppc64" "0.19.12" + "@esbuild/android-arm" "0.19.12" + "@esbuild/android-arm64" "0.19.12" + "@esbuild/android-x64" "0.19.12" + "@esbuild/darwin-arm64" "0.19.12" + "@esbuild/darwin-x64" "0.19.12" + "@esbuild/freebsd-arm64" "0.19.12" + "@esbuild/freebsd-x64" "0.19.12" + "@esbuild/linux-arm" "0.19.12" + "@esbuild/linux-arm64" "0.19.12" + "@esbuild/linux-ia32" "0.19.12" + "@esbuild/linux-loong64" "0.19.12" + "@esbuild/linux-mips64el" "0.19.12" + "@esbuild/linux-ppc64" "0.19.12" + "@esbuild/linux-riscv64" "0.19.12" + "@esbuild/linux-s390x" "0.19.12" + "@esbuild/linux-x64" "0.19.12" + "@esbuild/netbsd-x64" "0.19.12" + "@esbuild/openbsd-x64" "0.19.12" + "@esbuild/sunos-x64" "0.19.12" + "@esbuild/win32-arm64" "0.19.12" + "@esbuild/win32-ia32" "0.19.12" + "@esbuild/win32-x64" "0.19.12" + escalade@^3.1.1, escalade@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" @@ -8390,7 +8611,7 @@ executable@^4.1.1: dependencies: pify "^2.2.0" -expect-type@^1.3.0: +expect-type@^1.2.2, expect-type@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.3.0.tgz#0d58ed361877a31bbc4dd6cf71bbfef7faf6bd68" integrity sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA== @@ -8829,10 +9050,10 @@ get-symbol-description@^1.1.0: es-errors "^1.3.0" get-intrinsic "^1.2.6" -get-tsconfig@^4.10.0, get-tsconfig@^4.7.5, get-tsconfig@^4.8.1: - version "4.13.7" - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.13.7.tgz#b9d8b199b06033ceeea1a93df7ea5765415089bc" - integrity sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q== +get-tsconfig@^4.10.0, get-tsconfig@^4.7.2, get-tsconfig@^4.7.5, get-tsconfig@^4.8.1: + version "4.13.0" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.13.0.tgz#fcdd991e6d22ab9a600f00e91c318707a5d9a0d7" + integrity sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ== dependencies: resolve-pkg-maps "^1.0.0" @@ -10593,7 +10814,7 @@ lz-string@^1.4.4: resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== -magic-string@^0.30.11, magic-string@^0.30.17, magic-string@^0.30.21: +magic-string@^0.30.11, magic-string@^0.30.17, magic-string@^0.30.19, magic-string@^0.30.21: version "0.30.21" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== @@ -12452,7 +12673,7 @@ postcss@8.4.31: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8.4.4, postcss@^8.4.47, postcss@^8.5.8: +postcss@^8.4.4, postcss@^8.4.47, postcss@^8.5.6, postcss@^8.5.8: version "8.5.9" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.9.tgz#f6ee9e0b94f0f19c97d2f172bfbd7fc71fe1cca4" integrity sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw== @@ -13288,7 +13509,7 @@ rolldown@1.0.0-rc.15: "@rolldown/binding-win32-arm64-msvc" "1.0.0-rc.15" "@rolldown/binding-win32-x64-msvc" "1.0.0-rc.15" -rollup@^4.34.8: +rollup@^4.34.8, rollup@^4.43.0: version "4.60.1" resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.60.1.tgz#b4aa2bcb3a5e1437b5fad40d43fe42d4bde7a42d" integrity sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w== @@ -13882,6 +14103,11 @@ static-eval@2.1.1: dependencies: escodegen "^2.1.0" +std-env@^3.9.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.10.0.tgz#d810b27e3a073047b2b5e40034881f5ea6f9c83b" + integrity sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg== + std-env@^4.0.0-rc.1: version "4.0.0" resolved "https://registry.yarnpkg.com/std-env/-/std-env-4.0.0.tgz#ba3dc31c3a46bc5ba21138aa20a6a4ceb5bb9b7e" @@ -14378,7 +14604,7 @@ tinyglobby@^0.2.11, tinyglobby@^0.2.12, tinyglobby@^0.2.13, tinyglobby@^0.2.15: fdir "^6.5.0" picomatch "^4.0.4" -tinyrainbow@^3.1.0: +tinyrainbow@^3.0.3, tinyrainbow@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-3.1.0.tgz#1d8a623893f95cf0a2ddb9e5d11150e191409421" integrity sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw== @@ -14579,6 +14805,16 @@ tsx@4.21.0: optionalDependencies: fsevents "~2.3.3" +tsx@4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.7.0.tgz#1689cfe7dda495ca1f9a66d4cad79cb57b9f6f4a" + integrity sha512-I+t79RYPlEYlHn9a+KzwrvEwhJg35h/1zHsLC2JXvhC2mdynMv6Zxzvhv5EMV6VF5qJlLlkSnMVvdZV3PSIGcg== + dependencies: + esbuild "~0.19.10" + get-tsconfig "^4.7.2" + optionalDependencies: + fsevents "~2.3.3" + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -14700,7 +14936,7 @@ typescript-json-schema@0.56.0: typescript "~4.9.5" yargs "^17.1.1" -typescript@6.0.2, typescript@^5, typescript@^6.0.0, typescript@~4.9.5: +typescript@6.0.2, typescript@^5, typescript@^5.9.3, typescript@^6.0.0, typescript@~4.9.5: version "6.0.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-6.0.2.tgz#0b1bfb15f68c64b97032f3d78abbf98bdbba501f" integrity sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ== @@ -15211,6 +15447,20 @@ vite-tsconfig-paths@6.1.1: globrex "^0.1.2" tsconfck "^3.0.3" +"vite@^6.0.0 || ^7.0.0": + version "7.3.2" + resolved "https://registry.yarnpkg.com/vite/-/vite-7.3.2.tgz#cb041794d4c1395e28baea98198fd6e8f4b96b5c" + integrity sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg== + dependencies: + esbuild "^0.27.0" + fdir "^6.5.0" + picomatch "^4.0.3" + postcss "^8.5.6" + rollup "^4.43.0" + tinyglobby "^0.2.15" + optionalDependencies: + fsevents "~2.3.3" + "vite@^6.0.0 || ^7.0.0 || ^8.0.0", vite@^8.0.0: version "8.0.8" resolved "https://registry.yarnpkg.com/vite/-/vite-8.0.8.tgz#4e26a9bba77c4b27a00b6b10100a7dab48d546a3" @@ -15224,6 +15474,32 @@ vite-tsconfig-paths@6.1.1: optionalDependencies: fsevents "~2.3.3" +vitest@4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-4.0.4.tgz#92f8ed44110292c80efadc03bb6fa735ebefa414" + integrity sha512-hV31h0/bGbtmDQc0KqaxsTO1v4ZQeF8ojDFuy4sZhFadwAqqvJA0LDw68QUocctI5EDpFMql/jVWKuPYHIf2Ew== + dependencies: + "@vitest/expect" "4.0.4" + "@vitest/mocker" "4.0.4" + "@vitest/pretty-format" "4.0.4" + "@vitest/runner" "4.0.4" + "@vitest/snapshot" "4.0.4" + "@vitest/spy" "4.0.4" + "@vitest/utils" "4.0.4" + debug "^4.4.3" + es-module-lexer "^1.7.0" + expect-type "^1.2.2" + magic-string "^0.30.19" + pathe "^2.0.3" + picomatch "^4.0.3" + std-env "^3.9.0" + tinybench "^2.9.0" + tinyexec "^0.3.2" + tinyglobby "^0.2.15" + tinyrainbow "^3.0.3" + vite "^6.0.0 || ^7.0.0" + why-is-node-running "^2.3.0" + vitest@4.1.4: version "4.1.4" resolved "https://registry.yarnpkg.com/vitest/-/vitest-4.1.4.tgz#330a3798ce307f88d3eea373e61a5f14da8f3bb1" From 0d3cb0c7ced6f4586a5c5105f96385d6bb6235f0 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Tue, 20 Jan 2026 22:04:13 +1100 Subject: [PATCH 32/69] Various test, FIXMEs, config fixes (#10577) * Enable TS test * Add missing test for globalNamespace * Ensure dev-test-apollo-tooling is private --- dev-test-apollo-tooling/package.json | 1 + .../tests/ts-documents.standalone.spec.ts | 63 ++++++++++++++++++- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/dev-test-apollo-tooling/package.json b/dev-test-apollo-tooling/package.json index 164edd8d7cf..e0a5e49feee 100644 --- a/dev-test-apollo-tooling/package.json +++ b/dev-test-apollo-tooling/package.json @@ -1,5 +1,6 @@ { "name": "dev-test-apollo-tooling", + "private": true, "description": "A setup which mimics Apollo tooling generation as close as possible", "version": "0.0.1", "type": "module", diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts index 86ade3e739a..815347e89e8 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -187,8 +187,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { " `); - // FIXME: enable this to ensure type correctness - // validateTs(content, undefined, undefined, undefined, undefined, true); + validateTs(result, undefined, undefined, undefined, undefined, true); }); it('test generating input types enums in lists and inner field', async () => { @@ -849,4 +848,64 @@ describe('TypeScript Operations Plugin - Standalone', () => { validateTs(result, undefined, undefined, undefined, undefined, true); }); + + it('generates correctly with `globalNamespace: true`', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + nickname: String + } + + "UserRole Description" + enum UserRole { + "UserRole ADMIN" + ADMIN + "UserRole CUSTOMER" + CUSTOMER + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User($id: ID!) { + user(id: $id) { + id + role + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], { globalNamespace: true }, { outputFile: '' })]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + + declare global { + /** UserRole Description */ + export type UserRole = + /** UserRole ADMIN */ + | 'ADMIN' + /** UserRole CUSTOMER */ + | 'CUSTOMER'; + + export type UserQueryVariables = Exact<{ + id: string; + }>; + + + export type UserQuery = { user: { id: string, role: UserRole } | null }; + + }" + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); }); From 55fcdab02e87be2569a195d2bba6a753a42aa02b Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Wed, 21 Jan 2026 22:04:37 +1100 Subject: [PATCH 33/69] [typescript-operations] Cut down `avoidOptionals` to only support `object`, `inputValue` and `defaultValue` (+ minor drive-by fixes) (#10579) * Trim down avoidOptionals for client use case * Add changeset * Correctly ignore dev-test from changeset --- .changeset/config.json | 1 + .changeset/wise-poets-float.md | 6 +++ dev-test/gql-tag-operations/gql/graphql.ts | 4 +- .../gql-tag-operations/graphql/graphql.ts | 4 +- .../_types.generated.ts | 4 +- .../operations/src/config.avoidOptionals.ts | 33 ++++++++++++++ .../typescript/operations/src/config.ts | 45 ++++++++----------- .../src/ts-operation-variables-to-object.ts | 2 +- .../typescript/operations/src/visitor.ts | 16 ++++--- 9 files changed, 78 insertions(+), 37 deletions(-) create mode 100644 .changeset/wise-poets-float.md create mode 100644 packages/plugins/typescript/operations/src/config.avoidOptionals.ts diff --git a/.changeset/config.json b/.changeset/config.json index abf430e6f9e..b2f1f7d26bd 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -8,6 +8,7 @@ "ignore": [ "website", "example-*", + "dev-test*", "@graphql-codegen/client-preset-swc-plugin", "example-apollo-client-swc-plugin", "example-react-nextjs-swr" diff --git a/.changeset/wise-poets-float.md b/.changeset/wise-poets-float.md new file mode 100644 index 00000000000..9fb2acb4d2a --- /dev/null +++ b/.changeset/wise-poets-float.md @@ -0,0 +1,6 @@ +--- +'@graphql-codegen/typescript-operations': major +'@graphql-codegen/client-preset': major +--- + +BREAKING CHANGE: config.avoidOptionals now only supports object, inputValue, defaultValue diff --git a/dev-test/gql-tag-operations/gql/graphql.ts b/dev-test/gql-tag-operations/gql/graphql.ts index 700a96ddbee..bfeab7f1e4f 100644 --- a/dev-test/gql-tag-operations/gql/graphql.ts +++ b/dev-test/gql-tag-operations/gql/graphql.ts @@ -9,7 +9,9 @@ export type FooQueryVariables = Exact<{ [key: string]: never }>; export type FooQuery = { Tweets: Array<{ id: string } | null> | null }; -export type LelFragment = { id: string; body: string | null; date: unknown } & { ' $fragmentName'?: 'LelFragment' }; +export type LelFragment = { id: string; body: string | null; date: unknown } & { + ' $fragmentName'?: 'LelFragment'; +}; export type BarQueryVariables = Exact<{ [key: string]: never }>; diff --git a/dev-test/gql-tag-operations/graphql/graphql.ts b/dev-test/gql-tag-operations/graphql/graphql.ts index 700a96ddbee..bfeab7f1e4f 100644 --- a/dev-test/gql-tag-operations/graphql/graphql.ts +++ b/dev-test/gql-tag-operations/graphql/graphql.ts @@ -9,7 +9,9 @@ export type FooQueryVariables = Exact<{ [key: string]: never }>; export type FooQuery = { Tweets: Array<{ id: string } | null> | null }; -export type LelFragment = { id: string; body: string | null; date: unknown } & { ' $fragmentName'?: 'LelFragment' }; +export type LelFragment = { id: string; body: string | null; date: unknown } & { + ' $fragmentName'?: 'LelFragment'; +}; export type BarQueryVariables = Exact<{ [key: string]: never }>; diff --git a/dev-test/standalone-operations/with-typescript-plugin/_types.generated.ts b/dev-test/standalone-operations/with-typescript-plugin/_types.generated.ts index 6a222027557..954a5cffd3b 100644 --- a/dev-test/standalone-operations/with-typescript-plugin/_types.generated.ts +++ b/dev-test/standalone-operations/with-typescript-plugin/_types.generated.ts @@ -1,7 +1,9 @@ import type * as Types from './_base.generated.js'; type Exact = { [K in keyof T]: T[K] }; -export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +export type Incremental = + | T + | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type WithVariablesQueryVariables = Exact<{ role?: Types.UserRole | null | undefined; }>; diff --git a/packages/plugins/typescript/operations/src/config.avoidOptionals.ts b/packages/plugins/typescript/operations/src/config.avoidOptionals.ts new file mode 100644 index 00000000000..f8c921841fe --- /dev/null +++ b/packages/plugins/typescript/operations/src/config.avoidOptionals.ts @@ -0,0 +1,33 @@ +/** + * This version of AvoidOptionalsConfig is a cut down version of the type of the same name in `@graphql-codegen/visitor-plugins-common` + * This version only deal with types available in client use cases. + */ +export interface AvoidOptionalsConfig { + object?: boolean; + inputValue?: boolean; + defaultValue?: boolean; +} +export type NormalizedAvoidOptionalsConfig = Required; + +export const normalizeAvoidOptionals = ( + avoidOptionals?: boolean | AvoidOptionalsConfig +): NormalizedAvoidOptionalsConfig => { + const defaultAvoidOptionals: NormalizedAvoidOptionalsConfig = { + object: false, + inputValue: false, + defaultValue: false, + }; + + if (typeof avoidOptionals === 'boolean') { + return { + object: avoidOptionals, + inputValue: avoidOptionals, + defaultValue: avoidOptionals, + }; + } + + return { + ...defaultAvoidOptionals, + ...avoidOptionals, + }; +}; diff --git a/packages/plugins/typescript/operations/src/config.ts b/packages/plugins/typescript/operations/src/config.ts index b7f3edb545b..968bea303e8 100644 --- a/packages/plugins/typescript/operations/src/config.ts +++ b/packages/plugins/typescript/operations/src/config.ts @@ -1,15 +1,13 @@ import { - AvoidOptionalsConfig, type ConvertSchemaEnumToDeclarationBlockString, type EnumValuesMap, RawDocumentsConfig, } from '@graphql-codegen/visitor-plugin-common'; +import type { AvoidOptionalsConfig } from './config.avoidOptionals'; /** * @description This plugin generates TypeScript types based on your GraphQLSchema _and_ your GraphQL operations and fragments. * It generates types for your GraphQL documents: Query, Mutation, Subscription and Fragment. - * - * Note: In most configurations, this plugin requires you to use `typescript as well, because it depends on its base types. */ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { /** @@ -28,7 +26,7 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { * // ... * generates: { * 'path/to/file.ts': { - * plugins: ['typescript'], + * plugins: ['typescript-operations'], * config: { * arrayInputCoercion: false * }, @@ -55,7 +53,7 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { * // ... * generates: { * 'path/to/file.ts': { - * plugins: ['typescript'], + * plugins: ['typescript-operations'], * config: { * avoidOptionals: true * }, @@ -74,13 +72,12 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { * // ... * generates: { * 'path/to/file.ts': { - * plugins: ['typescript'], + * plugins: ['typescript-operations'], * config: { * avoidOptionals: { - * field: true - * inputValue: true - * object: true - * defaultValue: true + * inputValue: true, + * object: true, + * defaultValue: true, * } * }, * }, @@ -102,7 +99,7 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { * // ... * generates: { * 'path/to/file.ts': { - * plugins: ['typescript'], + * plugins: ['typescript-operations'], * config: { * immutableTypes: true * }, @@ -125,7 +122,7 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { * // ... * generates: { * 'path/to/file.ts': { - * plugins: ['typescript', 'typescript-operations'], + * plugins: ['typescript-operations'], * config: { * flattenGeneratedTypes: true * }, @@ -149,7 +146,7 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { * // ... * generates: { * 'path/to/file.ts': { - * plugins: ['typescript', 'typescript-operations'], + * plugins: ['typescript-operations'], * config: { * flattenGeneratedTypes: true, * flattenGeneratedTypesIncludeFragments: true @@ -175,7 +172,7 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { * // ... * generates: { * 'path/to/file.ts': { - * plugins: ['typescript'], + * plugins: ['typescript-operations'], * config: { * noExport: true * }, @@ -206,23 +203,19 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { * const config: CodegenConfig = { * // ... * generates: { - * "./typings/api.ts": { - * "plugins": [ - * "typescript" - * ] - * }, - * "./": { + * "./": { * "preset": "near-operation-file", * "presetConfig": { - * "baseTypesPath": "./typings/api.ts", - * "extension": ".gql.d.ts" + * "baseTypesPath": "./typings/api.ts", + * "extension": ".gql.d.ts" * }, * "plugins": [ - * "@graphql-codegen/typescript-operations" + * "typescript-operations" * ], * "config": { - * "addOperationExport": true + * "addOperationExport": true * } + * } * } * }; * export default config; @@ -298,7 +291,7 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { * // ... * generates: { * 'path/to/file.ts': { - * plugins: ['typescript'], + * plugins: ['typescript-operations'], * config: { * allowUndefinedQueryVariables: true * }, @@ -339,7 +332,7 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { * // ... * generates: { * 'path/to/file.ts': { - * plugins: ['typescript', 'typescript-operations'], + * plugins: ['typescript-operations'], * config: { * nullability: { * errorHandlingClient: true diff --git a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts index 8d469c69cca..3cc53eeb19e 100644 --- a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts +++ b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts @@ -1,12 +1,12 @@ import { Kind, TypeNode } from 'graphql'; import { ConvertNameFn, - NormalizedAvoidOptionalsConfig, NormalizedScalarsMap, OperationVariablesToObject, ParsedEnumValuesMap, printTypeScriptMaybeType, } from '@graphql-codegen/visitor-plugin-common'; +import type { NormalizedAvoidOptionalsConfig } from './config.avoidOptionals'; export const SCALARS = { ID: 'string | number', diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index b8162b5fce1..6b2257cd39e 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -34,8 +34,6 @@ import { isNativeNamedType, isOneOfInputObjectType, LoadedFragment, - normalizeAvoidOptionals, - NormalizedAvoidOptionalsConfig, ParsedDocumentsConfig, parseEnumValues, PreResolveTypesProcessor, @@ -46,7 +44,11 @@ import { type ConvertSchemaEnumToDeclarationBlockString, type ParsedEnumValuesMap, } from '@graphql-codegen/visitor-plugin-common'; -import { TypeScriptDocumentsPluginConfig } from './config.js'; +import { + normalizeAvoidOptionals, + NormalizedAvoidOptionalsConfig, +} from './config.avoidOptionals.js'; +import type { TypeScriptDocumentsPluginConfig } from './config.js'; import { SCALARS, TypeScriptOperationVariablesToObject, @@ -137,7 +139,10 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< ], }; - this._usedNamedInputTypes = this.collectUsedInputTypes({ schema, documentNode: documentWithAllFragments }); + this._usedNamedInputTypes = this.collectUsedInputTypes({ + schema, + documentNode: documentWithAllFragments, + }); const processorConfig: SelectionSetProcessorConfig = { namespacedImportName: this.config.namespacedImportName, @@ -182,9 +187,6 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< this.setVariablesTransformer( new TypeScriptOperationVariablesToObject( { - // FIXME: this is the legacy avoidOptionals which was used to make Result fields non-optional. This use case is no longer valid. - // It's also being used for Variables so people could already be using it. - // Maybe it's better to deprecate and remove, to see what users think. avoidOptionals: this.config.avoidOptionals, immutableTypes: this.config.immutableTypes, inputMaybeValue: this.config.inputMaybeValue, From e9c5b9e88de3547216856c07107327c9a9d81a39 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Fri, 23 Jan 2026 01:53:24 +1100 Subject: [PATCH 34/69] [typescript-operations] Rename `avoidOptionals.object` to `avoidOptionals.variableValue` to better reflect the target (#10582) * Rename avoidOptionals.object -> avoidOptionals.variableValue to better reflect the target. Add tests. * Add default input use cases --- .changeset/yellow-cups-crash.md | 5 + .../operations/src/config.avoidOptionals.ts | 8 +- .../typescript/operations/src/config.ts | 2 +- .../src/ts-operation-variables-to-object.ts | 4 +- ...s.standalone.config.avoidOptionals.spec.ts | 458 ++++++++++++++++++ 5 files changed, 470 insertions(+), 7 deletions(-) create mode 100644 .changeset/yellow-cups-crash.md create mode 100644 packages/plugins/typescript/operations/tests/ts-documents.standalone.config.avoidOptionals.spec.ts diff --git a/.changeset/yellow-cups-crash.md b/.changeset/yellow-cups-crash.md new file mode 100644 index 00000000000..0aa8b16743f --- /dev/null +++ b/.changeset/yellow-cups-crash.md @@ -0,0 +1,5 @@ +--- +'@graphql-codegen/typescript-operations': major +--- + +BREAKING CHANGE: rename avoidOptionals.object to avoidOptionals.variableValue diff --git a/packages/plugins/typescript/operations/src/config.avoidOptionals.ts b/packages/plugins/typescript/operations/src/config.avoidOptionals.ts index f8c921841fe..256c85c7a55 100644 --- a/packages/plugins/typescript/operations/src/config.avoidOptionals.ts +++ b/packages/plugins/typescript/operations/src/config.avoidOptionals.ts @@ -1,9 +1,9 @@ /** - * This version of AvoidOptionalsConfig is a cut down version of the type of the same name in `@graphql-codegen/visitor-plugins-common` + * This version of AvoidOptionalsConfig is an alternative and cut down version of the type of the same name in `@graphql-codegen/visitor-plugins-common` * This version only deal with types available in client use cases. */ export interface AvoidOptionalsConfig { - object?: boolean; + variableValue?: boolean; inputValue?: boolean; defaultValue?: boolean; } @@ -13,14 +13,14 @@ export const normalizeAvoidOptionals = ( avoidOptionals?: boolean | AvoidOptionalsConfig ): NormalizedAvoidOptionalsConfig => { const defaultAvoidOptionals: NormalizedAvoidOptionalsConfig = { - object: false, + variableValue: false, inputValue: false, defaultValue: false, }; if (typeof avoidOptionals === 'boolean') { return { - object: avoidOptionals, + variableValue: avoidOptionals, inputValue: avoidOptionals, defaultValue: avoidOptionals, }; diff --git a/packages/plugins/typescript/operations/src/config.ts b/packages/plugins/typescript/operations/src/config.ts index 968bea303e8..b792a6973c1 100644 --- a/packages/plugins/typescript/operations/src/config.ts +++ b/packages/plugins/typescript/operations/src/config.ts @@ -75,8 +75,8 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { * plugins: ['typescript-operations'], * config: { * avoidOptionals: { + * variableValue: true, * inputValue: true, - * object: true, * defaultValue: true, * } * }, diff --git a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts index 3cc53eeb19e..bea9ac89877 100644 --- a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts +++ b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts @@ -74,8 +74,8 @@ export class TypeScriptOperationVariablesToObject extends OperationVariablesToOb protected getAvoidOption(isNonNullType: boolean, hasDefaultValue: boolean): boolean { const options = this._config.avoidOptionals; return ( - ((options.object || !options.defaultValue) && hasDefaultValue) || - (!options.object && !isNonNullType) + ((options.variableValue || !options.defaultValue) && hasDefaultValue) || + (!options.variableValue && !isNonNullType) ); } diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.avoidOptionals.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.avoidOptionals.spec.ts new file mode 100644 index 00000000000..a41d8e9cc04 --- /dev/null +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.avoidOptionals.spec.ts @@ -0,0 +1,458 @@ +import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; +import { validateTs } from '@graphql-codegen/testing'; +import { buildSchema, parse } from 'graphql'; +import { plugin } from '../src/index.js'; + +describe('TypeScript Operations Plugin - config.avoidOptionals', () => { + it('generates optional for nullable Variables and Input by default', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(input: UserInput): User + } + + input UserInput { + id: ID! + id2: ID! = "default-id" + legacyId: ID + legacyId2: ID = "default-legacy-id" + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + nickname: String + } + + "UserRole Description" + enum UserRole { + "UserRole ADMIN" + ADMIN + "UserRole CUSTOMER" + CUSTOMER + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User($testNullable: ID, $testNonNullable: ID!, $inputNullable: UserInput, $inputNonNullable: UserInput!) { + user(input: $input) { + id + name + nickname + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], {}, { outputFile: '' })]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserInput = { + id: string | number; + id2?: string | number; + legacyId?: string | number | null | undefined; + legacyId2?: string | number | null | undefined; + }; + + export type UserQueryVariables = Exact<{ + testNullable?: string | null | undefined; + testNonNullable: string; + inputNullable?: UserInput | null | undefined; + inputNonNullable: UserInput; + }>; + + + export type UserQuery = { user: { id: string, name: string, nickname: string | null } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('generates non-optional Variables and Input when `avoidOptionals:true`', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(input: UserInput): User + } + + input UserInput { + id: ID! + id2: ID! = "default-id" + legacyId: ID + legacyId2: ID = "default-legacy-id" + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + nickname: String + } + + "UserRole Description" + enum UserRole { + "UserRole ADMIN" + ADMIN + "UserRole CUSTOMER" + CUSTOMER + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User($testNullable: ID, $testNonNullable: ID!, $inputNullable: UserInput, $inputNonNullable: UserInput!) { + user(input: $input) { + id + name + nickname + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], { avoidOptionals: true }, { outputFile: '' })]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserInput = { + id: string | number; + id2: string | number; + legacyId: string | number | null | undefined; + legacyId2: string | number | null | undefined; + }; + + export type UserQueryVariables = Exact<{ + testNullable: string | null | undefined; + testNonNullable: string; + inputNullable: UserInput | null | undefined; + inputNonNullable: UserInput; + }>; + + + export type UserQuery = { user: { id: string, name: string, nickname: string | null } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('generates non-optional Input when `avoidOptionals.inputValue:true`', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(input: UserInput): User + } + + input UserInput { + id: ID! + id2: ID! = "default-id" + legacyId: ID + legacyId2: ID = "default-legacy-id" + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + nickname: String + } + + "UserRole Description" + enum UserRole { + "UserRole ADMIN" + ADMIN + "UserRole CUSTOMER" + CUSTOMER + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User($test: ID, $input: UserInput) { + user { + id + name + nickname + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + avoidOptionals: { + inputValue: true, + }, + }, + { outputFile: '' } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserInput = { + id: string | number; + id2: string | number; + legacyId: string | number | null | undefined; + legacyId2: string | number | null | undefined; + }; + + export type UserQueryVariables = Exact<{ + test?: string | null | undefined; + input?: UserInput | null | undefined; + }>; + + + export type UserQuery = { user: { id: string, name: string, nickname: string | null } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('generates non-optional Input with defaults when `avoidOptionals.defaultValue:true`', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(input: UserInput): User + } + + input UserInput { + id: ID! + id2: ID! = "default-id" + legacyId: ID + legacyId2: ID = "default-legacy-id" + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + nickname: String + } + + "UserRole Description" + enum UserRole { + "UserRole ADMIN" + ADMIN + "UserRole CUSTOMER" + CUSTOMER + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User($test: ID, $input: UserInput) { + user { + id + name + nickname + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + avoidOptionals: { + defaultValue: true, + }, + }, + { outputFile: '' } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserInput = { + id: string | number; + id2: string | number; + legacyId?: string | number | null | undefined; + legacyId2?: string | number | null | undefined; + }; + + export type UserQueryVariables = Exact<{ + test?: string | null | undefined; + input?: UserInput | null | undefined; + }>; + + + export type UserQuery = { user: { id: string, name: string, nickname: string | null } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('generates non-optional Variable when `avoidOptionals.variableValue:true`', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(input: UserInput): User + } + + input UserInput { + id: ID! + id2: ID! = "default-id" + legacyId: ID + legacyId2: ID = "default-legacy-id" + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + nickname: String + } + + "UserRole Description" + enum UserRole { + "UserRole ADMIN" + ADMIN + "UserRole CUSTOMER" + CUSTOMER + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User($test: ID, $input: UserInput) { + user { + id + name + nickname + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + avoidOptionals: { + variableValue: true, + }, + }, + { outputFile: '' } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserInput = { + id: string | number; + id2?: string | number; + legacyId?: string | number | null | undefined; + legacyId2?: string | number | null | undefined; + }; + + export type UserQueryVariables = Exact<{ + test: string | null | undefined; + input: UserInput | null | undefined; + }>; + + + export type UserQuery = { user: { id: string, name: string, nickname: string | null } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('generates optional Variable if there is a default value when `avoidOptionals.variableValue:true` and `avoidOptionals.defaultValue:false`', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(input: UserInput): User + } + + input UserInput { + id: ID! + id2: ID! = "default-id" + legacyId: ID + legacyId2: ID = "default-legacy-id" + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + nickname: String + } + + "UserRole Description" + enum UserRole { + "UserRole ADMIN" + ADMIN + "UserRole CUSTOMER" + CUSTOMER + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User( + $test: ID # This does not have a default, so it will be non-optional (given the config) + $testWithDefault: ID = "100" # This has a default, so it will be optional (given the config) + $input: UserInput # This does not have a default, so it will be non-optional (given the config) + $inputWithDefault: UserInput = { id: "200" } # This has a default, so it will be optional (given the config) + ) { + user { + id + name + nickname + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + avoidOptionals: { + variableValue: true, + defaultValue: false, + }, + }, + { outputFile: '' } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserInput = { + id: string | number; + id2?: string | number; + legacyId?: string | number | null | undefined; + legacyId2?: string | number | null | undefined; + }; + + export type UserQueryVariables = Exact<{ + test: string | null | undefined; + testWithDefault?: string | null | undefined; + input: UserInput | null | undefined; + inputWithDefault?: UserInput | null | undefined; + }>; + + + export type UserQuery = { user: { id: string, name: string, nickname: string | null } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); +}); From 75fa4b45ea3327871df47ab25e44e045a190dd88 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Mon, 26 Jan 2026 01:01:14 +1100 Subject: [PATCH 35/69] [typescript-operations] Fix external custom scalars not getting imported (#10584) * Rename scalar test * Refactor to move position of getEnumsImports to group methods * Implement handling of external scalars * Add (wrong) import scalar tests to work against * Fix importing types wrongly count Scalar as part of types generated into shared type file * Do not generate scalar imports if not needed * Add changeset * Cleanup * Fix granularity of operation-file --- .changeset/proud-dingos-trade.md | 5 + .../typescript/operations/src/index.ts | 1 + .../typescript/operations/src/visitor.ts | 223 +++++- ...ts.standalone.default-scalar-types.spec.ts | 283 ------- ...-documents.standalone.import-types.spec.ts | 221 ++++++ .../ts-documents.standalone.scalars.spec.ts | 695 ++++++++++++++++++ 6 files changed, 1118 insertions(+), 310 deletions(-) create mode 100644 .changeset/proud-dingos-trade.md delete mode 100644 packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts create mode 100644 packages/plugins/typescript/operations/tests/ts-documents.standalone.scalars.spec.ts diff --git a/.changeset/proud-dingos-trade.md b/.changeset/proud-dingos-trade.md new file mode 100644 index 00000000000..22576b3959f --- /dev/null +++ b/.changeset/proud-dingos-trade.md @@ -0,0 +1,5 @@ +--- +'@graphql-codegen/typescript-operations': patch +--- + +Fix external custom scalars not getting imported diff --git a/packages/plugins/typescript/operations/src/index.ts b/packages/plugins/typescript/operations/src/index.ts index 7ac24ee1054..2a3da5d0802 100644 --- a/packages/plugins/typescript/operations/src/index.ts +++ b/packages/plugins/typescript/operations/src/index.ts @@ -95,6 +95,7 @@ export const plugin: PluginFunction< ...visitor.getImports(), ...visitor.getExternalSchemaTypeImports(), ...visitor.getEnumsImports(), + ...visitor.getScalarsImports(), ...visitor.getGlobalDeclarations(visitor.config.noExport), visitor.getExactUtilityType(), visitor.getIncrementalUtilityType(), diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 6b2257cd39e..7c2dfc96c27 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -22,6 +22,7 @@ import { import { normalizeImportExtension } from '@graphql-codegen/plugin-helpers'; import { BaseDocumentsVisitor, + buildTypeImport, convertSchemaEnumToDeclarationBlockString, DeclarationBlock, DeclarationKind, @@ -70,7 +71,12 @@ export interface TypeScriptDocumentsParsedConfig extends ParsedDocumentsConfig { type UsedNamedInputTypes = Record< string, - | { type: 'GraphQLScalarType'; node: GraphQLScalarType; tsType: string } + | { + type: 'GraphQLScalarType'; + node: GraphQLScalarType; + tsType: string; + useCases: { input: boolean; output: boolean; variables: boolean }; + } | { type: 'GraphQLEnumType'; node: GraphQLEnumType; tsType: string } | { type: 'GraphQLInputObjectType'; node: GraphQLInputObjectType; tsType: string } >; @@ -400,7 +406,10 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< return []; } - const hasTypesToImport = Object.keys(this._usedNamedInputTypes).length > 0; + const hasTypesToImport = + Object.values(this._usedNamedInputTypes).filter( + value => value.type === 'GraphQLEnumType' || value.type === 'GraphQLInputObjectType', // Only Enums and Inputs are stored in the shared type file (never Scalar), so we should only print import line if Enums and Inputs are used. + ).length > 0; if (!hasTypesToImport) { return []; @@ -426,6 +435,111 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< ]; } + public getEnumsImports(): string[] { + const usedEnumMap: ParsedEnumValuesMap = {}; + for (const [enumName, enumDetails] of Object.entries(this.config.enumValues)) { + if (this._usedNamedInputTypes[enumName]) { + usedEnumMap[enumName] = enumDetails; + } + } + + return getEnumsImports({ + enumValues: usedEnumMap, + useTypeImports: this.config.useTypeImports, + }); + } + + public getScalarsImports(): string[] { + const fileType: + | 'multi-file-shared-type-file' + | 'multi-file-operation-file' + | 'single-file-operation-file' = this.config.importSchemaTypesFrom + ? 'multi-file-operation-file' + : this.config.generatesOperationTypes + ? 'single-file-operation-file' + : 'multi-file-shared-type-file'; + + const imports: { + [ + source: string + ]: // `source` is where to import from e.g. './relative-import', 'package-import', '@org/package' + { + identifiers: { + [ + identifier: string + ]: // `identifier` is the name of import, this could be used for named or default imports + { asDefault: boolean }; + }; + }; + } = {}; + for (const [scalarName, parsedScalar] of Object.entries(this.config.scalars)) { + const usedScalar = this._usedNamedInputTypes[scalarName]; + if (!usedScalar || usedScalar.type !== 'GraphQLScalarType') { + continue; + } + + if ( + parsedScalar.input.isExternal && + (((usedScalar.useCases.input || usedScalar.useCases.variables) && + fileType === 'single-file-operation-file') || + (usedScalar.useCases.input && fileType === 'multi-file-shared-type-file') || + (usedScalar.useCases.variables && fileType === 'multi-file-operation-file')) + ) { + imports[parsedScalar.input.source] ||= { identifiers: {} }; + imports[parsedScalar.input.source].identifiers[parsedScalar.input.import] = { + asDefault: parsedScalar.input.default, + }; + } + + if ( + parsedScalar.output.isExternal && + usedScalar.useCases.output && + (fileType === 'single-file-operation-file' || fileType === 'multi-file-operation-file') + ) { + imports[parsedScalar.output.source] ||= { identifiers: {} }; + imports[parsedScalar.output.source].identifiers[parsedScalar.output.import] = { + asDefault: parsedScalar.output.default, + }; + } + } + + return Object.entries(imports).reduce((res, [importSource, importParams]) => { + // One import statement cannot have multiple defaults. + // So: + // - split each defaults into its own statements + // - the named imports can all go together, tracked by `namedImports` + const namedImports = []; + for (const [identifier, identifierMetadata] of Object.entries(importParams.identifiers)) { + if (identifierMetadata.asDefault) { + res.push( + buildTypeImport({ + identifier, + source: importSource, + asDefault: true, + useTypeImports: this.config.useTypeImports, + }), + ); + continue; + } + + namedImports.push(identifier); + } + + if (namedImports.length > 0) { + res.push( + buildTypeImport({ + identifier: namedImports.join(', '), + source: importSource, + asDefault: false, + useTypeImports: this.config.useTypeImports, + }), + ); + } + + return res; + }, []); + } + protected getPunctuation(_declarationKind: DeclarationKind): string { return ';'; } @@ -437,15 +551,20 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< return `Exact<${variablesBlock === '{}' ? `{ [key: string]: never; }` : variablesBlock}>${extraType}`; } - private collectInnerTypesRecursively( - node: GraphQLNamedInputType, - usedInputTypes: UsedNamedInputTypes, - ): void { - if (usedInputTypes[node.name]) { - return; - } - + private collectInnerTypesRecursively({ + node, + usedInputTypes, + location, + }: { + node: GraphQLNamedInputType; + usedInputTypes: UsedNamedInputTypes; + location: 'variables' | 'input'; // the location where the node was found. This is useful for nested input. Note: Since it starts at the variable, it first iteration is 'variables' and the rest will be `input` + }): void { if (node instanceof GraphQLEnumType) { + if (usedInputTypes[node.name]) { + return; + } + usedInputTypes[node.name] = { type: 'GraphQLEnumType', node, @@ -455,15 +574,40 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< } if (node instanceof GraphQLScalarType) { - usedInputTypes[node.name] = { + const scalarType = usedInputTypes[node.name] || { type: 'GraphQLScalarType', node, tsType: (SCALARS[node.name] || this.config.scalars?.[node.name]?.input.type) ?? 'unknown', + useCases: { + variables: location === 'variables', + input: location === 'input', + output: false, + }, }; + + if (scalarType.type !== 'GraphQLScalarType') { + throw new Error( + `${node.name} has been incorrectly parsed as Scalar. This should not happen.`, + ); + } + + // ensure scalar's useCases is updated to have `useCases.input:true` or `useCases.variables:true`, depending on the use case + // this is required because if the scalar has been parsed previously, it may only have `useCases.output:true`, and not `useCases.input:true` or `useCases.variables:true` + if (location === 'input') { + scalarType.useCases.input = true; + } + if (location === 'variables') { + scalarType.useCases.variables = true; + } + + usedInputTypes[node.name] = scalarType; return; } // GraphQLInputObjectType + if (usedInputTypes[node.name]) { + return; + } usedInputTypes[node.name] = { type: 'GraphQLInputObjectType', node, @@ -473,10 +617,23 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< const fields = node.getFields(); for (const field of Object.values(fields)) { const fieldType = getNamedType(field.type); - this.collectInnerTypesRecursively(fieldType, usedInputTypes); + this.collectInnerTypesRecursively({ + node: fieldType, + usedInputTypes, + location: 'input', + }); } } + /** + * FIXME: This function is called `collectUsedInputTypes`, but it collects the types used in Result (SelectionSet) as well: + * - used Enums for Variables + * - used Scalars for Variables + * - used Input for Variables + * + * - used Enums for Result + * - used Scalars for Result + */ private collectUsedInputTypes({ schema, documentNode, @@ -501,7 +658,11 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< foundInputType instanceof GraphQLEnumType) && !isNativeNamedType(foundInputType) ) { - this.collectInnerTypesRecursively(foundInputType, usedInputTypes); + this.collectInnerTypesRecursively({ + node: foundInputType, + usedInputTypes, + location: 'variables', + }); } }, }); @@ -527,6 +688,28 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< node: namedType, tsType: this.convertName(namedType.name), }; + return; + } + + if (namedType instanceof GraphQLScalarType) { + const scalarType = usedInputTypes[namedType.name] || { + type: 'GraphQLScalarType', + node: namedType, + tsType: this.convertName(namedType.name), + useCases: { variables: false, input: false, output: true }, + }; + + if (scalarType.type !== 'GraphQLScalarType') { + throw new Error( + `${namedType.name} has been incorrectly parsed as Scalar. This should not happen.`, + ); + } + + // ensure scalar's useCases is updated to have `useCases.output:true` + // this is required because if the scalar has been parsed previously, it may only have `useCases.input:true` or `useCases.variables:true`, not `useCases.output:true` + scalarType.useCases.output = true; + + usedInputTypes[namedType.name] = scalarType; } } }, @@ -536,20 +719,6 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< return usedInputTypes; } - public getEnumsImports(): string[] { - const usedEnumMap: ParsedEnumValuesMap = {}; - for (const [enumName, enumDetails] of Object.entries(this.config.enumValues)) { - if (this._usedNamedInputTypes[enumName]) { - usedEnumMap[enumName] = enumDetails; - } - } - - return getEnumsImports({ - enumValues: usedEnumMap, - useTypeImports: this.config.useTypeImports, - }); - } - getExactUtilityType(): string | null { if ( !this.config.generatesOperationTypes || // 1. If we don't generate operation types, definitely do not need `Exact` diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts deleted file mode 100644 index 057605180e6..00000000000 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.default-scalar-types.spec.ts +++ /dev/null @@ -1,283 +0,0 @@ -import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; -import { validateTs } from '@graphql-codegen/testing'; -import { buildSchema, parse } from 'graphql'; -import { plugin } from '../src/index.js'; - -describe('TypeScript Operations Plugin - Default Scalar types', () => { - it('generates `unknown` as the default custom defaultScalarType', async () => { - const schema = buildSchema(/* GraphQL */ ` - type Query { - user( - id: ID! - nonNullableDate: DateTime! - nullableDate: DateTime - dateArray1: [DateTime] - dateArray2: [DateTime]! - dateArray3: [DateTime!] - dateArray4: [DateTime!]! - input: UserInput! - ): User - } - - input UserInput { - nonNullableDate: DateTime! - nullableDate: DateTime - dateArray1: [DateTime] - dateArray2: [DateTime]! - dateArray3: [DateTime!] - dateArray4: [DateTime!]! - } - - type User { - id: ID! - nonNullableDate: DateTime! - nullableDate: DateTime - } - - scalar DateTime - `); - const document = parse(/* GraphQL */ ` - query User( - $nonNullableDate: DateTime! - $nullableDate: DateTime - $dateArray1: [DateTime] - $dateArray2: [DateTime]! - $dateArray3: [DateTime!] - $dateArray4: [DateTime!]! - $input: UserInput! - ) { - user( - id: "1" - nonNullableDate: $nonNullableDate - nullableDate: $nullableDate - dateArray1: $dateArray1 - dateArray2: $dateArray2 - dateArray3: $dateArray3 - dateArray4: $dateArray4 - input: $input - ) { - id - nonNullableDate - nullableDate - } - } - `); - - const result = mergeOutputs([await plugin(schema, [{ document }], {}, { outputFile: '' })]); - - expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - export type UserInput = { - nonNullableDate: unknown; - nullableDate?: unknown; - dateArray1?: Array | null | undefined; - dateArray2: Array; - dateArray3?: Array | null | undefined; - dateArray4: Array; - }; - - export type UserQueryVariables = Exact<{ - nonNullableDate: unknown; - nullableDate?: unknown; - dateArray1?: Array | unknown | null | undefined; - dateArray2: Array | unknown; - dateArray3?: Array | unknown | null | undefined; - dateArray4: Array | unknown; - input: UserInput; - }>; - - - export type UserQuery = { user: { id: string, nonNullableDate: unknown, nullableDate: unknown } | null }; - " - `); - - validateTs(result, undefined, undefined, undefined, undefined, true); - }); - - it("generates `any` when defaultScalarType:'any'", async () => { - const schema = buildSchema(/* GraphQL */ ` - type Query { - user( - id: ID! - nonNullableDate: DateTime! - nullableDate: DateTime - dateArray1: [DateTime] - dateArray2: [DateTime]! - dateArray3: [DateTime!] - dateArray4: [DateTime!]! - input: UserInput! - ): User - } - - input UserInput { - nonNullableDate: DateTime! - nullableDate: DateTime - dateArray1: [DateTime] - dateArray2: [DateTime]! - dateArray3: [DateTime!] - dateArray4: [DateTime!]! - } - - type User { - id: ID! - nonNullableDate: DateTime! - nullableDate: DateTime - } - - scalar DateTime - `); - const document = parse(/* GraphQL */ ` - query User( - $nonNullableDate: DateTime! - $nullableDate: DateTime - $dateArray1: [DateTime] - $dateArray2: [DateTime]! - $dateArray3: [DateTime!] - $dateArray4: [DateTime!]! - $input: UserInput! - ) { - user( - id: "1" - nonNullableDate: $nonNullableDate - nullableDate: $nullableDate - dateArray1: $dateArray1 - dateArray2: $dateArray2 - dateArray3: $dateArray3 - dateArray4: $dateArray4 - input: $input - ) { - id - nonNullableDate - nullableDate - } - } - `); - - const result = mergeOutputs([ - await plugin(schema, [{ document }], { defaultScalarType: 'any' }, { outputFile: '' }), - ]); - - expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - export type UserInput = { - nonNullableDate: any; - nullableDate?: any; - dateArray1?: Array | null | undefined; - dateArray2: Array; - dateArray3?: Array | null | undefined; - dateArray4: Array; - }; - - export type UserQueryVariables = Exact<{ - nonNullableDate: any; - nullableDate?: any; - dateArray1?: Array | any | null | undefined; - dateArray2: Array | any; - dateArray3?: Array | any | null | undefined; - dateArray4: Array | any; - input: UserInput; - }>; - - - export type UserQuery = { user: { id: string, nonNullableDate: any, nullableDate: any } | null }; - " - `); - - validateTs(result, undefined, undefined, undefined, undefined, true); - }); - - it('generates correct types when defaultScalarType is set to said types', async () => { - const schema = buildSchema(/* GraphQL */ ` - type Query { - user( - id: ID! - nonNullableDate: DateTime! - nullableDate: DateTime - dateArray1: [DateTime] - dateArray2: [DateTime]! - dateArray3: [DateTime!] - dateArray4: [DateTime!]! - input: UserInput! - ): User - } - - input UserInput { - nonNullableDate: DateTime! - nullableDate: DateTime - dateArray1: [DateTime] - dateArray2: [DateTime]! - dateArray3: [DateTime!] - dateArray4: [DateTime!]! - } - - type User { - id: ID! - nonNullableDate: DateTime! - nullableDate: DateTime - } - - scalar DateTime - `); - const document = parse(/* GraphQL */ ` - query User( - $nonNullableDate: DateTime! - $nullableDate: DateTime - $dateArray1: [DateTime] - $dateArray2: [DateTime]! - $dateArray3: [DateTime!] - $dateArray4: [DateTime!]! - $input: UserInput! - ) { - user( - id: "1" - nonNullableDate: $nonNullableDate - nullableDate: $nullableDate - dateArray1: $dateArray1 - dateArray2: $dateArray2 - dateArray3: $dateArray3 - dateArray4: $dateArray4 - input: $input - ) { - id - nonNullableDate - nullableDate - } - } - `); - - const result = mergeOutputs([ - await plugin(schema, [{ document }], { defaultScalarType: 'Date' }, { outputFile: '' }), - ]); - - expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - export type UserInput = { - nonNullableDate: Date; - nullableDate?: Date | null | undefined; - dateArray1?: Array | null | undefined; - dateArray2: Array; - dateArray3?: Array | null | undefined; - dateArray4: Array; - }; - - export type UserQueryVariables = Exact<{ - nonNullableDate: Date; - nullableDate?: Date | null | undefined; - dateArray1?: Array | Date | null | undefined; - dateArray2: Array | Date; - dateArray3?: Array | Date | null | undefined; - dateArray4: Array | Date; - input: UserInput; - }>; - - - export type UserQuery = { user: { id: string, nonNullableDate: Date, nullableDate: Date | null } | null }; - " - `); - - validateTs(result, undefined, undefined, undefined, undefined, true); - }); -}); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts index 20a634d0820..99e676025ae 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts @@ -372,3 +372,224 @@ describe('TypeScript Operations Plugin - Import Types', () => { validateTs(result, undefined, undefined, undefined, undefined, true); }); }); + +describe('TypeScript Operations Plugin - Import Types with external custom Scalars', () => { + it('imports external custom scalar in shared type file when said scalar is used in relevant Input', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(input: UserInput): User + } + + input UserInput { + id: ID! + scalar1: Scalar1 + } + + type User { + id: ID! + } + + scalar Scalar1 + `); + const document = parse(/* GraphQL */ ` + query User($input: UserInput) { + user(input: $input) { + id + } + } + `); + + const sharedTypeFileResult = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + generatesOperationTypes: false, + scalars: { + Scalar1: '@org/scalars#Scalar1', + }, + }, + { outputFile: '' } + ), + ]); + expect(sharedTypeFileResult).toMatchInlineSnapshot(` + "import { Scalar1 } from '@org/scalars'; + + + export type UserInput = { + id: string | number; + scalar1?: Scalar1 | null | undefined; + }; + " + `); + validateTs(sharedTypeFileResult, undefined, undefined, undefined, undefined, true); + + const operationFileResult = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + importSchemaTypesFrom: './path-to-other-file', + namespacedImportName: 'TypeImport', + scalars: { + Scalar1: '@org/scalars#Scalar1', + }, + }, + { outputFile: '' } + ), + ]); + expect(operationFileResult).toMatchInlineSnapshot(` + "import type * as TypeImport from './graphql-code-generator/path-to-other-file'; + + type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserQueryVariables = Exact<{ + input?: TypeImport.UserInput | null | undefined; + }>; + + + export type UserQuery = { user: { id: string } | null }; + " + `); + validateTs(operationFileResult, undefined, undefined, undefined, undefined, true); + }); + + it('imports external custom scalar in operation file when said scalar is used in Variables', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + } + + type User { + id: ID! + scalar1: Scalar1 + } + + scalar Scalar1 + `); + const document = parse(/* GraphQL */ ` + query User($scalar1: Scalar1) { + user(id: "100") { + id + } + } + `); + + const sharedTypeFileResult = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + generatesOperationTypes: false, + scalars: { + Scalar1: '@org/scalars#Scalar1', + }, + }, + { outputFile: '' } + ), + ]); + expect(sharedTypeFileResult).toMatchInlineSnapshot(` + " + + " + `); + validateTs(sharedTypeFileResult, undefined, undefined, undefined, undefined, true); + + const operationFileResult = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + importSchemaTypesFrom: './path-to-other-file', + namespacedImportName: 'TypeImport', + scalars: { + Scalar1: '@org/scalars#Scalar1', + }, + }, + { outputFile: '' } + ), + ]); + expect(operationFileResult).toMatchInlineSnapshot(` + "import { Scalar1 } from '@org/scalars'; + type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserQueryVariables = Exact<{ + scalar1?: Scalar1 | null | undefined; + }>; + + + export type UserQuery = { user: { id: string } | null }; + " + `); + validateTs(operationFileResult, undefined, undefined, undefined, undefined, true); + }); + + it('imports external custom scalar in operation file when said scalar is used in Result SelectionSet', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + } + + type User { + id: ID! + scalar1: Scalar1 + } + + scalar Scalar1 + `); + const document = parse(/* GraphQL */ ` + query User { + user(id: "100") { + id + scalar1 + } + } + `); + + const sharedTypeFileResult = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + generatesOperationTypes: false, + scalars: { + Scalar1: '@org/scalars#Scalar1', + }, + }, + { outputFile: '' } + ), + ]); + expect(sharedTypeFileResult).toMatchInlineSnapshot(` + " + + " + `); + validateTs(sharedTypeFileResult, undefined, undefined, undefined, undefined, true); + + const operationFileResult = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + importSchemaTypesFrom: './path-to-other-file', + namespacedImportName: 'TypeImport', + scalars: { + Scalar1: '@org/scalars#Scalar1', + }, + }, + { outputFile: '' } + ), + ]); + expect(operationFileResult).toMatchInlineSnapshot(` + "import { Scalar1 } from '@org/scalars'; + type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserQueryVariables = Exact<{ [key: string]: never; }>; + + + export type UserQuery = { user: { id: string, scalar1: Scalar1 | null } | null }; + " + `); + validateTs(operationFileResult, undefined, undefined, undefined, undefined, true); + }); +}); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.scalars.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.scalars.spec.ts new file mode 100644 index 00000000000..7dc053f4d13 --- /dev/null +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.scalars.spec.ts @@ -0,0 +1,695 @@ +import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; +import { validateTs } from '@graphql-codegen/testing'; +import { buildSchema, parse } from 'graphql'; +import { plugin } from '../src/index.js'; + +describe('TypeScript Operations Plugin - Default Scalar types', () => { + it('generates `unknown` as the default custom defaultScalarType', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user( + id: ID! + nonNullableDate: DateTime! + nullableDate: DateTime + dateArray1: [DateTime] + dateArray2: [DateTime]! + dateArray3: [DateTime!] + dateArray4: [DateTime!]! + input: UserInput! + ): User + } + + input UserInput { + nonNullableDate: DateTime! + nullableDate: DateTime + dateArray1: [DateTime] + dateArray2: [DateTime]! + dateArray3: [DateTime!] + dateArray4: [DateTime!]! + } + + type User { + id: ID! + nonNullableDate: DateTime! + nullableDate: DateTime + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User( + $nonNullableDate: DateTime! + $nullableDate: DateTime + $dateArray1: [DateTime] + $dateArray2: [DateTime]! + $dateArray3: [DateTime!] + $dateArray4: [DateTime!]! + $input: UserInput! + ) { + user( + id: "1" + nonNullableDate: $nonNullableDate + nullableDate: $nullableDate + dateArray1: $dateArray1 + dateArray2: $dateArray2 + dateArray3: $dateArray3 + dateArray4: $dateArray4 + input: $input + ) { + id + nonNullableDate + nullableDate + } + } + `); + + const result = mergeOutputs([await plugin(schema, [{ document }], {}, { outputFile: '' })]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserInput = { + nonNullableDate: unknown; + nullableDate?: unknown; + dateArray1?: Array | null | undefined; + dateArray2: Array; + dateArray3?: Array | null | undefined; + dateArray4: Array; + }; + + export type UserQueryVariables = Exact<{ + nonNullableDate: unknown; + nullableDate?: unknown; + dateArray1?: Array | unknown | null | undefined; + dateArray2: Array | unknown; + dateArray3?: Array | unknown | null | undefined; + dateArray4: Array | unknown; + input: UserInput; + }>; + + + export type UserQuery = { user: { id: string, nonNullableDate: unknown, nullableDate: unknown } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it("generates `any` when defaultScalarType:'any'", async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user( + id: ID! + nonNullableDate: DateTime! + nullableDate: DateTime + dateArray1: [DateTime] + dateArray2: [DateTime]! + dateArray3: [DateTime!] + dateArray4: [DateTime!]! + input: UserInput! + ): User + } + + input UserInput { + nonNullableDate: DateTime! + nullableDate: DateTime + dateArray1: [DateTime] + dateArray2: [DateTime]! + dateArray3: [DateTime!] + dateArray4: [DateTime!]! + } + + type User { + id: ID! + nonNullableDate: DateTime! + nullableDate: DateTime + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User( + $nonNullableDate: DateTime! + $nullableDate: DateTime + $dateArray1: [DateTime] + $dateArray2: [DateTime]! + $dateArray3: [DateTime!] + $dateArray4: [DateTime!]! + $input: UserInput! + ) { + user( + id: "1" + nonNullableDate: $nonNullableDate + nullableDate: $nullableDate + dateArray1: $dateArray1 + dateArray2: $dateArray2 + dateArray3: $dateArray3 + dateArray4: $dateArray4 + input: $input + ) { + id + nonNullableDate + nullableDate + } + } + `); + + const result = mergeOutputs([ + await plugin(schema, [{ document }], { defaultScalarType: 'any' }, { outputFile: '' }), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserInput = { + nonNullableDate: any; + nullableDate?: any; + dateArray1?: Array | null | undefined; + dateArray2: Array; + dateArray3?: Array | null | undefined; + dateArray4: Array; + }; + + export type UserQueryVariables = Exact<{ + nonNullableDate: any; + nullableDate?: any; + dateArray1?: Array | any | null | undefined; + dateArray2: Array | any; + dateArray3?: Array | any | null | undefined; + dateArray4: Array | any; + input: UserInput; + }>; + + + export type UserQuery = { user: { id: string, nonNullableDate: any, nullableDate: any } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('generates correct types when defaultScalarType is set to said types', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user( + id: ID! + nonNullableDate: DateTime! + nullableDate: DateTime + dateArray1: [DateTime] + dateArray2: [DateTime]! + dateArray3: [DateTime!] + dateArray4: [DateTime!]! + input: UserInput! + ): User + } + + input UserInput { + nonNullableDate: DateTime! + nullableDate: DateTime + dateArray1: [DateTime] + dateArray2: [DateTime]! + dateArray3: [DateTime!] + dateArray4: [DateTime!]! + } + + type User { + id: ID! + nonNullableDate: DateTime! + nullableDate: DateTime + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User( + $nonNullableDate: DateTime! + $nullableDate: DateTime + $dateArray1: [DateTime] + $dateArray2: [DateTime]! + $dateArray3: [DateTime!] + $dateArray4: [DateTime!]! + $input: UserInput! + ) { + user( + id: "1" + nonNullableDate: $nonNullableDate + nullableDate: $nullableDate + dateArray1: $dateArray1 + dateArray2: $dateArray2 + dateArray3: $dateArray3 + dateArray4: $dateArray4 + input: $input + ) { + id + nonNullableDate + nullableDate + } + } + `); + + const result = mergeOutputs([ + await plugin(schema, [{ document }], { defaultScalarType: 'Date' }, { outputFile: '' }), + ]); + + expect(result).toMatchInlineSnapshot(` + "type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserInput = { + nonNullableDate: Date; + nullableDate?: Date | null | undefined; + dateArray1?: Array | null | undefined; + dateArray2: Array; + dateArray3?: Array | null | undefined; + dateArray4: Array; + }; + + export type UserQueryVariables = Exact<{ + nonNullableDate: Date; + nullableDate?: Date | null | undefined; + dateArray1?: Array | Date | null | undefined; + dateArray2: Array | Date; + dateArray3?: Array | Date | null | undefined; + dateArray4: Array | Date; + input: UserInput; + }>; + + + export type UserQuery = { user: { id: string, nonNullableDate: Date, nullableDate: Date | null } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); +}); + +describe('TypeScript Operations Plugin - Custom Scalars', () => { + it('imports external custom scalar correctly when used in Result SelectionSet', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + } + + type User { + id: ID! + scalar1: Scalar1 + scalar2: Scalar2 + scalar3: Scalar3 + scalar4: Scalar4 + scalar5: Scalar5 + scalar6: Scalar6 + scalar7: Scalar7 + unusedScalar: UnusedScalar + } + + scalar Scalar1 + scalar Scalar2 + scalar Scalar3 + scalar Scalar4 + scalar Scalar5 + scalar Scalar6 + scalar Scalar7 + scalar UnusedScalar + `); + const document = parse(/* GraphQL */ ` + query User { + user(id: "1") { + id + scalar1 + scalar2 + scalar3 + scalar4 + scalar5 + scalar6 + scalar7 + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + scalars: { + Scalar1: '../../scalars#default', + Scalar2: '../../scalars#MyScalar2', + Scalar3: '../../scalars#MyScalar3 as AliasedScalar3', + Scalar4: '@org/scalars#default', + Scalar5: '@org/scalars#MyScalar5', + Scalar6: '@org/scalars#MyScalar6 as AliasedScalar6', + Scalar7: { + input: '@org/input-output#Scalar7Input', + output: '@org/input-output#Scalar7Output', + }, + UnusedScalar: 'scalars#UnusedScalar', + }, + }, + { outputFile: '' } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "import Scalar1 from '../../scalars'; + import { MyScalar2, MyScalar3 as AliasedScalar3 } from '../../scalars'; + import Scalar4 from '@org/scalars'; + import { MyScalar5, MyScalar6 as AliasedScalar6 } from '@org/scalars'; + import { Scalar7Output } from '@org/input-output'; + type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserQueryVariables = Exact<{ [key: string]: never; }>; + + + export type UserQuery = { user: { id: string, scalar1: Scalar1 | null, scalar2: MyScalar2 | null, scalar3: AliasedScalar3 | null, scalar4: Scalar4 | null, scalar5: MyScalar5 | null, scalar6: AliasedScalar6 | null, scalar7: Scalar7Output | null } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('imports external custom scalar correctly when used in Input and Variables', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(input: UserInput): User + } + + type User { + id: ID! + } + + input UserInput { + scalar1: Scalar1 + scalar2: Scalar2 + scalar3: Scalar3 + } + + scalar Scalar1 + scalar Scalar2 + scalar Scalar3 + scalar Scalar4 + scalar Scalar5 + scalar Scalar6 + scalar Scalar7 + scalar UnusedScalar + `); + const document = parse(/* GraphQL */ ` + query User($userInput: UserInput, $scalar4: Scalar4, $scalar5: Scalar5, $scalar6: Scalar6, $scalar7: Scalar7) { + user { + id + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + scalars: { + Scalar1: '../../scalars#default', + Scalar2: '../../scalars#MyScalar2', + Scalar3: '../../scalars#MyScalar3 as AliasedScalar3', + Scalar4: '@org/scalars#default', + Scalar5: '@org/scalars#MyScalar5', + Scalar6: '@org/scalars#MyScalar6 as AliasedScalar6', + Scalar7: { + input: '@org/input-output#Scalar7Input', + output: '@org/input-output#Scalar7Output', + }, + UnusedScalar: 'scalars#UnusedScalar', + }, + }, + { outputFile: '' } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "import Scalar1 from '../../scalars'; + import { MyScalar2, MyScalar3 as AliasedScalar3 } from '../../scalars'; + import Scalar4 from '@org/scalars'; + import { MyScalar5, MyScalar6 as AliasedScalar6 } from '@org/scalars'; + import { Scalar7Input } from '@org/input-output'; + type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserInput = { + scalar1?: Scalar1 | null | undefined; + scalar2?: MyScalar2 | null | undefined; + scalar3?: AliasedScalar3 | null | undefined; + }; + + export type UserQueryVariables = Exact<{ + userInput?: UserInput | null | undefined; + scalar4?: Scalar4 | null | undefined; + scalar5?: MyScalar5 | null | undefined; + scalar6?: AliasedScalar6 | null | undefined; + scalar7?: Scalar7Input | null | undefined; + }>; + + + export type UserQuery = { user: { id: string } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('imports multiple default imports and named imports correctly by default', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + } + + type User { + id: ID! + scalar11: Scalar11 + } + + scalar Scalar1 + scalar Scalar2 + scalar Scalar3 + scalar Scalar4 + scalar Scalar5 + scalar Scalar6 + scalar Scalar7 + scalar Scalar8 + scalar Scalar9 + scalar Scalar10 + scalar Scalar11 + scalar Scalar12 + scalar UnusedScalar + `); + const document = parse(/* GraphQL */ ` + query User( + # relative imports + $scalar1: Scalar1 + $scalar1a: Scalar1 # Should only import once + $scalar2: Scalar2 + $scalar3: Scalar3 + $scalar3a: Scalar3 # Should only import once + $scalar4: Scalar4 + # module imports + $scalar5: Scalar5 + $scalar6: Scalar6 + $scalar7: Scalar7 + $scalar8: Scalar8 + $scalar9: Scalar9 + $scalar10: Scalar10 + # mix of input/output + $scalar11: Scalar11 + $scalar12: Scalar12 + ) { + user { + id + scalar11 + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + scalars: { + Scalar1: '../../scalars#default', + Scalar2: '../../scalars#default as DefaultScalar2', + Scalar3: '../../scalars#default as DefaultScalar3', + Scalar4: '../../scalars#Scalar4', + Scalar5: '../../scalars#Scalar5 as MyScalar5', + Scalar6: '@org/scalars#default', + Scalar7: '@org/scalars#default as DefaultScalar7', + Scalar8: '@org/scalars#default as DefaultScalar8', + Scalar9: '@org/scalars#Scalar9', + Scalar10: '@org/scalars#Scalar10 as MyScalar10', + Scalar11: { + input: '@org/input-output#Scalar11 as Scalar11Input', + output: '@org/input-output#Scalar11 as Scalar11Output', + }, + Scalar12: { + input: '@org/input-output#Scalar12', + output: '@org/input-output#Scalar12', + }, + UnusedScalar: 'scalars#UnusedScalar', + }, + }, + { outputFile: '' } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "import Scalar1 from '../../scalars'; + import DefaultScalar2 from '../../scalars'; + import DefaultScalar3 from '../../scalars'; + import { Scalar4, Scalar5 as MyScalar5 } from '../../scalars'; + import Scalar6 from '@org/scalars'; + import DefaultScalar7 from '@org/scalars'; + import DefaultScalar8 from '@org/scalars'; + import { Scalar9, Scalar10 as MyScalar10 } from '@org/scalars'; + import { Scalar11 as Scalar11Input, Scalar11 as Scalar11Output, Scalar12 } from '@org/input-output'; + type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserQueryVariables = Exact<{ + scalar1?: Scalar1 | null | undefined; + scalar1a?: Scalar1 | null | undefined; + scalar2?: DefaultScalar2 | null | undefined; + scalar3?: DefaultScalar3 | null | undefined; + scalar3a?: DefaultScalar3 | null | undefined; + scalar4?: Scalar4 | null | undefined; + scalar5?: MyScalar5 | null | undefined; + scalar6?: Scalar6 | null | undefined; + scalar7?: DefaultScalar7 | null | undefined; + scalar8?: DefaultScalar8 | null | undefined; + scalar9?: Scalar9 | null | undefined; + scalar10?: MyScalar10 | null | undefined; + scalar11?: Scalar11Input | null | undefined; + scalar12?: Scalar12 | null | undefined; + }>; + + + export type UserQuery = { user: { id: string, scalar11: Scalar11Output | null } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('imports multiple default imports and named imports correctly with useTypeImports:true', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + } + + type User { + id: ID! + scalar11: Scalar11 + } + + scalar Scalar1 + scalar Scalar2 + scalar Scalar3 + scalar Scalar4 + scalar Scalar5 + scalar Scalar6 + scalar Scalar7 + scalar Scalar8 + scalar Scalar9 + scalar Scalar10 + scalar Scalar11 + scalar Scalar12 + scalar UnusedScalar + `); + const document = parse(/* GraphQL */ ` + query User( + # relative imports + $scalar1: Scalar1 + $scalar1a: Scalar1 # Should only import once + $scalar2: Scalar2 + $scalar3: Scalar3 + $scalar3a: Scalar3 # Should only import once + $scalar4: Scalar4 + # module imports + $scalar5: Scalar5 + $scalar6: Scalar6 + $scalar7: Scalar7 + $scalar8: Scalar8 + $scalar9: Scalar9 + $scalar10: Scalar10 + # mix of input/output + $scalar11: Scalar11 + $scalar12: Scalar12 + ) { + user { + id + scalar11 + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + useTypeImports: true, + scalars: { + Scalar1: '../../scalars#default', + Scalar2: '../../scalars#default as DefaultScalar2', + Scalar3: '../../scalars#default as DefaultScalar3', + Scalar4: '../../scalars#Scalar4', + Scalar5: '../../scalars#Scalar5 as MyScalar5', + Scalar6: '@org/scalars#default', + Scalar7: '@org/scalars#default as DefaultScalar7', + Scalar8: '@org/scalars#default as DefaultScalar8', + Scalar9: '@org/scalars#Scalar9', + Scalar10: '@org/scalars#Scalar10 as MyScalar10', + Scalar11: { + input: '@org/input-output#Scalar11 as Scalar11Input', + output: '@org/input-output#Scalar11 as Scalar11Output', + }, + Scalar12: { + input: '@org/input-output#Scalar12', + output: '@org/input-output#Scalar12', + }, + UnusedScalar: 'scalars#UnusedScalar', + }, + }, + { outputFile: '' } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "import type { default as Scalar1 } from '../../scalars'; + import type { default as DefaultScalar2 } from '../../scalars'; + import type { default as DefaultScalar3 } from '../../scalars'; + import type { Scalar4, Scalar5 as MyScalar5 } from '../../scalars'; + import type { default as Scalar6 } from '@org/scalars'; + import type { default as DefaultScalar7 } from '@org/scalars'; + import type { default as DefaultScalar8 } from '@org/scalars'; + import type { Scalar9, Scalar10 as MyScalar10 } from '@org/scalars'; + import type { Scalar11 as Scalar11Input, Scalar11 as Scalar11Output, Scalar12 } from '@org/input-output'; + type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserQueryVariables = Exact<{ + scalar1?: Scalar1 | null | undefined; + scalar1a?: Scalar1 | null | undefined; + scalar2?: DefaultScalar2 | null | undefined; + scalar3?: DefaultScalar3 | null | undefined; + scalar3a?: DefaultScalar3 | null | undefined; + scalar4?: Scalar4 | null | undefined; + scalar5?: MyScalar5 | null | undefined; + scalar6?: Scalar6 | null | undefined; + scalar7?: DefaultScalar7 | null | undefined; + scalar8?: DefaultScalar8 | null | undefined; + scalar9?: Scalar9 | null | undefined; + scalar10?: MyScalar10 | null | undefined; + scalar11?: Scalar11Input | null | undefined; + scalar12?: Scalar12 | null | undefined; + }>; + + + export type UserQuery = { user: { id: string, scalar11: Scalar11Output | null } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); +}); From 5c4c0422690cdbcfb90e65083043d333a1d14e3b Mon Sep 17 00:00:00 2001 From: Igor Kusakov Date: Mon, 16 Feb 2026 06:22:01 -0500 Subject: [PATCH 36/69] Improve comments, remove unused prop (#10589) Co-authored-by: Igor Kusakov --- dev-test-apollo-tooling/cli/index.ts | 37 +++++------- dev-test-apollo-tooling/src/Component.ts | 2 +- dev-test-apollo-tooling/src/Duplicates.ts | 2 +- .../src/__generated__/Component.ts | 4 +- .../src/__generated__/Duplicates.ts | 6 +- .../src/__generated__/Helper.ts | 4 +- .../src/selection-set-to-object.ts | 10 ++-- .../typescript/operations/src/visitor.ts | 2 +- ...gen+near-operation-file-preset+2.5.0.patch | 56 +++++++++++++++++++ 9 files changed, 81 insertions(+), 42 deletions(-) create mode 100644 patches/@graphql-codegen+near-operation-file-preset+2.5.0.patch diff --git a/dev-test-apollo-tooling/cli/index.ts b/dev-test-apollo-tooling/cli/index.ts index 72994ab2d47..8aaebce662c 100644 --- a/dev-test-apollo-tooling/cli/index.ts +++ b/dev-test-apollo-tooling/cli/index.ts @@ -27,7 +27,6 @@ const GRAPHQL_CODEGEN_CONFIG = { fragmentSuffix: '', // Don't add 'Fragment' suffix to fragment result types extractAllFieldsToTypesCompact: true, // Extracts all fields to separate types (similar to apollo-codegen behavior) printFieldsOnNewLines: true, // Prints each field on a new line (similar to apollo-codegen behavior) - importTypesNamespace: '', // Disable namespace prefix on imported types (preset config) enumType: 'native', generatesOperationTypes: true, }; @@ -39,17 +38,14 @@ export const main = async () => { const includes = ['src']; - const generateFiles: { [scanPath: string]: Types.ConfiguredOutput } = {}; + const generatePaths: { [scanPath: string]: Types.ConfiguredOutput } = {}; // Prepare the required structure for GraphQL Codegen includes.forEach((include: string) => { - generateFiles[include] = { + generatePaths[include] = { preset: 'near-operation-file', // This preset tells the codegen to generate multiple files instead of one presetConfig: { - extension: '.ts', // Matches the existing Apollo-Codegen file naming - // FIXME: The following config is required, but it is not needed with the recent version of typescript-operations. - // So - when the new version of near-operation-file' is available - fix this. - baseTypesPath: 'unused', + extension: '.ts', folder: GENERATED, // Output folder for generated files importTypesNamespace: '', // Disable namespace prefix on imported types }, @@ -64,23 +60,16 @@ export const main = async () => { }; }); - await generate( - { - schema: localSchemaFilePath, - documents: [ - // matching js extensins as well - there are cases where js files are not converted to typescript yet - // (but the package is typescript) - ...includes.map((include: any) => `${include}/**/*.{js,jsx,ts,tsx}`), - `!**/${GENERATED}/**`, - ], - config: GRAPHQL_CODEGEN_CONFIG, - generates: generateFiles, - silent: false, - debug: true, - verbose: true, - }, - true // overwrite existing files - ); + await generate({ + schema: localSchemaFilePath, + documents: [...includes.map((include: any) => `${include}/**/*.{js,jsx,ts,tsx}`), `!**/${GENERATED}/**`], + config: GRAPHQL_CODEGEN_CONFIG, + generates: generatePaths, + silent: false, + overwrite: true, + debug: false, + verbose: false, + }); }; if (import.meta.url === process.argv[1] || import.meta.url === `file://${process.argv[1]}`) { diff --git a/dev-test-apollo-tooling/src/Component.ts b/dev-test-apollo-tooling/src/Component.ts index 251f14a354d..5360cbd4218 100644 --- a/dev-test-apollo-tooling/src/Component.ts +++ b/dev-test-apollo-tooling/src/Component.ts @@ -1,6 +1,6 @@ /** * This file tests generating enum from external fragement from another file. - * Check that UserManagerRoleType enum is generated in __generated__/Component.ts + * Check that `UserManagerRoleType` enum is generated in `__generated__/Component.ts` */ import { useQuery, gql } from '@apollo/client'; diff --git a/dev-test-apollo-tooling/src/Duplicates.ts b/dev-test-apollo-tooling/src/Duplicates.ts index 54a4397a0db..61ad20e71ae 100644 --- a/dev-test-apollo-tooling/src/Duplicates.ts +++ b/dev-test-apollo-tooling/src/Duplicates.ts @@ -1,6 +1,6 @@ /** * This file tests handing duplicates when using extractAllFieldsToTypesCompact: true - * Check the resultring __generated__/Duplicates.ts file - it should not contain any duplicate names. + * Check the `__generated__/Duplicates.ts` file: it should not contain any duplicate names. */ import { gql } from '@apollo/client'; diff --git a/dev-test-apollo-tooling/src/__generated__/Component.ts b/dev-test-apollo-tooling/src/__generated__/Component.ts index 72d65a65725..678db425463 100644 --- a/dev-test-apollo-tooling/src/__generated__/Component.ts +++ b/dev-test-apollo-tooling/src/__generated__/Component.ts @@ -3,8 +3,6 @@ // @generated // This file was automatically generated and should not be edited. -import type * as Types from '../unused'; - type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export enum UserManagerRoleType { @@ -30,7 +28,7 @@ export type GetFoo_superUser_groupFromAlias_managers_fooUser = { export type GetFoo_superUser_groupFromAlias_managers = { __typename: 'UserManager'; - roleType: Types.UserManagerRoleType; + roleType: UserManagerRoleType; fooUser: GetFoo_superUser_groupFromAlias_managers_fooUser; }; diff --git a/dev-test-apollo-tooling/src/__generated__/Duplicates.ts b/dev-test-apollo-tooling/src/__generated__/Duplicates.ts index 48cecf574a6..dfcdf289c91 100644 --- a/dev-test-apollo-tooling/src/__generated__/Duplicates.ts +++ b/dev-test-apollo-tooling/src/__generated__/Duplicates.ts @@ -3,8 +3,6 @@ // @generated // This file was automatically generated and should not be edited. -import type * as Types from '../unused'; - type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export enum ProcessableFeedbackSortBy { @@ -158,6 +156,6 @@ export type GetFeedbackDataVariables = Exact<{ first?: number | null | undefined; after?: string | null | undefined; scoreFilter?: Array | number | null | undefined; - sortBy?: Types.ProcessableFeedbackSortBy | null | undefined; - sortOrder?: Types.ProcessableFeedbackSortOrder | null | undefined; + sortBy?: ProcessableFeedbackSortBy | null | undefined; + sortOrder?: ProcessableFeedbackSortOrder | null | undefined; }>; diff --git a/dev-test-apollo-tooling/src/__generated__/Helper.ts b/dev-test-apollo-tooling/src/__generated__/Helper.ts index 96087fb8869..7bdc34ff9b2 100644 --- a/dev-test-apollo-tooling/src/__generated__/Helper.ts +++ b/dev-test-apollo-tooling/src/__generated__/Helper.ts @@ -3,8 +3,6 @@ // @generated // This file was automatically generated and should not be edited. -import type * as Types from '../unused'; - export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export enum UserManagerRoleType { ROLE_TYPE_1 = 'ROLE_TYPE_1', @@ -29,6 +27,6 @@ export type HelperFields_fooUser = { export type HelperFields = { __typename: 'UserManager'; - roleType: Types.UserManagerRoleType; + roleType: UserManagerRoleType; fooUser: HelperFields_fooUser; }; diff --git a/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts b/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts index 5eb6083c729..40bdc55a86f 100644 --- a/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts +++ b/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts @@ -92,7 +92,7 @@ export class SelectionSetToObject< protected _primitiveAliasedFields: PrimitiveAliasedFields[] = []; protected _linksFields: LinkField[] = []; protected _queriedForTypename = false; - // Enables resolving conflics in extractAllFieldsToTypesCompact mode: + // Enables resolving conflicting type names in extractAllFieldsToTypesCompact mode: // key === GetFoo_user <-- full field name // value === User <-- last field type protected _seenFieldNames: Map = new Map(); @@ -920,7 +920,7 @@ export class SelectionSetToObject< .map(typeName => { const relevant = grouped[typeName].filter(Boolean); return relevant.map(objDefinition => { - // In compact mode, we still need to keep the final concrete type name for union/interface types + // In extractAllFieldsToTypesCompact mode, we still need to keep the final concrete type name for union/interface types // to distinguish between different implementations, but we skip it for simple object types const hasMultipleTypes = Object.keys(grouped).length > 1; let name: string; @@ -987,7 +987,7 @@ export class SelectionSetToObject< const subTypes: DependentType[] = Object.keys(grouped).flatMap(typeName => { const possibleFields = grouped[typeName].filter(Boolean); - // In compact mode, pass typeName only when there are multiple types + // In extractAllFieldsToTypesCompact mode, pass typeName only when there are multiple types const declarationName = this._config.extractAllFieldsToTypesCompact && !hasMultipleTypes ? this.buildFragmentTypeName(fragmentName, fragmentSuffix) @@ -1080,7 +1080,7 @@ export class SelectionSetToObject< } protected buildParentFieldName(typeName: string, parentName: string): string { - // Sample input: + // Sample args: // typeName = User <-- last field type // parentName = GetFoo_user <-- full field name @@ -1090,7 +1090,7 @@ export class SelectionSetToObject< return parentName; } - // When compact mode is enabled, skip appending typeName initially + // When extractAllFieldsToTypesCompact mode is enabled, skip appending typeName initially // but check for conflicts if (this._config.extractAllFieldsToTypesCompact) { const existingTypeName = this._seenFieldNames.get(parentName); diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 7c2dfc96c27..0b4f9c7d184 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -673,7 +673,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< const typeInfo = new TypeInfo(schema); visit( documentNode, - // AST doesn’t include field types (they are defined in schema) - only names. + // AST doesn’t include field types (they are defined in the schema) - only names. // TypeInfo is a stateful helper that tracks typing context while walking the AST // visitWithTypeInfo wires that context into a visitor. visitWithTypeInfo(typeInfo, { diff --git a/patches/@graphql-codegen+near-operation-file-preset+2.5.0.patch b/patches/@graphql-codegen+near-operation-file-preset+2.5.0.patch new file mode 100644 index 00000000000..07a0559c13e --- /dev/null +++ b/patches/@graphql-codegen+near-operation-file-preset+2.5.0.patch @@ -0,0 +1,56 @@ +diff --git a/node_modules/@graphql-codegen/near-operation-file-preset/cjs/index.js b/node_modules/@graphql-codegen/near-operation-file-preset/cjs/index.js +index a0636cb..17ebece 100644 +--- a/node_modules/@graphql-codegen/near-operation-file-preset/cjs/index.js ++++ b/node_modules/@graphql-codegen/near-operation-file-preset/cjs/index.js +@@ -19,7 +19,7 @@ exports.preset = { + const fileName = options.presetConfig.fileName || ''; + const extension = options.presetConfig.extension || '.generated.ts'; + const folder = options.presetConfig.folder || ''; +- const importTypesNamespace = options.presetConfig.importTypesNamespace || 'Types'; ++ const importTypesNamespace = options.presetConfig.importTypesNamespace ?? 'Types'; + const importAllFragmentsFrom = options.presetConfig.importAllFragmentsFrom || null; +- const { baseTypesPath } = options.presetConfig; +- if (!baseTypesPath) { ++ const baseTypesPath = options.presetConfig.baseTypesPath || ''; ++ if (!baseTypesPath && importTypesNamespace) { +diff --git a/node_modules/@graphql-codegen/near-operation-file-preset/cjs/resolve-document-imports.js b/node_modules/@graphql-codegen/near-operation-file-preset/cjs/resolve-document-imports.js +index f8dae4c..50fde90 100644 +--- a/node_modules/@graphql-codegen/near-operation-file-preset/cjs/resolve-document-imports.js ++++ b/node_modules/@graphql-codegen/near-operation-file-preset/cjs/resolve-document-imports.js +@@ -24,7 +24,7 @@ function resolveDocumentImports(presetOptions, schemaObject, importResolverOptio + ...documentFile.document, + definitions: [...documentFile.document.definitions, ...externalFragments.map(fragment => fragment.node)], + }; +- if ((0, plugin_helpers_1.isUsingTypes)(externalFragmentsInjectedDocument, [], schemaObject)) { ++ if ((0, plugin_helpers_1.isUsingTypes)(externalFragmentsInjectedDocument, [], schemaObject) && schemaTypesSource.namespace) { + const schemaTypesImportStatement = (0, visitor_plugin_common_1.generateImportStatement)({ + baseDir, + emitLegacyCommonJSImports: presetOptions.config.emitLegacyCommonJSImports, +diff --git a/node_modules/@graphql-codegen/near-operation-file-preset/esm/index.js b/node_modules/@graphql-codegen/near-operation-file-preset/esm/index.js +index 6c71580..4747c07 100644 +--- a/node_modules/@graphql-codegen/near-operation-file-preset/esm/index.js ++++ b/node_modules/@graphql-codegen/near-operation-file-preset/esm/index.js +@@ -15,7 +15,7 @@ export const preset = { + const fileName = options.presetConfig.fileName || ''; + const extension = options.presetConfig.extension || '.generated.ts'; + const folder = options.presetConfig.folder || ''; +- const importTypesNamespace = options.presetConfig.importTypesNamespace || 'Types'; ++ const importTypesNamespace = options.presetConfig.importTypesNamespace ?? 'Types'; + const importAllFragmentsFrom = options.presetConfig.importAllFragmentsFrom || null; +- const { baseTypesPath } = options.presetConfig; +- if (!baseTypesPath) { ++ const baseTypesPath = options.presetConfig.baseTypesPath || ''; ++ if (!baseTypesPath && importTypesNamespace) { +diff --git a/node_modules/@graphql-codegen/near-operation-file-preset/esm/resolve-document-imports.js b/node_modules/@graphql-codegen/near-operation-file-preset/esm/resolve-document-imports.js +index e8796cb..4332e0f 100644 +--- a/node_modules/@graphql-codegen/near-operation-file-preset/esm/resolve-document-imports.js ++++ b/node_modules/@graphql-codegen/near-operation-file-preset/esm/resolve-document-imports.js +@@ -20,7 +20,7 @@ export function resolveDocumentImports(presetOptions, schemaObject, importResolv + ...documentFile.document, + definitions: [...documentFile.document.definitions, ...externalFragments.map(fragment => fragment.node)], + }; +- if (isUsingTypes(externalFragmentsInjectedDocument, [], schemaObject)) { ++ if (isUsingTypes(externalFragmentsInjectedDocument, [], schemaObject) && schemaTypesSource.namespace) { + const schemaTypesImportStatement = generateImportStatement({ + baseDir, + emitLegacyCommonJSImports: presetOptions.config.emitLegacyCommonJSImports, From 65b13bec3f8828e2bb001d993cf62459ff11efbf Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Wed, 18 Feb 2026 22:40:23 +1100 Subject: [PATCH 37/69] Remove support for directiveArgumentAndInputFieldMappings (#10596) --- packages/plugins/typescript/operations/src/visitor.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 0b4f9c7d184..b8b6ff0c006 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -333,15 +333,6 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< } } - // TODO: eddeee888 check if we want to support `directiveArgumentAndInputFieldMappings` for operations - // if (node.directives && this.config.directiveArgumentAndInputFieldMappings) { - // typePart = - // getDirectiveOverrideType({ - // directives: node.directives, - // directiveArgumentAndInputFieldMappings: this.config.directiveArgumentAndInputFieldMappings, - // }) || typePart; - // } - const addOptionalSign = !oneOfDetails.isOneOfInputValue && !this.config.avoidOptionals.inputValue && From 34f6926a9e10f1f9b2c1eb5984693181e4b1c922 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Sat, 21 Feb 2026 17:06:53 +1100 Subject: [PATCH 38/69] [CLI] Set `noSilentErrors: true` by default (#10597) * Set noSilentErrors: true by default * Add changeset * Format tests --- .changeset/slow-sheep-rush.md | 9 +++ packages/graphql-codegen-cli/src/config.ts | 1 + .../tests/generate-and-save.spec.ts | 32 +++++++++++ .../error-document-error-keyword.graphql.1.ts | 7 +++ .../error-document-error-keyword.graphql.2.ts | 7 +++ ...gen+near-operation-file-preset+2.5.0.patch | 56 ------------------- 6 files changed, 56 insertions(+), 56 deletions(-) create mode 100644 .changeset/slow-sheep-rush.md create mode 100644 packages/graphql-codegen-cli/tests/test-files/error-document-error-keyword.graphql.1.ts create mode 100644 packages/graphql-codegen-cli/tests/test-files/error-document-error-keyword.graphql.2.ts delete mode 100644 patches/@graphql-codegen+near-operation-file-preset+2.5.0.patch diff --git a/.changeset/slow-sheep-rush.md b/.changeset/slow-sheep-rush.md new file mode 100644 index 00000000000..5caab3f24ed --- /dev/null +++ b/.changeset/slow-sheep-rush.md @@ -0,0 +1,9 @@ +--- +'@graphql-codegen/cli': major +--- + +BREAKING CHANGE: Set `noSilentErrors: true` by default + +When multiple files match documents pattern, and there are syntax errors in some but not others, then the operations with errors are not included in the loaded documents list by default (`noSilentErrors: false`). This is annoying for users as there is no feedback loop during development. + +`noSilentErrors: true` is used as the default for Codegen users to make the feedback loop faster. It can still overriden in Codegen Config if desired. \ No newline at end of file diff --git a/packages/graphql-codegen-cli/src/config.ts b/packages/graphql-codegen-cli/src/config.ts index e04547b1ad0..845c5274cc4 100644 --- a/packages/graphql-codegen-cli/src/config.ts +++ b/packages/graphql-codegen-cli/src/config.ts @@ -418,6 +418,7 @@ export class CodegenContext { } const config = { + noSilentErrors: true, // When a `documents` pattern matches multiple files e.g. `*` exists in filename like `src/something.*.ts`, and some files fail but some pass syntax error check, the failed files will silently fail if `noSilentErrors: false`. So, `noSilentErrors: true` is turned on by default to help users detect errors faster. ...extraConfig, ...this.config, }; diff --git a/packages/graphql-codegen-cli/tests/generate-and-save.spec.ts b/packages/graphql-codegen-cli/tests/generate-and-save.spec.ts index 137ce27ea52..8e064912622 100644 --- a/packages/graphql-codegen-cli/tests/generate-and-save.spec.ts +++ b/packages/graphql-codegen-cli/tests/generate-and-save.spec.ts @@ -333,6 +333,38 @@ describe('generate-and-save', () => { } }); + test('Document syntax error - when `*` is used in documents filename pattern, and some failed but some passed, should report error by default (noSilentErrors: true)', async () => { + expect.assertions(6); + outputErrorSpy.mockImplementation(() => true); + try { + await generate( + { + verbose: true, + schema: './tests/test-files/schema-dir/schema.ts', + documents: './tests/test-files/error-document-error-keyword.graphql.*.ts', // Should find `error-document-error-keyword.graphql.1.ts` (failed) and `error-document-error-keyword.graphql.2.ts` (passed) + generates: { + 'src/gql/': { + preset: 'client-preset', + }, + }, + }, + false + ); + } catch { + // Note: cannot use toMatchInlineSnapshot here because spacing in the snapshot gets formatted by prettier. + expect(outputErrorSpy.mock.calls[0][0]).toContain( + '[FAILED] Failed to load documents from ./tests/test-files/error-document-error-keyword.graphql.*.ts,!src/gql/:' + ); + expect(outputErrorSpy.mock.calls[0][0]).toContain('[FAILED] Syntax Error: Unexpected Name "qu".'); + expect(outputErrorSpy.mock.calls[0][0]).toContain( + `[FAILED] ${process.cwd()}/tests/test-files/error-document-error-keyword.graphql.1.ts:2:3` + ); + expect(outputErrorSpy.mock.calls[0][0]).toContain('[FAILED] 2 | qu ery Test {'); + expect(outputErrorSpy.mock.calls[0][0]).toContain('[FAILED] | ^'); + expect(outputErrorSpy.mock.calls[0][0]).toContain('[FAILED] 3 | user {'); + } + }); + test('No documents found - should throw error by default', async () => { expect.assertions(1); outputErrorSpy.mockImplementation(() => true); diff --git a/packages/graphql-codegen-cli/tests/test-files/error-document-error-keyword.graphql.1.ts b/packages/graphql-codegen-cli/tests/test-files/error-document-error-keyword.graphql.1.ts new file mode 100644 index 00000000000..a19d025d60d --- /dev/null +++ b/packages/graphql-codegen-cli/tests/test-files/error-document-error-keyword.graphql.1.ts @@ -0,0 +1,7 @@ +const query1 = /* GraphQL */ ` + qu ery Test { + user { + one: a + } + } +`; diff --git a/packages/graphql-codegen-cli/tests/test-files/error-document-error-keyword.graphql.2.ts b/packages/graphql-codegen-cli/tests/test-files/error-document-error-keyword.graphql.2.ts new file mode 100644 index 00000000000..70f42047e4b --- /dev/null +++ b/packages/graphql-codegen-cli/tests/test-files/error-document-error-keyword.graphql.2.ts @@ -0,0 +1,7 @@ +const query2 = /* GraphQL */ ` + query Test2 { + user { + two: a + } + } +`; diff --git a/patches/@graphql-codegen+near-operation-file-preset+2.5.0.patch b/patches/@graphql-codegen+near-operation-file-preset+2.5.0.patch deleted file mode 100644 index 07a0559c13e..00000000000 --- a/patches/@graphql-codegen+near-operation-file-preset+2.5.0.patch +++ /dev/null @@ -1,56 +0,0 @@ -diff --git a/node_modules/@graphql-codegen/near-operation-file-preset/cjs/index.js b/node_modules/@graphql-codegen/near-operation-file-preset/cjs/index.js -index a0636cb..17ebece 100644 ---- a/node_modules/@graphql-codegen/near-operation-file-preset/cjs/index.js -+++ b/node_modules/@graphql-codegen/near-operation-file-preset/cjs/index.js -@@ -19,7 +19,7 @@ exports.preset = { - const fileName = options.presetConfig.fileName || ''; - const extension = options.presetConfig.extension || '.generated.ts'; - const folder = options.presetConfig.folder || ''; -- const importTypesNamespace = options.presetConfig.importTypesNamespace || 'Types'; -+ const importTypesNamespace = options.presetConfig.importTypesNamespace ?? 'Types'; - const importAllFragmentsFrom = options.presetConfig.importAllFragmentsFrom || null; -- const { baseTypesPath } = options.presetConfig; -- if (!baseTypesPath) { -+ const baseTypesPath = options.presetConfig.baseTypesPath || ''; -+ if (!baseTypesPath && importTypesNamespace) { -diff --git a/node_modules/@graphql-codegen/near-operation-file-preset/cjs/resolve-document-imports.js b/node_modules/@graphql-codegen/near-operation-file-preset/cjs/resolve-document-imports.js -index f8dae4c..50fde90 100644 ---- a/node_modules/@graphql-codegen/near-operation-file-preset/cjs/resolve-document-imports.js -+++ b/node_modules/@graphql-codegen/near-operation-file-preset/cjs/resolve-document-imports.js -@@ -24,7 +24,7 @@ function resolveDocumentImports(presetOptions, schemaObject, importResolverOptio - ...documentFile.document, - definitions: [...documentFile.document.definitions, ...externalFragments.map(fragment => fragment.node)], - }; -- if ((0, plugin_helpers_1.isUsingTypes)(externalFragmentsInjectedDocument, [], schemaObject)) { -+ if ((0, plugin_helpers_1.isUsingTypes)(externalFragmentsInjectedDocument, [], schemaObject) && schemaTypesSource.namespace) { - const schemaTypesImportStatement = (0, visitor_plugin_common_1.generateImportStatement)({ - baseDir, - emitLegacyCommonJSImports: presetOptions.config.emitLegacyCommonJSImports, -diff --git a/node_modules/@graphql-codegen/near-operation-file-preset/esm/index.js b/node_modules/@graphql-codegen/near-operation-file-preset/esm/index.js -index 6c71580..4747c07 100644 ---- a/node_modules/@graphql-codegen/near-operation-file-preset/esm/index.js -+++ b/node_modules/@graphql-codegen/near-operation-file-preset/esm/index.js -@@ -15,7 +15,7 @@ export const preset = { - const fileName = options.presetConfig.fileName || ''; - const extension = options.presetConfig.extension || '.generated.ts'; - const folder = options.presetConfig.folder || ''; -- const importTypesNamespace = options.presetConfig.importTypesNamespace || 'Types'; -+ const importTypesNamespace = options.presetConfig.importTypesNamespace ?? 'Types'; - const importAllFragmentsFrom = options.presetConfig.importAllFragmentsFrom || null; -- const { baseTypesPath } = options.presetConfig; -- if (!baseTypesPath) { -+ const baseTypesPath = options.presetConfig.baseTypesPath || ''; -+ if (!baseTypesPath && importTypesNamespace) { -diff --git a/node_modules/@graphql-codegen/near-operation-file-preset/esm/resolve-document-imports.js b/node_modules/@graphql-codegen/near-operation-file-preset/esm/resolve-document-imports.js -index e8796cb..4332e0f 100644 ---- a/node_modules/@graphql-codegen/near-operation-file-preset/esm/resolve-document-imports.js -+++ b/node_modules/@graphql-codegen/near-operation-file-preset/esm/resolve-document-imports.js -@@ -20,7 +20,7 @@ export function resolveDocumentImports(presetOptions, schemaObject, importResolv - ...documentFile.document, - definitions: [...documentFile.document.definitions, ...externalFragments.map(fragment => fragment.node)], - }; -- if (isUsingTypes(externalFragmentsInjectedDocument, [], schemaObject)) { -+ if (isUsingTypes(externalFragmentsInjectedDocument, [], schemaObject) && schemaTypesSource.namespace) { - const schemaTypesImportStatement = generateImportStatement({ - baseDir, - emitLegacyCommonJSImports: presetOptions.config.emitLegacyCommonJSImports, From ea0bed52f040fd77a622e07791a1809b49ca91c0 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Tue, 24 Feb 2026 22:32:01 +1100 Subject: [PATCH 39/69] Change generatesOperationTypes to generateOperationTypes for consistency (#10602) --- .changeset/proud-jobs-decide.md | 2 +- dev-test-apollo-tooling/cli/index.ts | 2 +- dev-test/codegen.ts | 4 ++-- .../src/base-documents-visitor.ts | 18 ++++++++---------- .../typescript/operations/src/visitor.ts | 6 +++--- ...s-documents.standalone.import-types.spec.ts | 6 +++--- .../tests/ts-documents.standalone.spec.ts | 6 +++--- 7 files changed, 21 insertions(+), 23 deletions(-) diff --git a/.changeset/proud-jobs-decide.md b/.changeset/proud-jobs-decide.md index 36c3a298ac4..dd7d919643d 100644 --- a/.changeset/proud-jobs-decide.md +++ b/.changeset/proud-jobs-decide.md @@ -3,4 +3,4 @@ '@graphql-codegen/typescript-operations': minor --- -Add generatesOperationTypes to typescript-operations to allow omitting operation types such as Variables, Query/Mutation/Subscription selection set, and Fragment types +Add generateOperationTypes to typescript-operations to allow omitting operation types such as Variables, Query/Mutation/Subscription selection set, and Fragment types diff --git a/dev-test-apollo-tooling/cli/index.ts b/dev-test-apollo-tooling/cli/index.ts index 8aaebce662c..6c36c92470b 100644 --- a/dev-test-apollo-tooling/cli/index.ts +++ b/dev-test-apollo-tooling/cli/index.ts @@ -28,7 +28,7 @@ const GRAPHQL_CODEGEN_CONFIG = { extractAllFieldsToTypesCompact: true, // Extracts all fields to separate types (similar to apollo-codegen behavior) printFieldsOnNewLines: true, // Prints each field on a new line (similar to apollo-codegen behavior) enumType: 'native', - generatesOperationTypes: true, + generateOperationTypes: true, }; export const main = async () => { diff --git a/dev-test/codegen.ts b/dev-test/codegen.ts index c6525522c64..a5c16134903 100644 --- a/dev-test/codegen.ts +++ b/dev-test/codegen.ts @@ -83,7 +83,7 @@ const config: CodegenConfig = { './dev-test/githunt/types.onlyEnums.ts': { schema: './dev-test/githunt/schema.json', documents: './dev-test/githunt/**/*.graphql', - config: { generatesOperationTypes: false }, + config: { generateOperationTypes: false }, plugins: ['typescript-operations'], }, './dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts': { @@ -279,7 +279,7 @@ const config: CodegenConfig = { documents: ['./dev-test/standalone-operations/import-schema-types/*.graphql'], plugins: ['typescript-operations'], config: { - generatesOperationTypes: false, + generateOperationTypes: false, }, }, './dev-test/standalone-operations/import-schema-types/_types.generated.ts': { diff --git a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts index cca09fb2cb4..665bfd1ecd9 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts @@ -33,7 +33,7 @@ export interface ParsedDocumentsConfig extends ParsedConfig { experimentalFragmentVariables: boolean; mergeFragmentTypes: boolean; customDirectives: CustomDirectivesConfig; - generatesOperationTypes: boolean; + generateOperationTypes: boolean; importSchemaTypesFrom: string; } @@ -184,7 +184,7 @@ export interface RawDocumentsConfig extends RawConfig { * 'path/to/file.ts': { * plugins: ['typescript-operations'], * config: { - * generatesOperationTypes: false, + * generateOperationTypes: false, * }, * }, * }, @@ -192,10 +192,10 @@ export interface RawDocumentsConfig extends RawConfig { * export default config; * ``` */ - generatesOperationTypes?: boolean; + generateOperationTypes?: boolean; /** - * @description The absolute (prefixed with `~`) or relative path from `cwd` to the shared used Enums and Input (See `generatesOperationTypes`). + * @description The absolute (prefixed with `~`) or relative path from `cwd` to the shared used Enums and Input (See `generateOperationTypes`). * @default true * @exampleMarkdown * ```ts filename="codegen.ts" @@ -263,10 +263,8 @@ export class BaseDocumentsVisitor< globalNamespace: !!rawConfig.globalNamespace, operationResultSuffix: getConfigValue(rawConfig.operationResultSuffix, ''), scalars: buildScalarsFromConfig(_schema, rawConfig, defaultScalars), - customDirectives: getConfigValue(rawConfig.customDirectives, { - apolloUnmask: false, - }), - generatesOperationTypes: getConfigValue(rawConfig.generatesOperationTypes, true), + customDirectives: getConfigValue(rawConfig.customDirectives, { apolloUnmask: false }), + generateOperationTypes: getConfigValue(rawConfig.generateOperationTypes, true), importSchemaTypesFrom: getConfigValue(rawConfig.importSchemaTypesFrom, ''), extractAllFieldsToTypes: getConfigValue(rawConfig.extractAllFieldsToTypes, false) || @@ -325,7 +323,7 @@ export class BaseDocumentsVisitor< } FragmentDefinition(node: FragmentDefinitionNode): string { - if (!this.config.generatesOperationTypes) { + if (!this.config.generateOperationTypes) { return null; } @@ -362,7 +360,7 @@ export class BaseDocumentsVisitor< } OperationDefinition(node: OperationDefinitionNode): string | null { - if (!this.config.generatesOperationTypes) { + if (!this.config.generateOperationTypes) { return null; } diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index b8b6ff0c006..9c28558d06e 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -446,7 +446,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< | 'multi-file-operation-file' | 'single-file-operation-file' = this.config.importSchemaTypesFrom ? 'multi-file-operation-file' - : this.config.generatesOperationTypes + : this.config.generateOperationTypes ? 'single-file-operation-file' : 'multi-file-shared-type-file'; @@ -712,7 +712,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< getExactUtilityType(): string | null { if ( - !this.config.generatesOperationTypes || // 1. If we don't generate operation types, definitely do not need `Exact` + !this.config.generateOperationTypes || // 1. If we don't generate operation types, definitely do not need `Exact` !this._needsExactUtilityType // 2. Even if we generate operation types, we may not need `Exact` if there's no operations in the documents i.e. only fragments found ) { return null; @@ -722,7 +722,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< } getIncrementalUtilityType(): string | null { - if (!this.config.generatesOperationTypes) { + if (!this.config.generateOperationTypes) { return null; } diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts index 99e676025ae..403922141df 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts @@ -404,7 +404,7 @@ describe('TypeScript Operations Plugin - Import Types with external custom Scala schema, [{ document }], { - generatesOperationTypes: false, + generateOperationTypes: false, scalars: { Scalar1: '@org/scalars#Scalar1', }, @@ -480,7 +480,7 @@ describe('TypeScript Operations Plugin - Import Types with external custom Scala schema, [{ document }], { - generatesOperationTypes: false, + generateOperationTypes: false, scalars: { Scalar1: '@org/scalars#Scalar1', }, @@ -551,7 +551,7 @@ describe('TypeScript Operations Plugin - Import Types with external custom Scala schema, [{ document }], { - generatesOperationTypes: false, + generateOperationTypes: false, scalars: { Scalar1: '@org/scalars#Scalar1', }, diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts index 815347e89e8..b9ca78b04bc 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -519,7 +519,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { `); }); - it('does not generate Variables, Result or Fragments when generatesOperationTypes is false', async () => { + it('does not generate Variables, Result or Fragments when generateOperationTypes:false', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { user(id: ID!): User @@ -631,7 +631,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { generatesOperationTypes: false }, { outputFile: '' }), + await plugin(schema, [{ document }], { generateOperationTypes: false }, { outputFile: '' }), ]); expect(result).toMatchInlineSnapshot(` @@ -730,7 +730,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { generatesOperationTypes: false }, { outputFile: '' }), + await plugin(schema, [{ document }], { generateOperationTypes: false }, { outputFile: '' }), ]); expect(result).toMatchInlineSnapshot(` From a8b31763b58c343feb1721904e2da7abbe154cf2 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Tue, 24 Feb 2026 23:08:29 +1100 Subject: [PATCH 40/69] [typescript-operations] Set `namespacedImportName` default value when `importSchemaTypesFrom` is used (#10603) * Improve namespacedImportName integration with importSchemaTypesFrom * Update dev-test * Update changeset --- .changeset/big-taxes-hunt.md | 6 + dev-test/codegen.ts | 5 +- .../src/base-documents-visitor.ts | 30 ++++- ...-documents.standalone.import-types.spec.ts | 105 ++++++++++++------ 4 files changed, 106 insertions(+), 40 deletions(-) create mode 100644 .changeset/big-taxes-hunt.md diff --git a/.changeset/big-taxes-hunt.md b/.changeset/big-taxes-hunt.md new file mode 100644 index 00000000000..d4d9998152a --- /dev/null +++ b/.changeset/big-taxes-hunt.md @@ -0,0 +1,6 @@ +--- +'@graphql-codegen/visitor-plugin-common': patch +'@graphql-codegen/typescript-operations': patch +--- + +Improve `namespacedImportName` usability by setting a default when `importSchemaTypesFrom` is set diff --git a/dev-test/codegen.ts b/dev-test/codegen.ts index a5c16134903..61779fd7c46 100644 --- a/dev-test/codegen.ts +++ b/dev-test/codegen.ts @@ -289,7 +289,6 @@ const config: CodegenConfig = { config: { importSchemaTypesFrom: './dev-test/standalone-operations/import-schema-types/_base.generated.ts', - namespacedImportName: 'Types', }, }, @@ -303,8 +302,8 @@ const config: CodegenConfig = { documents: ['./dev-test/standalone-operations/with-typescript-plugin/*.graphql'], plugins: ['typescript-operations'], config: { - importSchemaTypesFrom: './dev-test/standalone-operations/with-typescript-plugin/_base.generated.ts', - namespacedImportName: 'Types', + importSchemaTypesFrom: + './dev-test/standalone-operations/with-typescript-plugin/_base.generated.ts', }, }, }, diff --git a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts index 665bfd1ecd9..f5c2f1a8f08 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts @@ -25,7 +25,6 @@ export interface ParsedDocumentsConfig extends ParsedConfig { operationResultSuffix: string; dedupeOperationSuffix: boolean; omitOperationSuffix: boolean; - namespacedImportName: string | null; exportFragmentSpreadSubTypes: boolean; skipTypeNameForRoot: boolean; nonOptionalTypename: boolean; @@ -35,6 +34,7 @@ export interface ParsedDocumentsConfig extends ParsedConfig { customDirectives: CustomDirectivesConfig; generateOperationTypes: boolean; importSchemaTypesFrom: string; + namespacedImportName: string | null; } export interface RawDocumentsConfig extends RawConfig { @@ -139,9 +139,27 @@ export interface RawDocumentsConfig extends RawConfig { */ mergeFragmentTypes?: boolean; - // The following are internal, and used by presets /** - * @ignore + * @description Prefixes all GraphQL related generated types with that value, as namespaces import. + * You can use this feature to allow separation of plugins to different files (See `importSchemaTypesFrom`) + * @default 'Types' (if `importSchemaTypesFrom` is set) + * @exampleMarkdown + * ```ts filename="codegen.ts" + * import type { CodegenConfig } from '@graphql-codegen/cli'; + * const config: CodegenConfig = { + * // ... + * generates: { + * 'path/to/file.ts': { + * plugins: ['typescript-operations'], + * config: { + * importSchemaTypesFrom: './path/to/shared-types.ts', + * namespacedImportName: 'Types' + * }, + * }, + * }, + * }; + * export default config; + * ``` */ namespacedImportName?: string; @@ -252,20 +270,22 @@ export class BaseDocumentsVisitor< protected _schema: GraphQLSchema, defaultScalars: NormalizedScalarsMap = DEFAULT_SCALARS, ) { + const importSchemaTypesFrom = getConfigValue(rawConfig.importSchemaTypesFrom, ''); + super(rawConfig, { exportFragmentSpreadSubTypes: getConfigValue(rawConfig.exportFragmentSpreadSubTypes, false), dedupeOperationSuffix: getConfigValue(rawConfig.dedupeOperationSuffix, false), omitOperationSuffix: getConfigValue(rawConfig.omitOperationSuffix, false), skipTypeNameForRoot: getConfigValue(rawConfig.skipTypeNameForRoot, false), nonOptionalTypename: getConfigValue(rawConfig.nonOptionalTypename, false), - namespacedImportName: getConfigValue(rawConfig.namespacedImportName, null), experimentalFragmentVariables: getConfigValue(rawConfig.experimentalFragmentVariables, false), globalNamespace: !!rawConfig.globalNamespace, operationResultSuffix: getConfigValue(rawConfig.operationResultSuffix, ''), scalars: buildScalarsFromConfig(_schema, rawConfig, defaultScalars), customDirectives: getConfigValue(rawConfig.customDirectives, { apolloUnmask: false }), generateOperationTypes: getConfigValue(rawConfig.generateOperationTypes, true), - importSchemaTypesFrom: getConfigValue(rawConfig.importSchemaTypesFrom, ''), + importSchemaTypesFrom, + namespacedImportName: getConfigValue(rawConfig.namespacedImportName, importSchemaTypesFrom ? 'Types' : null), extractAllFieldsToTypes: getConfigValue(rawConfig.extractAllFieldsToTypes, false) || getConfigValue(rawConfig.extractAllFieldsToTypesCompact, false), diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts index 403922141df..26d755d447d 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts @@ -94,16 +94,13 @@ describe('TypeScript Operations Plugin - Import Types', () => { await plugin( schema, [{ document }], - { - importSchemaTypesFrom: './base-dir/path-to-other-file.generated.ts', - namespacedImportName: 'TypeImport', - }, + { importSchemaTypesFrom: './base-dir/path-to-other-file.generated.ts' }, { outputFile: './base-dir/this-file.ts' } ), ]); expect(result).toMatchInlineSnapshot(` - "import type * as TypeImport from './path-to-other-file.generated'; + "import type * as Types from './path-to-other-file.generated'; type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; @@ -112,22 +109,22 @@ describe('TypeScript Operations Plugin - Import Types', () => { }>; - export type UserQuery = { user: { id: string, name: string, role: TypeImport.UserRole, createdAt: unknown } | null }; + export type UserQuery = { user: { id: string, name: string, role: Types.UserRole, createdAt: unknown } | null }; export type UsersQueryVariables = Exact<{ - input: TypeImport.UsersInput; + input: Types.UsersInput; }>; export type UsersQuery = { users: | { result: Array<{ id: string }> } - | { error: TypeImport.ResponseErrorType } + | { error: Types.ResponseErrorType } }; export type UsersWithScalarInputQueryVariables = Exact<{ from: unknown; to?: unknown; - role?: TypeImport.UserRole | null | undefined; + role?: Types.UserRole | null | undefined; }>; @@ -229,16 +226,13 @@ describe('TypeScript Operations Plugin - Import Types', () => { await plugin( schema, [{ document }], - { - importSchemaTypesFrom: '~@my-company/package/types', - namespacedImportName: 'TypeImport', - }, + { importSchemaTypesFrom: '~@my-company/package/types' }, { outputFile: './base-dir/this-file.ts' } ), ]); expect(result).toMatchInlineSnapshot(` - "import type * as TypeImport from '@my-company/package/types'; + "import type * as Types from '@my-company/package/types'; type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; @@ -247,22 +241,22 @@ describe('TypeScript Operations Plugin - Import Types', () => { }>; - export type UserQuery = { user: { id: string, name: string, role: TypeImport.UserRole, createdAt: unknown } | null }; + export type UserQuery = { user: { id: string, name: string, role: Types.UserRole, createdAt: unknown } | null }; export type UsersQueryVariables = Exact<{ - input: TypeImport.UsersInput; + input: Types.UsersInput; }>; export type UsersQuery = { users: | { result: Array<{ id: string }> } - | { error: TypeImport.ResponseErrorType } + | { error: Types.ResponseErrorType } }; export type UsersWithScalarInputQueryVariables = Exact<{ from: unknown; to?: unknown; - role?: TypeImport.UserRole | null | undefined; + role?: Types.UserRole | null | undefined; }>; @@ -342,15 +336,7 @@ describe('TypeScript Operations Plugin - Import Types', () => { `); const result = mergeOutputs([ - await plugin( - schema, - [{ document }], - { - importSchemaTypesFrom: './path-to-other-file', - namespacedImportName: 'TypeImport', - }, - { outputFile: '' } - ), + await plugin(schema, [{ document }], { importSchemaTypesFrom: './path-to-other-file' }, { outputFile: '' }), ]); expect(result).toMatchInlineSnapshot(` @@ -430,7 +416,6 @@ describe('TypeScript Operations Plugin - Import Types with external custom Scala [{ document }], { importSchemaTypesFrom: './path-to-other-file', - namespacedImportName: 'TypeImport', scalars: { Scalar1: '@org/scalars#Scalar1', }, @@ -439,12 +424,12 @@ describe('TypeScript Operations Plugin - Import Types with external custom Scala ), ]); expect(operationFileResult).toMatchInlineSnapshot(` - "import type * as TypeImport from './graphql-code-generator/path-to-other-file'; + "import type * as Types from './graphql-code-generator/path-to-other-file'; type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ - input?: TypeImport.UserInput | null | undefined; + input?: Types.UserInput | null | undefined; }>; @@ -501,7 +486,6 @@ describe('TypeScript Operations Plugin - Import Types with external custom Scala [{ document }], { importSchemaTypesFrom: './path-to-other-file', - namespacedImportName: 'TypeImport', scalars: { Scalar1: '@org/scalars#Scalar1', }, @@ -572,7 +556,6 @@ describe('TypeScript Operations Plugin - Import Types with external custom Scala [{ document }], { importSchemaTypesFrom: './path-to-other-file', - namespacedImportName: 'TypeImport', scalars: { Scalar1: '@org/scalars#Scalar1', }, @@ -592,4 +575,62 @@ describe('TypeScript Operations Plugin - Import Types with external custom Scala `); validateTs(operationFileResult, undefined, undefined, undefined, undefined, true); }); + + it('uses `namespacedImportName` correctly to name the import type', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + } + + type User { + id: ID! + name: String! + role: UserRole! + createdAt: DateTime! + } + + enum UserRole { + ADMIN + CUSTOMER + } + + scalar DateTime + `); + const document = parse(/* GraphQL */ ` + query User($id: ID!) { + user(id: $id) { + id + name + role + createdAt + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + importSchemaTypesFrom: './base-dir/path-to-other-file.generated.ts', + namespacedImportName: 'TypeImport', + }, + { outputFile: './base-dir/this-file.ts' } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "import type * as TypeImport from './path-to-other-file.generated'; + + type Exact = { [K in keyof T]: T[K] }; + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserQueryVariables = Exact<{ + id: string; + }>; + + + export type UserQuery = { user: { id: string, name: string, role: TypeImport.UserRole, createdAt: unknown } | null }; + " + `); + }); }); From 34b67bdbfde379414ad03a2448802e706f1e62a4 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Tue, 24 Feb 2026 23:46:54 +1100 Subject: [PATCH 41/69] [typescript-operations] Change default input ID scalar type (#10604) * Ensure input and variables use the same input scalars default * Add changeset --- .changeset/stale-regions-bow.md | 6 +++++ .../src/base-documents-visitor.ts | 9 +++++--- .../visitor-plugin-common/src/scalars.ts | 23 +++++++++++++++++++ .../src/ts-operation-variables-to-object.ts | 11 ++------- .../typescript/operations/src/visitor.ts | 13 ++++++----- .../__snapshots__/ts-documents.spec.ts.snap | 4 ++-- .../tests/extract-all-types.spec.ts | 2 +- ...s.standalone.config.avoidOptionals.spec.ts | 18 +++++++-------- ...-documents.standalone.import-types.spec.ts | 8 +++---- .../ts-documents.standalone.input.spec.ts | 10 ++++++++ .../tests/ts-documents.standalone.spec.ts | 8 +++---- 11 files changed, 74 insertions(+), 38 deletions(-) create mode 100644 .changeset/stale-regions-bow.md diff --git a/.changeset/stale-regions-bow.md b/.changeset/stale-regions-bow.md new file mode 100644 index 00000000000..612da8f1e04 --- /dev/null +++ b/.changeset/stale-regions-bow.md @@ -0,0 +1,6 @@ +--- +'@graphql-codegen/visitor-plugin-common': patch +'@graphql-codegen/typescript-operations': patch +--- + +Ensure Input and Variables use the same input scalars default e.g. `ID` can take `string | number` diff --git a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts index f5c2f1a8f08..b70d716d272 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts @@ -8,7 +8,7 @@ import { VariableDefinitionNode, } from 'graphql'; import { BaseVisitor, type ParsedConfig, type RawConfig } from './base-visitor.js'; -import { DEFAULT_SCALARS } from './scalars.js'; +import { DEFAULT_INPUT_SCALARS } from './scalars.js'; import { SelectionSetToObject } from './selection-set-to-object.js'; import { CustomDirectivesConfig, NormalizedScalarsMap } from './types.js'; import { @@ -268,7 +268,7 @@ export class BaseDocumentsVisitor< rawConfig: TRawConfig, additionalConfig: TPluginConfig, protected _schema: GraphQLSchema, - defaultScalars: NormalizedScalarsMap = DEFAULT_SCALARS, + defaultScalars: NormalizedScalarsMap = DEFAULT_INPUT_SCALARS, ) { const importSchemaTypesFrom = getConfigValue(rawConfig.importSchemaTypesFrom, ''); @@ -285,7 +285,10 @@ export class BaseDocumentsVisitor< customDirectives: getConfigValue(rawConfig.customDirectives, { apolloUnmask: false }), generateOperationTypes: getConfigValue(rawConfig.generateOperationTypes, true), importSchemaTypesFrom, - namespacedImportName: getConfigValue(rawConfig.namespacedImportName, importSchemaTypesFrom ? 'Types' : null), + namespacedImportName: getConfigValue( + rawConfig.namespacedImportName, + importSchemaTypesFrom ? 'Types' : null, + ), extractAllFieldsToTypes: getConfigValue(rawConfig.extractAllFieldsToTypes, false) || getConfigValue(rawConfig.extractAllFieldsToTypesCompact, false), diff --git a/packages/plugins/other/visitor-plugin-common/src/scalars.ts b/packages/plugins/other/visitor-plugin-common/src/scalars.ts index e58f82790ed..eb1b6bfa11e 100644 --- a/packages/plugins/other/visitor-plugin-common/src/scalars.ts +++ b/packages/plugins/other/visitor-plugin-common/src/scalars.ts @@ -22,3 +22,26 @@ export const DEFAULT_SCALARS: NormalizedScalarsMap = { output: 'number', }, }; + +export const DEFAULT_INPUT_SCALARS: NormalizedScalarsMap = { + ID: { + input: 'string | number', + output: 'string', + }, + String: { + input: 'string', + output: 'string', + }, + Boolean: { + input: 'boolean', + output: 'boolean', + }, + Int: { + input: 'number', + output: 'number', + }, + Float: { + input: 'number', + output: 'number', + }, +}; diff --git a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts index bea9ac89877..d3147b3928f 100644 --- a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts +++ b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts @@ -5,17 +5,10 @@ import { OperationVariablesToObject, ParsedEnumValuesMap, printTypeScriptMaybeType, + DEFAULT_INPUT_SCALARS, } from '@graphql-codegen/visitor-plugin-common'; import type { NormalizedAvoidOptionalsConfig } from './config.avoidOptionals'; -export const SCALARS = { - ID: 'string | number', - String: 'string', - Int: 'number', - Float: 'number', - Boolean: 'boolean', -}; - export class TypeScriptOperationVariablesToObject extends OperationVariablesToObject { constructor( private _config: { @@ -80,7 +73,7 @@ export class TypeScriptOperationVariablesToObject extends OperationVariablesToOb } protected getScalar(name: string): string { - return this._scalars[name]?.input ?? SCALARS[name] ?? 'unknown'; + return this._scalars[name]?.input ?? DEFAULT_INPUT_SCALARS[name].input ?? 'unknown'; } protected getPunctuation(): string { diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 9c28558d06e..74f09e0451d 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -26,6 +26,7 @@ import { convertSchemaEnumToDeclarationBlockString, DeclarationBlock, DeclarationKind, + DEFAULT_INPUT_SCALARS, generateFragmentImportStatement, generateImportStatement, getConfigValue, @@ -50,10 +51,7 @@ import { NormalizedAvoidOptionalsConfig, } from './config.avoidOptionals.js'; import type { TypeScriptDocumentsPluginConfig } from './config.js'; -import { - SCALARS, - TypeScriptOperationVariablesToObject, -} from './ts-operation-variables-to-object.js'; +import { TypeScriptOperationVariablesToObject } from './ts-operation-variables-to-object.js'; export interface TypeScriptDocumentsParsedConfig extends ParsedDocumentsConfig { arrayInputCoercion: boolean; @@ -568,7 +566,10 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< const scalarType = usedInputTypes[node.name] || { type: 'GraphQLScalarType', node, - tsType: (SCALARS[node.name] || this.config.scalars?.[node.name]?.input.type) ?? 'unknown', + tsType: + (DEFAULT_INPUT_SCALARS[node.name]?.input || + this.config.scalars?.[node.name]?.input.type) ?? + 'unknown', useCases: { variables: location === 'variables', input: location === 'input', @@ -617,7 +618,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< } /** - * FIXME: This function is called `collectUsedInputTypes`, but it collects the types used in Result (SelectionSet) as well: + * FIXME: eddeee888 This function is called `collectUsedInputTypes`, but it collects the types used in Result (SelectionSet) as well: * - used Enums for Variables * - used Scalars for Variables * - used Input for Variables diff --git a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap index 0832c48df20..e15d308cbc5 100644 --- a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap +++ b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap @@ -12,8 +12,8 @@ export type TextNotificationFragmentFragmentVariables = Exact<{ exports[`TypeScript Operations Plugin > Issues > #2699 - Issues with multiple interfaces and unions 1`] = ` "export type GetEntityBrandDataQueryVariables = Exact<{ - gid: string; - brand: string; + gid: string | number; + brand: string | number; }>; diff --git a/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts b/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts index 98417731685..b5fd484f026 100644 --- a/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts @@ -1666,7 +1666,7 @@ describe('extractAllFieldsToTypesCompact: true', () => { export type GetCompanyInfoVariables = Exact<{ - id: string; + id: string | number; }>; " `); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.avoidOptionals.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.avoidOptionals.spec.ts index a41d8e9cc04..e4f659b2309 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.avoidOptionals.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.avoidOptionals.spec.ts @@ -58,8 +58,8 @@ describe('TypeScript Operations Plugin - config.avoidOptionals', () => { }; export type UserQueryVariables = Exact<{ - testNullable?: string | null | undefined; - testNonNullable: string; + testNullable?: string | number | null | undefined; + testNonNullable: string | number; inputNullable?: UserInput | null | undefined; inputNonNullable: UserInput; }>; @@ -126,8 +126,8 @@ describe('TypeScript Operations Plugin - config.avoidOptionals', () => { }; export type UserQueryVariables = Exact<{ - testNullable: string | null | undefined; - testNonNullable: string; + testNullable: string | number | null | undefined; + testNonNullable: string | number; inputNullable: UserInput | null | undefined; inputNonNullable: UserInput; }>; @@ -205,7 +205,7 @@ describe('TypeScript Operations Plugin - config.avoidOptionals', () => { }; export type UserQueryVariables = Exact<{ - test?: string | null | undefined; + test?: string | number | null | undefined; input?: UserInput | null | undefined; }>; @@ -282,7 +282,7 @@ describe('TypeScript Operations Plugin - config.avoidOptionals', () => { }; export type UserQueryVariables = Exact<{ - test?: string | null | undefined; + test?: string | number | null | undefined; input?: UserInput | null | undefined; }>; @@ -359,7 +359,7 @@ describe('TypeScript Operations Plugin - config.avoidOptionals', () => { }; export type UserQueryVariables = Exact<{ - test: string | null | undefined; + test: string | number | null | undefined; input: UserInput | null | undefined; }>; @@ -442,8 +442,8 @@ describe('TypeScript Operations Plugin - config.avoidOptionals', () => { }; export type UserQueryVariables = Exact<{ - test: string | null | undefined; - testWithDefault?: string | null | undefined; + test: string | number | null | undefined; + testWithDefault?: string | number | null | undefined; input: UserInput | null | undefined; inputWithDefault?: UserInput | null | undefined; }>; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts index 26d755d447d..efd54f316a6 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts @@ -105,7 +105,7 @@ describe('TypeScript Operations Plugin - Import Types', () => { type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ - id: string; + id: string | number; }>; @@ -237,7 +237,7 @@ describe('TypeScript Operations Plugin - Import Types', () => { type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ - id: string; + id: string | number; }>; @@ -343,7 +343,7 @@ describe('TypeScript Operations Plugin - Import Types', () => { "type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ - id?: string | null | undefined; + id?: string | number | null | undefined; name?: string | null | undefined; bool?: boolean | null | undefined; int?: number | null | undefined; @@ -625,7 +625,7 @@ describe('TypeScript Operations Plugin - Import Types with external custom Scala type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ - id: string; + id: string | number; }>; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts index c77972b6537..fa84ec8d629 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts @@ -28,6 +28,8 @@ describe('TypeScript Operations Plugin - Input', () => { "UsersInput Description" input UsersInput { + idNonNullable: ID! + idNullable: ID "UsersInput from" from: DateTime "UsersInput to" @@ -51,6 +53,8 @@ describe('TypeScript Operations Plugin - Input', () => { `); const document = parse(/* GraphQL */ ` query UsersWithScalarInput( + $idNonNullable: ID! + $idNullable: ID $inputNonNullable: UsersInput! $inputNullable: UsersInput $ageRange1: [Int] @@ -59,6 +63,8 @@ describe('TypeScript Operations Plugin - Input', () => { $ageRange4: [Int!]! ) { users( + idNonNullable: $idNonNullable + idNullable: $idNullable input: $inputNonNullable ageRange1: $ageRange1 ageRange2: $ageRange2 @@ -98,6 +104,8 @@ describe('TypeScript Operations Plugin - Input', () => { /** UsersInput Description */ export type UsersInput = { + idNonNullable: string | number; + idNullable?: string | number | null | undefined; /** UsersInput from */ from?: Date | null | undefined; /** UsersInput to */ @@ -117,6 +125,8 @@ describe('TypeScript Operations Plugin - Input', () => { }; export type UsersWithScalarInputQueryVariables = Exact<{ + idNonNullable: string | number; + idNullable?: string | number | null | undefined; inputNonNullable: UsersInput; inputNullable?: UsersInput | null | undefined; ageRange1?: Array | number | null | undefined; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts index b9ca78b04bc..add6723dd06 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -145,7 +145,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { }; export type UserQueryVariables = Exact<{ - id: string; + id: string | number; }>; @@ -358,7 +358,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { export type UserQueryVariables = Exact<{ - id: string; + id: string | number; }>; @@ -797,7 +797,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { "type Exact = { [K in keyof T]: T[K] }; export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ - id: string; + id: string | number; }>; @@ -897,7 +897,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { | 'CUSTOMER'; export type UserQueryVariables = Exact<{ - id: string; + id: string | number; }>; From 551e53b2c25cfb334df2d95d90271bd1b00a44e4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 25 Feb 2026 12:36:31 +0000 Subject: [PATCH 42/69] chore(dependencies): updated changesets for modified dependencies --- ...@graphql-codegen_typescript-operations-10496-dependencies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md b/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md index 47502ec48d5..f2fbe6cd647 100644 --- a/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md +++ b/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md @@ -3,4 +3,4 @@ --- dependencies updates: - Added dependency [`@graphql-codegen/schema-ast@^5.0.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/schema-ast/v/5.0.0) (to `dependencies`) - - Removed dependency [`@graphql-codegen/typescript@^5.0.7` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.7) (from `dependencies`) + - Removed dependency [`@graphql-codegen/typescript@^5.0.8` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.8) (from `dependencies`) From 521f474cc7a24f96077c93d711bbbf615c31e8aa Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Thu, 26 Feb 2026 01:00:52 +1100 Subject: [PATCH 43/69] Fix lint issue --- dev-test-apollo-tooling/cli/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dev-test-apollo-tooling/cli/index.ts b/dev-test-apollo-tooling/cli/index.ts index 6c36c92470b..28db8968dd6 100644 --- a/dev-test-apollo-tooling/cli/index.ts +++ b/dev-test-apollo-tooling/cli/index.ts @@ -41,6 +41,7 @@ export const main = async () => { const generatePaths: { [scanPath: string]: Types.ConfiguredOutput } = {}; // Prepare the required structure for GraphQL Codegen + // eslint-disable-next-line unicorn/no-array-for-each includes.forEach((include: string) => { generatePaths[include] = { preset: 'near-operation-file', // This preset tells the codegen to generate multiple files instead of one @@ -74,6 +75,7 @@ export const main = async () => { if (import.meta.url === process.argv[1] || import.meta.url === `file://${process.argv[1]}`) { main().catch(e => { + // eslint-disable-next-line no-console console.error(e); process.exit(1); }); From a2f87919f584d0b5e842fcc2916851a84ebe9974 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Fri, 27 Feb 2026 00:09:03 +1100 Subject: [PATCH 44/69] Fix unit tests (#10606) --- .../operations/tests/extract-all-types.spec.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts b/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts index b5fd484f026..a4bebc6780f 100644 --- a/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts @@ -1375,9 +1375,9 @@ describe('extractAllFieldsToTypes: true', () => { expect(content).toMatchInlineSnapshot(` "export type GetFragmentPetFragment_Pet_home_House = { __typename: 'House', id: string }; - type GetFragmentPet_Dog_Fragment = { __typename: 'Dog', id: string, home?: GetFragmentPetFragment_Pet_home_House | null }; + type GetFragmentPet_Dog_Fragment = { __typename: 'Dog', id: string, home: GetFragmentPetFragment_Pet_home_House | null }; - type GetFragmentPet_Cat_Fragment = { __typename: 'Cat', id: string, home?: GetFragmentPetFragment_Pet_home_House | null }; + type GetFragmentPet_Cat_Fragment = { __typename: 'Cat', id: string, home: GetFragmentPetFragment_Pet_home_House | null }; export type GetFragmentPetFragment = | GetFragmentPet_Dog_Fragment @@ -1386,20 +1386,20 @@ describe('extractAllFieldsToTypes: true', () => { export type GetPetDataQuery_pet_Pet_home_House = { __typename: 'House', id: string }; - export type GetPetDataQuery_pet_Dog = { __typename: 'Dog', id: string, home?: GetPetDataQuery_pet_Pet_home_House | null }; + export type GetPetDataQuery_pet_Dog = { __typename: 'Dog', id: string, home: GetPetDataQuery_pet_Pet_home_House | null }; - export type GetPetDataQuery_pet_Cat = { __typename: 'Cat', id: string, home?: GetPetDataQuery_pet_Pet_home_House | null }; + export type GetPetDataQuery_pet_Cat = { __typename: 'Cat', id: string, home: GetPetDataQuery_pet_Pet_home_House | null }; export type GetPetDataQuery_pet = | GetPetDataQuery_pet_Dog | GetPetDataQuery_pet_Cat ; - export type GetPetDataQuery_Query = { __typename: 'Query', pet?: GetPetDataQuery_pet | null }; + export type GetPetDataQuery_Query = { __typename: 'Query', pet: GetPetDataQuery_pet | null }; export type GetPetDataQueryVariables = Exact<{ - petId: Scalars['ID']['input']; + petId: string | number; }>; From 4d5e240425c76697939b15abaac11445623dd41d Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Tue, 3 Mar 2026 23:46:14 +1100 Subject: [PATCH 45/69] [client-preset] Update client preset doc and clean up deps (#10608) * Remove typescript plugin from client-preset as no longer used * Update client-preset doc * Add changeset * chore(dependencies): updated changesets for modified dependencies --------- Co-authored-by: github-actions[bot] --- ...odegen_client-preset-10608-dependencies.md | 5 ++ .changeset/seven-wombats-tie.md | 5 ++ .../pages/plugins/presets/preset-client.mdx | 65 ++++++++----------- 3 files changed, 38 insertions(+), 37 deletions(-) create mode 100644 .changeset/@graphql-codegen_client-preset-10608-dependencies.md create mode 100644 .changeset/seven-wombats-tie.md diff --git a/.changeset/@graphql-codegen_client-preset-10608-dependencies.md b/.changeset/@graphql-codegen_client-preset-10608-dependencies.md new file mode 100644 index 00000000000..d3a31ec2973 --- /dev/null +++ b/.changeset/@graphql-codegen_client-preset-10608-dependencies.md @@ -0,0 +1,5 @@ +--- +"@graphql-codegen/client-preset": patch +--- +dependencies updates: + - Removed dependency [`@graphql-codegen/typescript@^5.0.8` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.8) (from `dependencies`) diff --git a/.changeset/seven-wombats-tie.md b/.changeset/seven-wombats-tie.md new file mode 100644 index 00000000000..4291aa63ff0 --- /dev/null +++ b/.changeset/seven-wombats-tie.md @@ -0,0 +1,5 @@ +--- +'@graphql-codegen/client-preset': patch +--- + +Remove @graphql-codegen/typescript from client-preset dep as the preset no longer uses the plugin. diff --git a/website/src/pages/plugins/presets/preset-client.mdx b/website/src/pages/plugins/presets/preset-client.mdx index 82ab461934a..b956cd3d3aa 100644 --- a/website/src/pages/plugins/presets/preset-client.mdx +++ b/website/src/pages/plugins/presets/preset-client.mdx @@ -48,53 +48,44 @@ For step-by-step instructions, please [refer to our dedicated guide](/docs/guide The `client` preset allows the following `config` options: -- [`scalars`](/plugins/typescript/typescript#scalars): Extends or overrides the built-in scalars and - custom GraphQL scalars to a custom type. -- [`defaultScalarType`](/plugins/typescript/typescript#defaultscalartype): Allows you to override - the type that unknown `scalars` will have. Defaults to `any`. -- [`strictScalars`](/plugins/typescript/typescript#strictscalars): If `scalars` are found in the - schema that are not defined in scalars an error will be thrown during codegen. -- [`namingConvention`](/plugins/typescript/typescript#namingconvention): Available case functions in - `change-case-all` are `camelCase`, `capitalCase`, `constantCase`, `dotCase`, `headerCase`, - `noCase`, `paramCase`, `pascalCase`, `pathCase`, `sentenceCase`, `snakeCase`, `lowerCase`, - `localeLowerCase`, `lowerCaseFirst`, `spongeCase`, `titleCase`, `upperCase`, `localeUpperCase` and - `upperCaseFirst`. -- [`useTypeImports`](/plugins/typescript/typescript#usetypeimports): Will use `import type {}` - rather than `import {}` when importing only types. This gives compatibility with TypeScript's +- [`scalars`](/plugins/typescript/typescript-operations#scalars): Extends or overrides the built-in + scalars and custom GraphQL scalars to a custom type. +- [`defaultScalarType`](/plugins/typescript/typescript-operations#defaultscalartype): Allows you to + override the type that unknown `scalars` will have. Defaults to `any`. +- [`strictScalars`](/plugins/typescript/typescript-operations#strictscalars): If `scalars` are found + in the schema that are not defined in scalars an error will be thrown during codegen. +- [`namingConvention`](/plugins/typescript/typescript-operations#namingconvention): Available case + functions in `change-case-all` are `camelCase`, `capitalCase`, `constantCase`, `dotCase`, + `headerCase`, `noCase`, `paramCase`, `pascalCase`, `pathCase`, `sentenceCase`, `snakeCase`, + `lowerCase`, `localeLowerCase`, `lowerCaseFirst`, `spongeCase`, `titleCase`, `upperCase`, + `localeUpperCase` and `upperCaseFirst`. +- [`useTypeImports`](/plugins/typescript/typescript-operations#usetypeimports): Will use + `import type {}` rather than `import {}` when importing only types. This gives compatibility with + TypeScript's [`"importsNotUsedAsValues": "error"`](https://www.typescriptlang.org/tsconfig#importsNotUsedAsValues) option. -- [`immutableTypes`](/plugins/typescript/typescript#immutabletypes): Generates immutable types by - adding `readonly` to properties and `ReadonlyArray` for lists. -- [`skipTypename`](/plugins/typescript/typescript#skiptypename): Does not add `__typename` to the - generated types, unless it was specified in the selection set. +- [`immutableTypes`](/plugins/typescript/typescript-operations#immutabletypes): Generates immutable + types by adding `readonly` to properties and `ReadonlyArray` for lists. - [`arrayInputCoercion`](/plugins/typescript/typescript-operations#arrayinputcoercion): The [GraphQL spec](https://spec.graphql.org/draft/#sel-FAHjBJFCAACE_Gh7d) allows arrays and a single primitive value for list input. This allows to deactivate that behavior to only accept arrays instead of single values. -- [`enumsAsTypes`](/plugins/typescript/typescript#enumsastypes): Generates enum as TypeScript string - union `type` instead of an `enum`. Useful if you wish to generate `.d.ts` declaration file instead - of `.ts`, or if you want to avoid using TypeScript enums due to bundle size concerns. -- [`enumsAsConst`](/plugins/typescript/typescript#enumsasconst): Generates enum as TypeScript const - assertions instead of enum. This can even be used to enable enum-like patterns in plain JavaScript - code if you choose not to use TypeScript’s enum construct. -- [`enumValues`](/plugins/typescript/typescript#enumvalues): Overrides the default value of enum - values declared in your GraphQL schema. You can also map the entire enum to an external type by - providing a string that of module#type. -- [`futureProofEnums`](/plugins/typescript/typescript#futureproofenums): Adds a catch-all entry to - enum type definitions for values that may be added in the future. -- [`nonOptionalTypename`](/plugins/typescript/typescript#nonoptionaltypename): Automatically adds - `__typename` field to the generated types, even when they are not specified in the selection set, - and makes it non-optional. -- [`avoidOptionals`](/plugins/typescript/typescript#avoidoptionals): This will cause the generator - to avoid using TypeScript optionals (`?`) on types. +- [`enumType`](/plugins/typescript/typescript-operations#enumType): Changes how TypeScript enums are + generated. +- [`enumValues`](/plugins/typescript/typescript-operations#enumvalues): Overrides the default value + of enum values declared in your GraphQL schema. You can also map the entire enum to an external + type by providing a string that of module#type. +- [`futureProofEnums`](/plugins/typescript/typescrip-operations#futureproofenums): Adds a catch-all + entry to enum type definitions for values that may be added in the future. +- [`nonOptionalTypename`](/plugins/typescript/typescript-operations#nonoptionaltypename): + Automatically adds `__typename` field to the generated types, even when they are not specified in + the selection set, and makes it non-optional. +- [`avoidOptionals`](/plugins/typescript/typescript-operations#avoidoptionals): This will cause the + generator to avoid using TypeScript optionals (`?`) on types. - [`documentMode`](#documentmode): Allows you to control how the documents are generated. - [`skipTypeNameForRoot`](/plugins/typescript/typescript-operations#skiptypenameforroot): Avoid adding `__typename` for root types. This is ignored when a selection explicitly specifies `__typename`. -- [`onlyOperationTypes`](/plugins/typescript/typescript#onlyoperationtypes): This will cause the - generator to emit types required for operations only i.e. only enums and scalars. -- [`onlyEnums`](/plugins/typescript/typescript#onlyenums): This will cause the generator to emit - types for enums only. - [`customDirectives`](/plugins/typescript/typescript-operations#customdirectives): Configures behavior for use with custom directives from various GraphQL libraries, such as Apollo Client's [@unmask](https://www.apollographql.com/docs/react/data/directives#unmask). From 1674416cffb596a824a7f8c26a76d9abf4ff8228 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 3 Mar 2026 12:47:34 +0000 Subject: [PATCH 46/69] chore(dependencies): updated changesets for modified dependencies --- .../@graphql-codegen_client-preset-10496-dependencies.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/@graphql-codegen_client-preset-10496-dependencies.md diff --git a/.changeset/@graphql-codegen_client-preset-10496-dependencies.md b/.changeset/@graphql-codegen_client-preset-10496-dependencies.md new file mode 100644 index 00000000000..d3a31ec2973 --- /dev/null +++ b/.changeset/@graphql-codegen_client-preset-10496-dependencies.md @@ -0,0 +1,5 @@ +--- +"@graphql-codegen/client-preset": patch +--- +dependencies updates: + - Removed dependency [`@graphql-codegen/typescript@^5.0.8` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.8) (from `dependencies`) From 9a75addbe91f5e76b1dc30b7c4351cf7eefdcc54 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Wed, 4 Mar 2026 00:12:55 +1100 Subject: [PATCH 47/69] [client-preset] Fix docs for upcoming major release (#10609) * Fix enumValues doc issue * fix link issues in client preset doc * Move nonOptionalTypename and skipTypeNameForRoot together in the doc for ease of read --- packages/plugins/typescript/operations/src/config.ts | 2 ++ website/src/pages/plugins/presets/preset-client.mdx | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/plugins/typescript/operations/src/config.ts b/packages/plugins/typescript/operations/src/config.ts index b792a6973c1..482228cd6d9 100644 --- a/packages/plugins/typescript/operations/src/config.ts +++ b/packages/plugins/typescript/operations/src/config.ts @@ -368,8 +368,10 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { * } * } * export default config + * ``` */ enumType?: ConvertSchemaEnumToDeclarationBlockString['outputType']; + /** * @description Overrides the default value of enum values declared in your GraphQL schema. * You can also map the entire enum to an external type by providing a string that of `module#type`. diff --git a/website/src/pages/plugins/presets/preset-client.mdx b/website/src/pages/plugins/presets/preset-client.mdx index b956cd3d3aa..145514d4004 100644 --- a/website/src/pages/plugins/presets/preset-client.mdx +++ b/website/src/pages/plugins/presets/preset-client.mdx @@ -70,19 +70,19 @@ The `client` preset allows the following `config` options: [GraphQL spec](https://spec.graphql.org/draft/#sel-FAHjBJFCAACE_Gh7d) allows arrays and a single primitive value for list input. This allows to deactivate that behavior to only accept arrays instead of single values. -- [`enumType`](/plugins/typescript/typescript-operations#enumType): Changes how TypeScript enums are +- [`enumType`](/plugins/typescript/typescript-operations#enumtype): Changes how TypeScript enums are generated. - [`enumValues`](/plugins/typescript/typescript-operations#enumvalues): Overrides the default value of enum values declared in your GraphQL schema. You can also map the entire enum to an external type by providing a string that of module#type. -- [`futureProofEnums`](/plugins/typescript/typescrip-operations#futureproofenums): Adds a catch-all +- [`futureProofEnums`](/plugins/typescript/typescript-operations#futureproofenums): Adds a catch-all entry to enum type definitions for values that may be added in the future. -- [`nonOptionalTypename`](/plugins/typescript/typescript-operations#nonoptionaltypename): - Automatically adds `__typename` field to the generated types, even when they are not specified in - the selection set, and makes it non-optional. - [`avoidOptionals`](/plugins/typescript/typescript-operations#avoidoptionals): This will cause the generator to avoid using TypeScript optionals (`?`) on types. - [`documentMode`](#documentmode): Allows you to control how the documents are generated. +- [`nonOptionalTypename`](/plugins/typescript/typescript-operations#nonoptionaltypename): + Automatically adds `__typename` field to the generated types, even when they are not specified in + the selection set, and makes it non-optional. - [`skipTypeNameForRoot`](/plugins/typescript/typescript-operations#skiptypenameforroot): Avoid adding `__typename` for root types. This is ignored when a selection explicitly specifies `__typename`. From 3c8169218ab0b8c08c28dccc5f0c5de80cbf9b1d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 8 Mar 2026 04:28:59 +0000 Subject: [PATCH 48/69] chore(dependencies): updated changesets for modified dependencies --- .../@graphql-codegen_client-preset-10496-dependencies.md | 2 +- ...raphql-codegen_typescript-operations-10496-dependencies.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.changeset/@graphql-codegen_client-preset-10496-dependencies.md b/.changeset/@graphql-codegen_client-preset-10496-dependencies.md index d3a31ec2973..bfcc839c224 100644 --- a/.changeset/@graphql-codegen_client-preset-10496-dependencies.md +++ b/.changeset/@graphql-codegen_client-preset-10496-dependencies.md @@ -2,4 +2,4 @@ "@graphql-codegen/client-preset": patch --- dependencies updates: - - Removed dependency [`@graphql-codegen/typescript@^5.0.8` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.8) (from `dependencies`) + - Removed dependency [`@graphql-codegen/typescript@^5.0.9` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.9) (from `dependencies`) diff --git a/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md b/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md index f2fbe6cd647..28e7577253f 100644 --- a/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md +++ b/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md @@ -2,5 +2,5 @@ "@graphql-codegen/typescript-operations": patch --- dependencies updates: - - Added dependency [`@graphql-codegen/schema-ast@^5.0.0` ↗︎](https://www.npmjs.com/package/@graphql-codegen/schema-ast/v/5.0.0) (to `dependencies`) - - Removed dependency [`@graphql-codegen/typescript@^5.0.8` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.8) (from `dependencies`) + - Added dependency [`@graphql-codegen/schema-ast@^5.0.1` ↗︎](https://www.npmjs.com/package/@graphql-codegen/schema-ast/v/5.0.1) (to `dependencies`) + - Removed dependency [`@graphql-codegen/typescript@^5.0.9` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.9) (from `dependencies`) From 9e8c8cc696c2b9d05ec8d2dd40586ac4aad40397 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Sun, 8 Mar 2026 21:46:58 +1100 Subject: [PATCH 49/69] Bring in latest near-operation-file preset (#10621) --- dev-test-apollo-tooling/cli/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/dev-test-apollo-tooling/cli/index.ts b/dev-test-apollo-tooling/cli/index.ts index 28db8968dd6..50b6bd525da 100644 --- a/dev-test-apollo-tooling/cli/index.ts +++ b/dev-test-apollo-tooling/cli/index.ts @@ -48,7 +48,6 @@ export const main = async () => { presetConfig: { extension: '.ts', folder: GENERATED, // Output folder for generated files - importTypesNamespace: '', // Disable namespace prefix on imported types }, plugins: [ 'typescript-operations', From 55dbd8b72425d7771d28b5c41127eba7b3bc22c8 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Wed, 11 Mar 2026 21:30:24 +1100 Subject: [PATCH 50/69] Master next fix native ast detection (#10637) * Fix isNativeNamedType function * Add changeset * Regen dev-tests --- .changeset/new-foxes-bake.md | 9 +++++++++ .../external-documents/app/types.generated.ts | 2 +- dev-test/githunt/typed-document-nodes.ts | 12 ++++++++++++ dev-test/githunt/types.avoidOptionals.ts | 12 ++++++++++++ dev-test/githunt/types.d.ts | 12 ++++++++++++ dev-test/githunt/types.enumsAsTypes.ts | 12 ++++++++++++ .../githunt/types.flatten.preResolveTypes.ts | 12 ++++++++++++ dev-test/githunt/types.immutableTypes.ts | 12 ++++++++++++ dev-test/githunt/types.onlyEnums.ts | 15 +++++---------- .../types.preResolveTypes.onlyOperationTypes.ts | 12 ++++++++++++ dev-test/githunt/types.preResolveTypes.ts | 12 ++++++++++++ dev-test/githunt/types.ts | 12 ++++++++++++ dev-test/star-wars/types.avoidOptionals.ts | 17 +++++++++++++++++ dev-test/star-wars/types.excludeQueryAlpha.ts | 17 +++++++++++++++++ dev-test/star-wars/types.excludeQueryBeta.ts | 17 +++++++++++++++++ dev-test/star-wars/types.globallyAvailable.d.ts | 17 +++++++++++++++++ dev-test/star-wars/types.immutableTypes.ts | 17 +++++++++++++++++ .../types.preResolveTypes.onlyOperationTypes.ts | 17 +++++++++++++++++ dev-test/star-wars/types.preResolveTypes.ts | 17 +++++++++++++++++ dev-test/star-wars/types.skipSchema.ts | 17 +++++++++++++++++ dev-test/star-wars/types.ts | 17 +++++++++++++++++ .../src/graphql-type-utils.ts | 3 +-- 22 files changed, 277 insertions(+), 13 deletions(-) create mode 100644 .changeset/new-foxes-bake.md diff --git a/.changeset/new-foxes-bake.md b/.changeset/new-foxes-bake.md new file mode 100644 index 00000000000..c3355eb01a1 --- /dev/null +++ b/.changeset/new-foxes-bake.md @@ -0,0 +1,9 @@ +--- +'@graphql-codegen/visitor-plugin-common': patch +--- + +Fix isNativeNamedType to handle types from remote schemas correctly + +Previously, we assumed that if a name type does note have `astNode`, it is a native named type because it is not declared in user's schema. + +However, this is a wrong assumption because remote schemas do not have `astNode`. This causes all user declared types are wrongly recognised as native types e.g. Input diff --git a/dev-test/external-documents/app/types.generated.ts b/dev-test/external-documents/app/types.generated.ts index 2c99a5e5866..5f685f2c710 100644 --- a/dev-test/external-documents/app/types.generated.ts +++ b/dev-test/external-documents/app/types.generated.ts @@ -5,7 +5,7 @@ export type Incremental = export type UserRole = 'ADMIN' | 'CUSTOMER'; export type UserQueryVariables = Exact<{ - id: string; + id: string | number; }>; export type UserQuery = { user: { id: string; name: string; role: UserRole } | null }; diff --git a/dev-test/githunt/typed-document-nodes.ts b/dev-test/githunt/typed-document-nodes.ts index f4908eadb66..1c07b674e35 100644 --- a/dev-test/githunt/typed-document-nodes.ts +++ b/dev-test/githunt/typed-document-nodes.ts @@ -4,6 +4,18 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** A list of options for the sort order of the feed */ +export type FeedType = + /** Sort by a combination of freshness and score, using Reddit's algorithm */ + | 'HOT' + /** Newest entries first */ + | 'NEW' + /** Highest score entries first */ + | 'TOP'; + +/** The type of vote to record, when submitting a vote */ +export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; + export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.avoidOptionals.ts b/dev-test/githunt/types.avoidOptionals.ts index e59e09522e2..765daed8ab9 100644 --- a/dev-test/githunt/types.avoidOptionals.ts +++ b/dev-test/githunt/types.avoidOptionals.ts @@ -2,6 +2,18 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** A list of options for the sort order of the feed */ +export type FeedType = + /** Sort by a combination of freshness and score, using Reddit's algorithm */ + | 'HOT' + /** Newest entries first */ + | 'NEW' + /** Highest score entries first */ + | 'TOP'; + +/** The type of vote to record, when submitting a vote */ +export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; + export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.d.ts b/dev-test/githunt/types.d.ts index e5ca456fdf7..9502cb33eaa 100644 --- a/dev-test/githunt/types.d.ts +++ b/dev-test/githunt/types.d.ts @@ -2,6 +2,18 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** A list of options for the sort order of the feed */ +export type FeedType = + /** Sort by a combination of freshness and score, using Reddit's algorithm */ + | 'HOT' + /** Newest entries first */ + | 'NEW' + /** Highest score entries first */ + | 'TOP'; + +/** The type of vote to record, when submitting a vote */ +export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; + export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.enumsAsTypes.ts b/dev-test/githunt/types.enumsAsTypes.ts index e5ca456fdf7..9502cb33eaa 100644 --- a/dev-test/githunt/types.enumsAsTypes.ts +++ b/dev-test/githunt/types.enumsAsTypes.ts @@ -2,6 +2,18 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** A list of options for the sort order of the feed */ +export type FeedType = + /** Sort by a combination of freshness and score, using Reddit's algorithm */ + | 'HOT' + /** Newest entries first */ + | 'NEW' + /** Highest score entries first */ + | 'TOP'; + +/** The type of vote to record, when submitting a vote */ +export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; + export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.flatten.preResolveTypes.ts b/dev-test/githunt/types.flatten.preResolveTypes.ts index 4689bd339ce..72391d2870b 100644 --- a/dev-test/githunt/types.flatten.preResolveTypes.ts +++ b/dev-test/githunt/types.flatten.preResolveTypes.ts @@ -2,6 +2,18 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** A list of options for the sort order of the feed */ +export type FeedType = + /** Sort by a combination of freshness and score, using Reddit's algorithm */ + | 'HOT' + /** Newest entries first */ + | 'NEW' + /** Highest score entries first */ + | 'TOP'; + +/** The type of vote to record, when submitting a vote */ +export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; + export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.immutableTypes.ts b/dev-test/githunt/types.immutableTypes.ts index 9b38ec4a08a..7980f4fe02a 100644 --- a/dev-test/githunt/types.immutableTypes.ts +++ b/dev-test/githunt/types.immutableTypes.ts @@ -2,6 +2,18 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** A list of options for the sort order of the feed */ +export type FeedType = + /** Sort by a combination of freshness and score, using Reddit's algorithm */ + | 'HOT' + /** Newest entries first */ + | 'NEW' + /** Highest score entries first */ + | 'TOP'; + +/** The type of vote to record, when submitting a vote */ +export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; + export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.onlyEnums.ts b/dev-test/githunt/types.onlyEnums.ts index 941573d8a76..1bd6a5f0fcd 100644 --- a/dev-test/githunt/types.onlyEnums.ts +++ b/dev-test/githunt/types.onlyEnums.ts @@ -1,16 +1,11 @@ /** A list of options for the sort order of the feed */ -export enum FeedType { +export type FeedType = /** Sort by a combination of freshness and score, using Reddit's algorithm */ - Hot = 'HOT', + | 'HOT' /** Newest entries first */ - New = 'NEW', + | 'NEW' /** Highest score entries first */ - Top = 'TOP', -} + | 'TOP'; /** The type of vote to record, when submitting a vote */ -export enum VoteType { - Cancel = 'CANCEL', - Down = 'DOWN', - Up = 'UP', -} +export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; diff --git a/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts index e5ca456fdf7..9502cb33eaa 100644 --- a/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts @@ -2,6 +2,18 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** A list of options for the sort order of the feed */ +export type FeedType = + /** Sort by a combination of freshness and score, using Reddit's algorithm */ + | 'HOT' + /** Newest entries first */ + | 'NEW' + /** Highest score entries first */ + | 'TOP'; + +/** The type of vote to record, when submitting a vote */ +export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; + export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.preResolveTypes.ts b/dev-test/githunt/types.preResolveTypes.ts index e5ca456fdf7..9502cb33eaa 100644 --- a/dev-test/githunt/types.preResolveTypes.ts +++ b/dev-test/githunt/types.preResolveTypes.ts @@ -2,6 +2,18 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** A list of options for the sort order of the feed */ +export type FeedType = + /** Sort by a combination of freshness and score, using Reddit's algorithm */ + | 'HOT' + /** Newest entries first */ + | 'NEW' + /** Highest score entries first */ + | 'TOP'; + +/** The type of vote to record, when submitting a vote */ +export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; + export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/githunt/types.ts b/dev-test/githunt/types.ts index e5ca456fdf7..9502cb33eaa 100644 --- a/dev-test/githunt/types.ts +++ b/dev-test/githunt/types.ts @@ -2,6 +2,18 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** A list of options for the sort order of the feed */ +export type FeedType = + /** Sort by a combination of freshness and score, using Reddit's algorithm */ + | 'HOT' + /** Newest entries first */ + | 'NEW' + /** Highest score entries first */ + | 'TOP'; + +/** The type of vote to record, when submitting a vote */ +export type VoteType = 'CANCEL' | 'DOWN' | 'UP'; + export type OnCommentAddedSubscriptionVariables = Exact<{ repoFullName: string; }>; diff --git a/dev-test/star-wars/types.avoidOptionals.ts b/dev-test/star-wars/types.avoidOptionals.ts index 7b6ff963688..b4a31e491e6 100644 --- a/dev-test/star-wars/types.avoidOptionals.ts +++ b/dev-test/star-wars/types.avoidOptionals.ts @@ -2,6 +2,13 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** The input object sent when passing a color */ +export type ColorInput = { + blue: number; + green: number; + red: number; +}; + /** The episodes in the Star Wars trilogy */ export type Episode = /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ @@ -11,6 +18,16 @@ export type Episode = /** Star Wars Episode IV: A New Hope, released in 1977. */ | 'NEWHOPE'; +/** The input object sent when someone is creating a new review */ +export type ReviewInput = { + /** Comment about the movie, optional */ + commentary: string | null | undefined; + /** Favorite color, optional */ + favoriteColor: ColorInput | null | undefined; + /** 0-5 stars */ + stars: number; +}; + export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.excludeQueryAlpha.ts b/dev-test/star-wars/types.excludeQueryAlpha.ts index eb57ff98370..87b55bd79c4 100644 --- a/dev-test/star-wars/types.excludeQueryAlpha.ts +++ b/dev-test/star-wars/types.excludeQueryAlpha.ts @@ -2,6 +2,13 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** The input object sent when passing a color */ +export type ColorInput = { + blue: number; + green: number; + red: number; +}; + /** The episodes in the Star Wars trilogy */ export type Episode = /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ @@ -11,6 +18,16 @@ export type Episode = /** Star Wars Episode IV: A New Hope, released in 1977. */ | 'NEWHOPE'; +/** The input object sent when someone is creating a new review */ +export type ReviewInput = { + /** Comment about the movie, optional */ + commentary?: string | null | undefined; + /** Favorite color, optional */ + favoriteColor?: ColorInput | null | undefined; + /** 0-5 stars */ + stars: number; +}; + export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.excludeQueryBeta.ts b/dev-test/star-wars/types.excludeQueryBeta.ts index e34e9d26455..dff78d508eb 100644 --- a/dev-test/star-wars/types.excludeQueryBeta.ts +++ b/dev-test/star-wars/types.excludeQueryBeta.ts @@ -2,6 +2,13 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** The input object sent when passing a color */ +export type ColorInput = { + blue: number; + green: number; + red: number; +}; + /** The episodes in the Star Wars trilogy */ export type Episode = /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ @@ -11,6 +18,16 @@ export type Episode = /** Star Wars Episode IV: A New Hope, released in 1977. */ | 'NEWHOPE'; +/** The input object sent when someone is creating a new review */ +export type ReviewInput = { + /** Comment about the movie, optional */ + commentary?: string | null | undefined; + /** Favorite color, optional */ + favoriteColor?: ColorInput | null | undefined; + /** 0-5 stars */ + stars: number; +}; + export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.globallyAvailable.d.ts b/dev-test/star-wars/types.globallyAvailable.d.ts index aab799829d6..ffc0449a7e8 100644 --- a/dev-test/star-wars/types.globallyAvailable.d.ts +++ b/dev-test/star-wars/types.globallyAvailable.d.ts @@ -2,6 +2,13 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** The input object sent when passing a color */ +type ColorInput = { + blue: number; + green: number; + red: number; +}; + /** The episodes in the Star Wars trilogy */ type Episode = /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ @@ -11,6 +18,16 @@ type Episode = /** Star Wars Episode IV: A New Hope, released in 1977. */ | 'NEWHOPE'; +/** The input object sent when someone is creating a new review */ +type ReviewInput = { + /** Comment about the movie, optional */ + commentary?: string | null | undefined; + /** Favorite color, optional */ + favoriteColor?: ColorInput | null | undefined; + /** 0-5 stars */ + stars: number; +}; + type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.immutableTypes.ts b/dev-test/star-wars/types.immutableTypes.ts index 3e72e723968..0e1b9b53e51 100644 --- a/dev-test/star-wars/types.immutableTypes.ts +++ b/dev-test/star-wars/types.immutableTypes.ts @@ -2,6 +2,13 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** The input object sent when passing a color */ +export type ColorInput = { + readonly blue: number; + readonly green: number; + readonly red: number; +}; + /** The episodes in the Star Wars trilogy */ export type Episode = /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ @@ -11,6 +18,16 @@ export type Episode = /** Star Wars Episode IV: A New Hope, released in 1977. */ | 'NEWHOPE'; +/** The input object sent when someone is creating a new review */ +export type ReviewInput = { + /** Comment about the movie, optional */ + readonly commentary?: string | null | undefined; + /** Favorite color, optional */ + readonly favoriteColor?: ColorInput | null | undefined; + /** 0-5 stars */ + readonly stars: number; +}; + export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts index 01475ff009f..7a45c0bd207 100644 --- a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts @@ -2,6 +2,13 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** The input object sent when passing a color */ +export type ColorInput = { + blue: number; + green: number; + red: number; +}; + /** The episodes in the Star Wars trilogy */ export type Episode = /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ @@ -11,6 +18,16 @@ export type Episode = /** Star Wars Episode IV: A New Hope, released in 1977. */ | 'NEWHOPE'; +/** The input object sent when someone is creating a new review */ +export type ReviewInput = { + /** Comment about the movie, optional */ + commentary?: string | null | undefined; + /** Favorite color, optional */ + favoriteColor?: ColorInput | null | undefined; + /** 0-5 stars */ + stars: number; +}; + export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.preResolveTypes.ts b/dev-test/star-wars/types.preResolveTypes.ts index 01475ff009f..7a45c0bd207 100644 --- a/dev-test/star-wars/types.preResolveTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.ts @@ -2,6 +2,13 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** The input object sent when passing a color */ +export type ColorInput = { + blue: number; + green: number; + red: number; +}; + /** The episodes in the Star Wars trilogy */ export type Episode = /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ @@ -11,6 +18,16 @@ export type Episode = /** Star Wars Episode IV: A New Hope, released in 1977. */ | 'NEWHOPE'; +/** The input object sent when someone is creating a new review */ +export type ReviewInput = { + /** Comment about the movie, optional */ + commentary?: string | null | undefined; + /** Favorite color, optional */ + favoriteColor?: ColorInput | null | undefined; + /** 0-5 stars */ + stars: number; +}; + export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.skipSchema.ts b/dev-test/star-wars/types.skipSchema.ts index 01475ff009f..7a45c0bd207 100644 --- a/dev-test/star-wars/types.skipSchema.ts +++ b/dev-test/star-wars/types.skipSchema.ts @@ -2,6 +2,13 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** The input object sent when passing a color */ +export type ColorInput = { + blue: number; + green: number; + red: number; +}; + /** The episodes in the Star Wars trilogy */ export type Episode = /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ @@ -11,6 +18,16 @@ export type Episode = /** Star Wars Episode IV: A New Hope, released in 1977. */ | 'NEWHOPE'; +/** The input object sent when someone is creating a new review */ +export type ReviewInput = { + /** Comment about the movie, optional */ + commentary?: string | null | undefined; + /** Favorite color, optional */ + favoriteColor?: ColorInput | null | undefined; + /** 0-5 stars */ + stars: number; +}; + export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/dev-test/star-wars/types.ts b/dev-test/star-wars/types.ts index 01475ff009f..7a45c0bd207 100644 --- a/dev-test/star-wars/types.ts +++ b/dev-test/star-wars/types.ts @@ -2,6 +2,13 @@ type Exact = { [K in keyof T]: T[K] }; export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; +/** The input object sent when passing a color */ +export type ColorInput = { + blue: number; + green: number; + red: number; +}; + /** The episodes in the Star Wars trilogy */ export type Episode = /** Star Wars Episode V: The Empire Strikes Back, released in 1980. */ @@ -11,6 +18,16 @@ export type Episode = /** Star Wars Episode IV: A New Hope, released in 1977. */ | 'NEWHOPE'; +/** The input object sent when someone is creating a new review */ +export type ReviewInput = { + /** Comment about the movie, optional */ + commentary?: string | null | undefined; + /** Favorite color, optional */ + favoriteColor?: ColorInput | null | undefined; + /** 0-5 stars */ + stars: number; +}; + export type CreateReviewForEpisodeMutationVariables = Exact<{ episode: Episode; review: ReviewInput; diff --git a/packages/plugins/other/visitor-plugin-common/src/graphql-type-utils.ts b/packages/plugins/other/visitor-plugin-common/src/graphql-type-utils.ts index 82634cd2849..9c2e2c175ea 100644 --- a/packages/plugins/other/visitor-plugin-common/src/graphql-type-utils.ts +++ b/packages/plugins/other/visitor-plugin-common/src/graphql-type-utils.ts @@ -4,8 +4,7 @@ export const isNativeNamedType = (namedType: GraphQLNamedType): boolean => { // "Native" NamedType in this context means the following: // 1. introspection types i.e. with `__` prefixes // 2. base scalars e.g. Boolean, Int, etc. - // 3. Other natives (mostly base scalars) which was not defined in the schema i.e. no `astNode` - if (isSpecifiedScalarType(namedType) || isIntrospectionType(namedType) || !namedType.astNode) { + if (isSpecifiedScalarType(namedType) || isIntrospectionType(namedType)) { return true; } From 94cae7b4558f5b48f8a2e19b63ac7777d9bbe8fe Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Thu, 12 Mar 2026 23:21:07 +1100 Subject: [PATCH 51/69] Rename function from collectUsedInputTypes to collectUsedSchemaTypesToGenerate to correctly reflect its functionality (#10640) --- .../typescript/operations/src/visitor.ts | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 74f09e0451d..deb611a78ec 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -67,7 +67,7 @@ export interface TypeScriptDocumentsParsedConfig extends ParsedDocumentsConfig { futureProofEnums: boolean; } -type UsedNamedInputTypes = Record< +type UsedSchemaTypes = Record< string, | { type: 'GraphQLScalarType'; @@ -83,7 +83,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< TypeScriptDocumentsPluginConfig, TypeScriptDocumentsParsedConfig > { - protected _usedNamedInputTypes: UsedNamedInputTypes = {}; + protected _usedSchemaTypes: UsedSchemaTypes = {}; protected _needsExactUtilityType: boolean = false; private _outputPath: string; @@ -143,7 +143,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< ], }; - this._usedNamedInputTypes = this.collectUsedInputTypes({ + this._usedSchemaTypes = this.collectUsedSchemaTypesToGenerate({ schema, documentNode: documentWithAllFragments, }); @@ -214,7 +214,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< EnumTypeDefinition(node: EnumTypeDefinitionNode): string | null { const enumName = node.name.value; if ( - !this._usedNamedInputTypes[enumName] || // If not used... + !this._usedSchemaTypes[enumName] || // If not used... this.config.importSchemaTypesFrom // ... Or, is imported from a shared file ) { return null; // ... then, don't generate in this file @@ -242,7 +242,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< InputObjectTypeDefinition(node: InputObjectTypeDefinitionNode): string | null { const inputTypeName = node.name.value; if ( - !this._usedNamedInputTypes[inputTypeName] || // If not used... + !this._usedSchemaTypes[inputTypeName] || // If not used... this.config.importSchemaTypesFrom // ... Or, is imported from a shared file ) { return null; // ... then, don't generate in this file @@ -305,7 +305,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< // We call `.reverse()` here to get the base type node first for (const typeNode of typeNodes.reverse()) { if (typeNode.type === 'NamedType') { - const usedInputType = this._usedNamedInputTypes[typeNode.name]; + const usedInputType = this._usedSchemaTypes[typeNode.name]; if (!usedInputType) { continue; } @@ -396,7 +396,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< } const hasTypesToImport = - Object.values(this._usedNamedInputTypes).filter( + Object.values(this._usedSchemaTypes).filter( value => value.type === 'GraphQLEnumType' || value.type === 'GraphQLInputObjectType', // Only Enums and Inputs are stored in the shared type file (never Scalar), so we should only print import line if Enums and Inputs are used. ).length > 0; @@ -427,7 +427,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< public getEnumsImports(): string[] { const usedEnumMap: ParsedEnumValuesMap = {}; for (const [enumName, enumDetails] of Object.entries(this.config.enumValues)) { - if (this._usedNamedInputTypes[enumName]) { + if (this._usedSchemaTypes[enumName]) { usedEnumMap[enumName] = enumDetails; } } @@ -462,7 +462,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< }; } = {}; for (const [scalarName, parsedScalar] of Object.entries(this.config.scalars)) { - const usedScalar = this._usedNamedInputTypes[scalarName]; + const usedScalar = this._usedSchemaTypes[scalarName]; if (!usedScalar || usedScalar.type !== 'GraphQLScalarType') { continue; } @@ -542,19 +542,19 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< private collectInnerTypesRecursively({ node, - usedInputTypes, + usedSchemaTypes, location, }: { node: GraphQLNamedInputType; - usedInputTypes: UsedNamedInputTypes; + usedSchemaTypes: UsedSchemaTypes; location: 'variables' | 'input'; // the location where the node was found. This is useful for nested input. Note: Since it starts at the variable, it first iteration is 'variables' and the rest will be `input` }): void { if (node instanceof GraphQLEnumType) { - if (usedInputTypes[node.name]) { + if (usedSchemaTypes[node.name]) { return; } - usedInputTypes[node.name] = { + usedSchemaTypes[node.name] = { type: 'GraphQLEnumType', node, tsType: this.convertName(node.name), @@ -563,7 +563,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< } if (node instanceof GraphQLScalarType) { - const scalarType = usedInputTypes[node.name] || { + const scalarType = usedSchemaTypes[node.name] || { type: 'GraphQLScalarType', node, tsType: @@ -592,15 +592,15 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< scalarType.useCases.variables = true; } - usedInputTypes[node.name] = scalarType; + usedSchemaTypes[node.name] = scalarType; return; } // GraphQLInputObjectType - if (usedInputTypes[node.name]) { + if (usedSchemaTypes[node.name]) { return; } - usedInputTypes[node.name] = { + usedSchemaTypes[node.name] = { type: 'GraphQLInputObjectType', node, tsType: this.convertName(node.name), @@ -611,31 +611,31 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< const fieldType = getNamedType(field.type); this.collectInnerTypesRecursively({ node: fieldType, - usedInputTypes, + usedSchemaTypes, location: 'input', }); } } /** - * FIXME: eddeee888 This function is called `collectUsedInputTypes`, but it collects the types used in Result (SelectionSet) as well: + * @description collects schema types used in operations: * - used Enums for Variables * - used Scalars for Variables - * - used Input for Variables + * - used Input for Variables (recursively) * * - used Enums for Result * - used Scalars for Result */ - private collectUsedInputTypes({ + private collectUsedSchemaTypesToGenerate({ schema, documentNode, }: { schema: GraphQLSchema; documentNode: DocumentNode; - }): UsedNamedInputTypes { + }): UsedSchemaTypes { const schemaTypes = schema.getTypeMap(); - const usedInputTypes: UsedNamedInputTypes = {}; + const usedSchemaTypes: UsedSchemaTypes = {}; // Collect input enums and input types visit(documentNode, { @@ -652,7 +652,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< ) { this.collectInnerTypesRecursively({ node: foundInputType, - usedInputTypes, + usedSchemaTypes, location: 'variables', }); } @@ -675,7 +675,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< const namedType = getNamedType(fieldType); if (namedType instanceof GraphQLEnumType) { - usedInputTypes[namedType.name] = { + usedSchemaTypes[namedType.name] = { type: 'GraphQLEnumType', node: namedType, tsType: this.convertName(namedType.name), @@ -684,7 +684,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< } if (namedType instanceof GraphQLScalarType) { - const scalarType = usedInputTypes[namedType.name] || { + const scalarType = usedSchemaTypes[namedType.name] || { type: 'GraphQLScalarType', node: namedType, tsType: this.convertName(namedType.name), @@ -701,14 +701,14 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< // this is required because if the scalar has been parsed previously, it may only have `useCases.input:true` or `useCases.variables:true`, not `useCases.output:true` scalarType.useCases.output = true; - usedInputTypes[namedType.name] = scalarType; + usedSchemaTypes[namedType.name] = scalarType; } } }, }), ); - return usedInputTypes; + return usedSchemaTypes; } getExactUtilityType(): string | null { From 81c5e9b3bd2906a63e96c052b0c21fca44db55d8 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Fri, 13 Mar 2026 00:53:25 +1100 Subject: [PATCH 52/69] [typescript-operations] Add warning for internal utility types (#10643) * Add internal utility type warning * Update snapshots * Add changeset * Improve internal type message --- .changeset/flat-paths-boil.md | 5 + .../external-documents/app/types.generated.ts | 2 + dev-test/githunt/typed-document-nodes.ts | 3 + dev-test/githunt/types.avoidOptionals.ts | 2 + dev-test/githunt/types.d.ts | 2 + dev-test/githunt/types.enumsAsTypes.ts | 2 + .../githunt/types.flatten.preResolveTypes.ts | 2 + dev-test/githunt/types.immutableTypes.ts | 2 + ...ypes.preResolveTypes.onlyOperationTypes.ts | 2 + dev-test/githunt/types.preResolveTypes.ts | 2 + dev-test/githunt/types.ts | 2 + .../gql-tag-operations-masking/gql/graphql.ts | 5 +- .../gql-tag-operations-urql/gql/graphql.ts | 5 +- dev-test/gql-tag-operations/gql/graphql.ts | 5 +- .../gql-tag-operations/graphql/graphql.ts | 5 +- .../import-schema-types/_types.generated.ts | 3 + .../_types.generated.ts | 3 + dev-test/star-wars/types.avoidOptionals.ts | 2 + dev-test/star-wars/types.d.ts | 1 + dev-test/star-wars/types.excludeQueryAlpha.ts | 2 + dev-test/star-wars/types.excludeQueryBeta.ts | 2 + .../star-wars/types.globallyAvailable.d.ts | 2 + dev-test/star-wars/types.immutableTypes.ts | 2 + ...ypes.preResolveTypes.onlyOperationTypes.ts | 2 + dev-test/star-wars/types.preResolveTypes.ts | 2 + dev-test/star-wars/types.skipSchema.ts | 2 + dev-test/star-wars/types.ts | 2 + dev-test/test-null-value/result.d.ts | 2 + ...ypes.preResolveTypes.onlyOperationTypes.ts | 2 + dev-test/test-schema/types.preResolveTypes.ts | 2 + .../src/gql/graphql.ts | 5 +- .../persisted-documents/src/gql/graphql.ts | 5 +- .../apollo-client-defer/src/gql/graphql.ts | 5 +- .../react/apollo-client/src/gql/graphql.ts | 5 +- .../react/http-executor/src/gql/graphql.ts | 5 +- .../tanstack-react-query/src/gql/graphql.ts | 5 +- examples/react/urql/src/gql/graphql.ts | 5 +- examples/typescript-esm/src/gql/graphql.ts | 5 +- .../src/gql/graphql.ts | 5 +- .../vite/vite-react-cts/src/gql/graphql.ts | 5 +- .../vite/vite-react-mts/src/gql/graphql.ts | 5 +- .../vite/vite-react-ts/src/gql/graphql.ts | 5 +- .../vue/apollo-composable/src/gql/graphql.ts | 5 +- examples/vue/urql/src/gql/graphql.ts | 5 +- examples/vue/villus/src/gql/graphql.ts | 5 +- examples/yoga-tests/src/gql/graphql.ts | 5 +- .../typescript/operations/src/visitor.ts | 6 +- .../operations/tests/ts-documents.spec.ts | 4 +- ...s.standalone.config.avoidOptionals.spec.ts | 24 +++-- .../ts-documents.standalone.enum.spec.ts | 92 +++++++++++++++---- ...-documents.standalone.import-types.spec.ts | 16 +++- .../ts-documents.standalone.input.spec.ts | 16 +++- .../ts-documents.standalone.scalars.spec.ts | 20 +++- .../tests/ts-documents.standalone.spec.ts | 33 +++++-- .../client/tests/client-preset.enum.spec.ts | 13 ++- .../client/tests/client-preset.spec.ts | 88 +++++++++++++----- 56 files changed, 379 insertions(+), 90 deletions(-) create mode 100644 .changeset/flat-paths-boil.md diff --git a/.changeset/flat-paths-boil.md b/.changeset/flat-paths-boil.md new file mode 100644 index 00000000000..7a02df893a0 --- /dev/null +++ b/.changeset/flat-paths-boil.md @@ -0,0 +1,5 @@ +--- +'@graphql-codegen/typescript-operations': patch +--- + +Add internal utility type warning to deter usage diff --git a/dev-test/external-documents/app/types.generated.ts b/dev-test/external-documents/app/types.generated.ts index 5f685f2c710..0a4e99d4f5e 100644 --- a/dev-test/external-documents/app/types.generated.ts +++ b/dev-test/external-documents/app/types.generated.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/githunt/typed-document-nodes.ts b/dev-test/githunt/typed-document-nodes.ts index 1c07b674e35..81f92bdfb56 100644 --- a/dev-test/githunt/typed-document-nodes.ts +++ b/dev-test/githunt/typed-document-nodes.ts @@ -1,9 +1,12 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + /** A list of options for the sort order of the feed */ export type FeedType = /** Sort by a combination of freshness and score, using Reddit's algorithm */ diff --git a/dev-test/githunt/types.avoidOptionals.ts b/dev-test/githunt/types.avoidOptionals.ts index 765daed8ab9..4b7921b4d98 100644 --- a/dev-test/githunt/types.avoidOptionals.ts +++ b/dev-test/githunt/types.avoidOptionals.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/githunt/types.d.ts b/dev-test/githunt/types.d.ts index 9502cb33eaa..fe2ef34a356 100644 --- a/dev-test/githunt/types.d.ts +++ b/dev-test/githunt/types.d.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/githunt/types.enumsAsTypes.ts b/dev-test/githunt/types.enumsAsTypes.ts index 9502cb33eaa..fe2ef34a356 100644 --- a/dev-test/githunt/types.enumsAsTypes.ts +++ b/dev-test/githunt/types.enumsAsTypes.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/githunt/types.flatten.preResolveTypes.ts b/dev-test/githunt/types.flatten.preResolveTypes.ts index 72391d2870b..69fac9b9cef 100644 --- a/dev-test/githunt/types.flatten.preResolveTypes.ts +++ b/dev-test/githunt/types.flatten.preResolveTypes.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/githunt/types.immutableTypes.ts b/dev-test/githunt/types.immutableTypes.ts index 7980f4fe02a..076ac9ee412 100644 --- a/dev-test/githunt/types.immutableTypes.ts +++ b/dev-test/githunt/types.immutableTypes.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts index 9502cb33eaa..fe2ef34a356 100644 --- a/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/githunt/types.preResolveTypes.onlyOperationTypes.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/githunt/types.preResolveTypes.ts b/dev-test/githunt/types.preResolveTypes.ts index 9502cb33eaa..fe2ef34a356 100644 --- a/dev-test/githunt/types.preResolveTypes.ts +++ b/dev-test/githunt/types.preResolveTypes.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/githunt/types.ts b/dev-test/githunt/types.ts index 9502cb33eaa..fe2ef34a356 100644 --- a/dev-test/githunt/types.ts +++ b/dev-test/githunt/types.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/gql-tag-operations-masking/gql/graphql.ts b/dev-test/gql-tag-operations-masking/gql/graphql.ts index 9dda1735a5d..d442a0136d9 100644 --- a/dev-test/gql-tag-operations-masking/gql/graphql.ts +++ b/dev-test/gql-tag-operations-masking/gql/graphql.ts @@ -1,10 +1,13 @@ -/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; +/* eslint-disable */ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type TweetFragmentFragment = ({ id: string; body: string } & { ' $fragmentRefs'?: { TweetAuthorFragmentFragment: TweetAuthorFragmentFragment }; }) & { ' $fragmentName'?: 'TweetFragmentFragment' }; diff --git a/dev-test/gql-tag-operations-urql/gql/graphql.ts b/dev-test/gql-tag-operations-urql/gql/graphql.ts index aa5c16c9b1c..fb143deb0cb 100644 --- a/dev-test/gql-tag-operations-urql/gql/graphql.ts +++ b/dev-test/gql-tag-operations-urql/gql/graphql.ts @@ -1,10 +1,13 @@ -/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; +/* eslint-disable */ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type FooQueryVariables = Exact<{ [key: string]: never }>; export type FooQuery = { Tweets: Array<{ id: string } | null> | null }; diff --git a/dev-test/gql-tag-operations/gql/graphql.ts b/dev-test/gql-tag-operations/gql/graphql.ts index bfeab7f1e4f..148be727022 100644 --- a/dev-test/gql-tag-operations/gql/graphql.ts +++ b/dev-test/gql-tag-operations/gql/graphql.ts @@ -1,10 +1,13 @@ -/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; +/* eslint-disable */ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type FooQueryVariables = Exact<{ [key: string]: never }>; export type FooQuery = { Tweets: Array<{ id: string } | null> | null }; diff --git a/dev-test/gql-tag-operations/graphql/graphql.ts b/dev-test/gql-tag-operations/graphql/graphql.ts index bfeab7f1e4f..148be727022 100644 --- a/dev-test/gql-tag-operations/graphql/graphql.ts +++ b/dev-test/gql-tag-operations/graphql/graphql.ts @@ -1,10 +1,13 @@ -/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; +/* eslint-disable */ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type FooQueryVariables = Exact<{ [key: string]: never }>; export type FooQuery = { Tweets: Array<{ id: string } | null> | null }; diff --git a/dev-test/standalone-operations/import-schema-types/_types.generated.ts b/dev-test/standalone-operations/import-schema-types/_types.generated.ts index 954a5cffd3b..3f88552ad29 100644 --- a/dev-test/standalone-operations/import-schema-types/_types.generated.ts +++ b/dev-test/standalone-operations/import-schema-types/_types.generated.ts @@ -1,9 +1,12 @@ import type * as Types from './_base.generated.js'; +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type WithVariablesQueryVariables = Exact<{ role?: Types.UserRole | null | undefined; }>; diff --git a/dev-test/standalone-operations/with-typescript-plugin/_types.generated.ts b/dev-test/standalone-operations/with-typescript-plugin/_types.generated.ts index 954a5cffd3b..3f88552ad29 100644 --- a/dev-test/standalone-operations/with-typescript-plugin/_types.generated.ts +++ b/dev-test/standalone-operations/with-typescript-plugin/_types.generated.ts @@ -1,9 +1,12 @@ import type * as Types from './_base.generated.js'; +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type WithVariablesQueryVariables = Exact<{ role?: Types.UserRole | null | undefined; }>; diff --git a/dev-test/star-wars/types.avoidOptionals.ts b/dev-test/star-wars/types.avoidOptionals.ts index b4a31e491e6..f99a9a941d7 100644 --- a/dev-test/star-wars/types.avoidOptionals.ts +++ b/dev-test/star-wars/types.avoidOptionals.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/star-wars/types.d.ts b/dev-test/star-wars/types.d.ts index 92e0ff02565..5190be1aab1 100644 --- a/dev-test/star-wars/types.d.ts +++ b/dev-test/star-wars/types.d.ts @@ -1,3 +1,4 @@ +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/star-wars/types.excludeQueryAlpha.ts b/dev-test/star-wars/types.excludeQueryAlpha.ts index 87b55bd79c4..58e75ed1035 100644 --- a/dev-test/star-wars/types.excludeQueryAlpha.ts +++ b/dev-test/star-wars/types.excludeQueryAlpha.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/star-wars/types.excludeQueryBeta.ts b/dev-test/star-wars/types.excludeQueryBeta.ts index dff78d508eb..43847b69a88 100644 --- a/dev-test/star-wars/types.excludeQueryBeta.ts +++ b/dev-test/star-wars/types.excludeQueryBeta.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/star-wars/types.globallyAvailable.d.ts b/dev-test/star-wars/types.globallyAvailable.d.ts index ffc0449a7e8..bf3ce6677cd 100644 --- a/dev-test/star-wars/types.globallyAvailable.d.ts +++ b/dev-test/star-wars/types.globallyAvailable.d.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/star-wars/types.immutableTypes.ts b/dev-test/star-wars/types.immutableTypes.ts index 0e1b9b53e51..fafd0e5ccea 100644 --- a/dev-test/star-wars/types.immutableTypes.ts +++ b/dev-test/star-wars/types.immutableTypes.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts index 7a45c0bd207..09384a92091 100644 --- a/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.onlyOperationTypes.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/star-wars/types.preResolveTypes.ts b/dev-test/star-wars/types.preResolveTypes.ts index 7a45c0bd207..09384a92091 100644 --- a/dev-test/star-wars/types.preResolveTypes.ts +++ b/dev-test/star-wars/types.preResolveTypes.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/star-wars/types.skipSchema.ts b/dev-test/star-wars/types.skipSchema.ts index 7a45c0bd207..09384a92091 100644 --- a/dev-test/star-wars/types.skipSchema.ts +++ b/dev-test/star-wars/types.skipSchema.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/star-wars/types.ts b/dev-test/star-wars/types.ts index 7a45c0bd207..09384a92091 100644 --- a/dev-test/star-wars/types.ts +++ b/dev-test/star-wars/types.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/test-null-value/result.d.ts b/dev-test/test-null-value/result.d.ts index fb0c8076f1a..fe5efedc5ff 100644 --- a/dev-test/test-null-value/result.d.ts +++ b/dev-test/test-null-value/result.d.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts b/dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts index 3891d0d999a..bdbf325176c 100644 --- a/dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts +++ b/dev-test/test-schema/types.preResolveTypes.onlyOperationTypes.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/dev-test/test-schema/types.preResolveTypes.ts b/dev-test/test-schema/types.preResolveTypes.ts index 3891d0d999a..bdbf325176c 100644 --- a/dev-test/test-schema/types.preResolveTypes.ts +++ b/dev-test/test-schema/types.preResolveTypes.ts @@ -1,4 +1,6 @@ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; diff --git a/examples/persisted-documents-string-mode/src/gql/graphql.ts b/examples/persisted-documents-string-mode/src/gql/graphql.ts index 2fe6966db28..1aaa31e4817 100644 --- a/examples/persisted-documents-string-mode/src/gql/graphql.ts +++ b/examples/persisted-documents-string-mode/src/gql/graphql.ts @@ -1,10 +1,13 @@ -/* eslint-disable */ import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; +/* eslint-disable */ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type HelloQueryQueryVariables = Exact<{ [key: string]: never }>; export type HelloQueryQuery = { hello: string }; diff --git a/examples/persisted-documents/src/gql/graphql.ts b/examples/persisted-documents/src/gql/graphql.ts index 158f8951d3a..a3786f6e6e9 100644 --- a/examples/persisted-documents/src/gql/graphql.ts +++ b/examples/persisted-documents/src/gql/graphql.ts @@ -1,10 +1,13 @@ -/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; +/* eslint-disable */ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type HelloQueryQueryVariables = Exact<{ [key: string]: never }>; export type HelloQueryQuery = { hello: string }; diff --git a/examples/react/apollo-client-defer/src/gql/graphql.ts b/examples/react/apollo-client-defer/src/gql/graphql.ts index 5fd1e0fbbde..fd811a03a35 100644 --- a/examples/react/apollo-client-defer/src/gql/graphql.ts +++ b/examples/react/apollo-client-defer/src/gql/graphql.ts @@ -1,10 +1,13 @@ -/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; +/* eslint-disable */ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type SlowFieldFragmentFragment = { slowField: string } & { ' $fragmentName'?: 'SlowFieldFragmentFragment'; }; diff --git a/examples/react/apollo-client/src/gql/graphql.ts b/examples/react/apollo-client/src/gql/graphql.ts index 9f483eedc67..a9b41a154c3 100644 --- a/examples/react/apollo-client/src/gql/graphql.ts +++ b/examples/react/apollo-client/src/gql/graphql.ts @@ -1,10 +1,13 @@ -/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; +/* eslint-disable */ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ first: number; }>; diff --git a/examples/react/http-executor/src/gql/graphql.ts b/examples/react/http-executor/src/gql/graphql.ts index 35ca172a4ff..41ca140746c 100644 --- a/examples/react/http-executor/src/gql/graphql.ts +++ b/examples/react/http-executor/src/gql/graphql.ts @@ -1,10 +1,13 @@ -/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; +/* eslint-disable */ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ first: number; }>; diff --git a/examples/react/tanstack-react-query/src/gql/graphql.ts b/examples/react/tanstack-react-query/src/gql/graphql.ts index 6a5e52c1ba7..d51ee811183 100644 --- a/examples/react/tanstack-react-query/src/gql/graphql.ts +++ b/examples/react/tanstack-react-query/src/gql/graphql.ts @@ -1,10 +1,13 @@ -/* eslint-disable */ import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; +/* eslint-disable */ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ first: number; }>; diff --git a/examples/react/urql/src/gql/graphql.ts b/examples/react/urql/src/gql/graphql.ts index 23a2c624e02..a37bc092fd7 100644 --- a/examples/react/urql/src/gql/graphql.ts +++ b/examples/react/urql/src/gql/graphql.ts @@ -1,10 +1,13 @@ -/* eslint-disable */ import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; +/* eslint-disable */ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type AllFilmsWithVariablesQuery199QueryVariables = Exact<{ first: number; }>; diff --git a/examples/typescript-esm/src/gql/graphql.ts b/examples/typescript-esm/src/gql/graphql.ts index 478717a7da7..4b3afeee756 100644 --- a/examples/typescript-esm/src/gql/graphql.ts +++ b/examples/typescript-esm/src/gql/graphql.ts @@ -1,10 +1,13 @@ -/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; +/* eslint-disable */ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type AllPeopleQueryQueryVariables = Exact<{ [key: string]: never }>; export type AllPeopleQueryQuery = { diff --git a/examples/typescript-graphql-request/src/gql/graphql.ts b/examples/typescript-graphql-request/src/gql/graphql.ts index 2d4c1973778..9aa9bc5e476 100644 --- a/examples/typescript-graphql-request/src/gql/graphql.ts +++ b/examples/typescript-graphql-request/src/gql/graphql.ts @@ -1,10 +1,13 @@ -/* eslint-disable */ import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; +/* eslint-disable */ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type AllPeopleQueryQueryVariables = Exact<{ [key: string]: never }>; export type AllPeopleQueryQuery = { diff --git a/examples/vite/vite-react-cts/src/gql/graphql.ts b/examples/vite/vite-react-cts/src/gql/graphql.ts index 73f95a195d4..c1f9f07008d 100644 --- a/examples/vite/vite-react-cts/src/gql/graphql.ts +++ b/examples/vite/vite-react-cts/src/gql/graphql.ts @@ -1,10 +1,13 @@ -/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; +/* eslint-disable */ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type FilmItemFragment = { id: string; title: string | null; diff --git a/examples/vite/vite-react-mts/src/gql/graphql.ts b/examples/vite/vite-react-mts/src/gql/graphql.ts index 73f95a195d4..c1f9f07008d 100644 --- a/examples/vite/vite-react-mts/src/gql/graphql.ts +++ b/examples/vite/vite-react-mts/src/gql/graphql.ts @@ -1,10 +1,13 @@ -/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; +/* eslint-disable */ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type FilmItemFragment = { id: string; title: string | null; diff --git a/examples/vite/vite-react-ts/src/gql/graphql.ts b/examples/vite/vite-react-ts/src/gql/graphql.ts index 73f95a195d4..c1f9f07008d 100644 --- a/examples/vite/vite-react-ts/src/gql/graphql.ts +++ b/examples/vite/vite-react-ts/src/gql/graphql.ts @@ -1,10 +1,13 @@ -/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; +/* eslint-disable */ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type FilmItemFragment = { id: string; title: string | null; diff --git a/examples/vue/apollo-composable/src/gql/graphql.ts b/examples/vue/apollo-composable/src/gql/graphql.ts index 7a4aaeb85ae..32b8b38e8d3 100644 --- a/examples/vue/apollo-composable/src/gql/graphql.ts +++ b/examples/vue/apollo-composable/src/gql/graphql.ts @@ -1,10 +1,13 @@ -/* eslint-disable */ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; +/* eslint-disable */ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ first: number; }>; diff --git a/examples/vue/urql/src/gql/graphql.ts b/examples/vue/urql/src/gql/graphql.ts index 7a4aaeb85ae..32b8b38e8d3 100644 --- a/examples/vue/urql/src/gql/graphql.ts +++ b/examples/vue/urql/src/gql/graphql.ts @@ -1,10 +1,13 @@ -/* eslint-disable */ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; +/* eslint-disable */ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ first: number; }>; diff --git a/examples/vue/villus/src/gql/graphql.ts b/examples/vue/villus/src/gql/graphql.ts index 7a4aaeb85ae..32b8b38e8d3 100644 --- a/examples/vue/villus/src/gql/graphql.ts +++ b/examples/vue/villus/src/gql/graphql.ts @@ -1,10 +1,13 @@ -/* eslint-disable */ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; +/* eslint-disable */ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type AllFilmsWithVariablesQueryQueryVariables = Exact<{ first: number; }>; diff --git a/examples/yoga-tests/src/gql/graphql.ts b/examples/yoga-tests/src/gql/graphql.ts index 946b85f42e5..299a5f4e2bc 100644 --- a/examples/yoga-tests/src/gql/graphql.ts +++ b/examples/yoga-tests/src/gql/graphql.ts @@ -1,10 +1,13 @@ -/* eslint-disable */ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; +/* eslint-disable */ +/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; +/** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = | T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type HelloQueryQueryVariables = Exact<{ [key: string]: never }>; export type HelloQueryQuery = { hello: string }; diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index deb611a78ec..620e03029d9 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -719,7 +719,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< return null; } - return 'type Exact = { [K in keyof T]: T[K] };'; + return `${internalUtilityTypeWarning}type Exact = { [K in keyof T]: T[K] };`; } getIncrementalUtilityType(): string | null { @@ -730,10 +730,12 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< // Note: `export` here is important for 2 reasons // 1. It is not always used in the rest of the file, so this is a safe way to avoid lint rules (in tsconfig or eslint) complaining it's not used in the current file. // 2. In Client Preset, it is used by fragment-masking.ts, so it needs `export` - return "export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never };"; + return `${internalUtilityTypeWarning}export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never };`; } } +const internalUtilityTypeWarning = '/** Internal type. DO NOT USE DIRECTLY. */\n'; + function parseOneOfInputValue({ node, schema, diff --git a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts index 9857dc6c37f..ea59956a13b 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts @@ -6211,7 +6211,9 @@ function test(q: GetEntityBrandDataQuery): void { ]); expect(content).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type WidgetFragmentFragment = { widgetCount: number, widgetPreference: string } & { ' $fragmentName'?: 'WidgetFragmentFragment' }; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.avoidOptionals.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.avoidOptionals.spec.ts index e4f659b2309..025f1890f67 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.avoidOptionals.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.avoidOptionals.spec.ts @@ -48,7 +48,9 @@ describe('TypeScript Operations Plugin - config.avoidOptionals', () => { const result = mergeOutputs([await plugin(schema, [{ document }], {}, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserInput = { id: string | number; @@ -116,7 +118,9 @@ describe('TypeScript Operations Plugin - config.avoidOptionals', () => { const result = mergeOutputs([await plugin(schema, [{ document }], { avoidOptionals: true }, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserInput = { id: string | number; @@ -195,7 +199,9 @@ describe('TypeScript Operations Plugin - config.avoidOptionals', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserInput = { id: string | number; @@ -272,7 +278,9 @@ describe('TypeScript Operations Plugin - config.avoidOptionals', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserInput = { id: string | number; @@ -349,7 +357,9 @@ describe('TypeScript Operations Plugin - config.avoidOptionals', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserInput = { id: string | number; @@ -432,7 +442,9 @@ describe('TypeScript Operations Plugin - config.avoidOptionals', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserInput = { id: string | number; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts index cc0bcb97a89..ed5988f779a 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts @@ -35,7 +35,9 @@ describe('TypeScript Operations Plugin - Enum', () => { const result = mergeOutputs([await plugin(schema, [{ document }], {}, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type MeQueryVariables = Exact<{ [key: string]: never; }>; @@ -80,7 +82,9 @@ describe('TypeScript Operations Plugin - Enum', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export enum UserRole { Admin = 0, @@ -133,7 +137,9 @@ describe('TypeScript Operations Plugin - Enum', () => { const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'const' }, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export const UserRole = { ABC: 'A_B_C', @@ -192,7 +198,9 @@ describe('TypeScript Operations Plugin - Enum', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** Multiline comment test */ export const enum UserRole { @@ -244,7 +252,9 @@ describe('TypeScript Operations Plugin - Enum', () => { const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' }, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export enum UserRole { Admin = 'ADMIN', @@ -313,7 +323,9 @@ describe('TypeScript Operations Plugin - Enum', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserRole = | 0 @@ -383,7 +395,9 @@ describe('TypeScript Operations Plugin - Enum', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export const UserRole = { ABC: 0, @@ -451,7 +465,9 @@ describe('TypeScript Operations Plugin - Enum', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export enum UserRole { Admin = 0, @@ -514,7 +530,9 @@ describe('TypeScript Operations Plugin - Enum', () => { expect(result).toMatchInlineSnapshot(` "import { MyEnum as UserRole } from './my-file'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export { UserRole }; @@ -573,7 +591,9 @@ describe('TypeScript Operations Plugin - Enum', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; @@ -630,7 +650,9 @@ describe('TypeScript Operations Plugin - Enum', () => { expect(result).toMatchInlineSnapshot(` "import { NS } from './my-file'; import UserRole = NS.ETest; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export { UserRole }; @@ -691,7 +713,9 @@ describe('TypeScript Operations Plugin - Enum', () => { expect(result).toMatchInlineSnapshot(` "import { NS } from './my-file'; import UserRole = NS.UserRole; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export { UserRole }; @@ -756,7 +780,9 @@ describe('TypeScript Operations Plugin - Enum', () => { expect(result).toMatchInlineSnapshot(` "import { UserRole } from './my-file'; import { UserStatus } from './my-file'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export { UserRole }; @@ -824,7 +850,9 @@ describe('TypeScript Operations Plugin - Enum', () => { expect(result).toMatchInlineSnapshot(` "import { UserRole } from './my-file'; import { UserStatus2X as UserStatus } from './my-file'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export { UserRole }; @@ -877,7 +905,9 @@ describe('TypeScript Operations Plugin - Enum', () => { const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' }, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export enum UserRole { ABC = 'A_B_C', @@ -931,7 +961,9 @@ describe('TypeScript Operations Plugin - Enum', () => { const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' }, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export enum UserRole { _ = '_', @@ -984,7 +1016,9 @@ describe('TypeScript Operations Plugin - Enum', () => { await plugin(schema, [{ document }], { typesPrefix: 'I', enumPrefix: true }, { outputFile: '' }), ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type IUserRole = | 'ADMIN' @@ -1035,7 +1069,9 @@ describe('TypeScript Operations Plugin - Enum', () => { await plugin(schema, [{ document }], { typesPrefix: 'I', enumPrefix: false }, { outputFile: '' }), ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserRole = | 'ADMIN' @@ -1086,7 +1122,9 @@ describe('TypeScript Operations Plugin - Enum', () => { await plugin(schema, [{ document }], { typesSuffix: 'Z', enumSuffix: true }, { outputFile: '' }), ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserRoleZ = | 'ADMIN' @@ -1137,7 +1175,9 @@ describe('TypeScript Operations Plugin - Enum', () => { await plugin(schema, [{ document }], { typesSuffix: 'Z', enumSuffix: false }, { outputFile: '' }), ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserRole = | 'ADMIN' @@ -1198,7 +1238,9 @@ describe('TypeScript Operations Plugin - Enum', () => { ), ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type userrole = | 'ADMIN' @@ -1260,7 +1302,9 @@ describe('TypeScript Operations Plugin - Enum', () => { ), ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export enum UserRole { admin = 'ADMIN', @@ -1319,7 +1363,9 @@ describe('TypeScript Operations Plugin - Enum', () => { ), ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; type UserRole = | 'ADMIN' @@ -1383,7 +1429,9 @@ describe('TypeScript Operations Plugin - Enum', () => { expect(result).toMatchInlineSnapshot(` "import UserRole from './files'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export { UserRole }; @@ -1430,7 +1478,9 @@ describe('TypeScript Operations Plugin - Enum', () => { const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' }, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export enum UserRole { Axb = 'AXB', @@ -1481,7 +1531,9 @@ describe('TypeScript Operations Plugin - Enum `%future added value`', () => { const result = mergeOutputs([await plugin(schema, [{ document }], { futureProofEnums: true }, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserRole = | 'ADMIN' diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts index efd54f316a6..1519b50e31f 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts @@ -102,7 +102,9 @@ describe('TypeScript Operations Plugin - Import Types', () => { expect(result).toMatchInlineSnapshot(` "import type * as Types from './path-to-other-file.generated'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ id: string | number; @@ -234,7 +236,9 @@ describe('TypeScript Operations Plugin - Import Types', () => { expect(result).toMatchInlineSnapshot(` "import type * as Types from '@my-company/package/types'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ id: string | number; @@ -340,7 +344,9 @@ describe('TypeScript Operations Plugin - Import Types', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ id?: string | number | null | undefined; @@ -426,7 +432,9 @@ describe('TypeScript Operations Plugin - Import Types with external custom Scala expect(operationFileResult).toMatchInlineSnapshot(` "import type * as Types from './graphql-code-generator/path-to-other-file'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ input?: Types.UserInput | null | undefined; @@ -495,7 +503,9 @@ describe('TypeScript Operations Plugin - Import Types with external custom Scala ]); expect(operationFileResult).toMatchInlineSnapshot(` "import { Scalar1 } from '@org/scalars'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ scalar1?: Scalar1 | null | undefined; @@ -565,7 +575,9 @@ describe('TypeScript Operations Plugin - Import Types with external custom Scala ]); expect(operationFileResult).toMatchInlineSnapshot(` "import { Scalar1 } from '@org/scalars'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ [key: string]: never; }>; @@ -622,7 +634,9 @@ describe('TypeScript Operations Plugin - Import Types with external custom Scala expect(result).toMatchInlineSnapshot(` "import type * as TypeImport from './path-to-other-file.generated'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ id: string | number; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts index fa84ec8d629..b47e3af2527 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts @@ -93,7 +93,9 @@ describe('TypeScript Operations Plugin - Input', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** UserRole Description */ export type UserRole = @@ -214,7 +216,9 @@ describe('TypeScript Operations Plugin - Input', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** UserRole Description */ export type UserRole = @@ -323,7 +327,9 @@ describe('TypeScript Operations Plugin - Input', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; /** UserRole Description */ export type UserRole = @@ -422,7 +428,9 @@ describe('TypeScript Operations Plugin - Input', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserInput = { dateRange1?: Array | null; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.scalars.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.scalars.spec.ts index 7dc053f4d13..ea8726487aa 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.scalars.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.scalars.spec.ts @@ -66,7 +66,9 @@ describe('TypeScript Operations Plugin - Default Scalar types', () => { const result = mergeOutputs([await plugin(schema, [{ document }], {}, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserInput = { nonNullableDate: unknown; @@ -159,7 +161,9 @@ describe('TypeScript Operations Plugin - Default Scalar types', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserInput = { nonNullableDate: any; @@ -252,7 +256,9 @@ describe('TypeScript Operations Plugin - Default Scalar types', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserInput = { nonNullableDate: Date; @@ -354,7 +360,9 @@ describe('TypeScript Operations Plugin - Custom Scalars', () => { import Scalar4 from '@org/scalars'; import { MyScalar5, MyScalar6 as AliasedScalar6 } from '@org/scalars'; import { Scalar7Output } from '@org/input-output'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ [key: string]: never; }>; @@ -428,7 +436,9 @@ describe('TypeScript Operations Plugin - Custom Scalars', () => { import Scalar4 from '@org/scalars'; import { MyScalar5, MyScalar6 as AliasedScalar6 } from '@org/scalars'; import { Scalar7Input } from '@org/input-output'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserInput = { scalar1?: Scalar1 | null | undefined; @@ -545,7 +555,9 @@ describe('TypeScript Operations Plugin - Custom Scalars', () => { import DefaultScalar8 from '@org/scalars'; import { Scalar9, Scalar10 as MyScalar10 } from '@org/scalars'; import { Scalar11 as Scalar11Input, Scalar11 as Scalar11Output, Scalar12 } from '@org/input-output'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ scalar1?: Scalar1 | null | undefined; @@ -666,7 +678,9 @@ describe('TypeScript Operations Plugin - Custom Scalars', () => { import type { default as DefaultScalar8 } from '@org/scalars'; import type { Scalar9, Scalar10 as MyScalar10 } from '@org/scalars'; import type { Scalar11 as Scalar11Input, Scalar11 as Scalar11Output, Scalar12 } from '@org/input-output'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ scalar1?: Scalar1 | null | undefined; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts index add6723dd06..5c7a5db8a65 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -120,7 +120,9 @@ describe('TypeScript Operations Plugin - Standalone', () => { const result = mergeOutputs([await plugin(schema, [{ document }], {}, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type ResponseErrorType = | 'NOT_FOUND' @@ -236,7 +238,9 @@ describe('TypeScript Operations Plugin - Standalone', () => { const result = mergeOutputs([await plugin(schema, [{ document }], {}, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type EnumRoot = | 'ENUM_A' @@ -328,7 +332,9 @@ describe('TypeScript Operations Plugin - Standalone', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type EnumRoot = | 'ENUM_A' @@ -392,7 +398,9 @@ describe('TypeScript Operations Plugin - Standalone', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ id: string | number | boolean; @@ -443,7 +451,9 @@ describe('TypeScript Operations Plugin - Standalone', () => { const result = mergeOutputs([await plugin(schema, [{ document }], {}, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type RoleType = | 'ROLE_A' @@ -503,7 +513,9 @@ describe('TypeScript Operations Plugin - Standalone', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type RoleType = | 'ROLE_A' @@ -794,7 +806,9 @@ describe('TypeScript Operations Plugin - Standalone', () => { ]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserQueryVariables = Exact<{ id: string | number; @@ -841,6 +855,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { expect(result).toMatchInlineSnapshot(` " + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export type UserPartFragment = { id: string, name: string }; " @@ -885,7 +900,9 @@ describe('TypeScript Operations Plugin - Standalone', () => { const result = mergeOutputs([await plugin(schema, [{ document }], { globalNamespace: true }, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` - "type Exact = { [K in keyof T]: T[K] }; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; declare global { diff --git a/packages/presets/client/tests/client-preset.enum.spec.ts b/packages/presets/client/tests/client-preset.enum.spec.ts index 8ea0aa1a047..028e5164e37 100644 --- a/packages/presets/client/tests/client-preset.enum.spec.ts +++ b/packages/presets/client/tests/client-preset.enum.spec.ts @@ -23,6 +23,7 @@ describe('client-preset - Enum', () => { const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never };" `); }); @@ -69,9 +70,11 @@ describe('client-preset - Enum', () => { const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Shape = | 'ROUND' | 'SQUARE'; @@ -131,9 +134,11 @@ describe('client-preset - Enum', () => { const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Shape = | 'ROUND' | 'SQUARE'; @@ -188,9 +193,11 @@ describe('client-preset - Enum', () => { const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export const Shape = { Round: 'ROUND', Square: 'SQUARE' diff --git a/packages/presets/client/tests/client-preset.spec.ts b/packages/presets/client/tests/client-preset.spec.ts index 5594f5ed2b3..ebfdae04e20 100644 --- a/packages/presets/client/tests/client-preset.spec.ts +++ b/packages/presets/client/tests/client-preset.spec.ts @@ -362,9 +362,11 @@ export * from "./gql";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type AQueryVariables = Exact<{ [key: string]: never; }>; @@ -477,9 +479,11 @@ export * from "./gql";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type AQueryVariables = Exact<{ [key: string]: never; }>; @@ -543,9 +547,11 @@ export * from "./gql";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type MeQueryVariables = Exact<{ [key: string]: never; }>; @@ -634,9 +640,11 @@ export * from "./gql";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type AQueryVariables = Exact<{ [key: string]: never; }>; @@ -1472,9 +1480,11 @@ export * from "./gql.cjs";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type BbbQueryVariables = Exact<{ [key: string]: never; }>; @@ -1531,9 +1541,11 @@ export * from "./gql.cjs";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type AQueryVariables = Exact<{ [key: string]: never; }>; @@ -1593,9 +1605,11 @@ export * from "./gql.cjs";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type AQueryVariables = Exact<{ [key: string]: never; }>; @@ -1655,9 +1669,11 @@ export * from "./gql.cjs";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type AQueryVariables = Exact<{ [key: string]: never; }>; @@ -1717,9 +1733,11 @@ export * from "./gql.cjs";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type AaaQueryVariables = Exact<{ [key: string]: never; }>; @@ -1777,9 +1795,11 @@ export * from "./gql.cjs";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type AQueryVariables = Exact<{ [key: string]: never; }>; @@ -1843,9 +1863,11 @@ export * from "./gql.cjs";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type AQueryVariables = Exact<{ [key: string]: never; }>; @@ -1910,9 +1932,11 @@ export * from "./gql.cjs";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type AQueryVariables = Exact<{ [key: string]: never; }>; @@ -1977,9 +2001,11 @@ export * from "./gql.cjs";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type AQueryVariables = Exact<{ [key: string]: never; }>; @@ -2048,9 +2074,11 @@ export * from "./gql.cjs";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type AbFragment = ( { b: string } & { ' $fragmentRefs'?: { 'AcFragment': AcFragment;'AaFragment': AaFragment } } @@ -2126,9 +2154,11 @@ export * from "./gql.cjs";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type AcFragment = { __typename: 'A', b: string } & { ' $fragmentName'?: 'AcFragment' }; export type AaFragment = { __typename: 'A', b: string } & { ' $fragmentName'?: 'AaFragment' }; @@ -2180,9 +2210,11 @@ export * from "./gql.cjs";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type FooQueryVariables = Exact<{ [key: string]: never; }>; @@ -2242,9 +2274,11 @@ export * from "./gql.cjs";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type FooQueryVariables = Exact<{ [key: string]: never; }>; @@ -2304,9 +2338,11 @@ export * from "./gql.cjs";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; export type FooQueryVariables = Exact<{ [key: string]: never; }>; @@ -2439,9 +2475,11 @@ export * from "./gql.cjs";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; export type FooQueryVariables = Exact<{ [key: string]: never; }>; @@ -2572,9 +2610,11 @@ export * from "./gql.cjs";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; export type FooQueryVariables = Exact<{ [key: string]: never; }>; @@ -2838,9 +2878,11 @@ export * from "./gql.cjs";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; export type OnRegionCreatedSubscriptionVariables = Exact<{ [key: string]: never; }>; @@ -2915,9 +2957,11 @@ export * from "./gql.cjs";`); const graphqlFile = result.find(file => file.filename === 'out1/graphql.ts'); expect(graphqlFile.content).toMatchInlineSnapshot(` "/* eslint-disable */ - import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; export type Test_UserQueryVariables = Exact<{ [key: string]: never; }>; From 0519f487e06faae37096b28c1ec8d862d6d3fb01 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Tue, 17 Mar 2026 00:20:02 +1100 Subject: [PATCH 53/69] [typescript-operations] Fix `@skip` and `@include` not applying conditional modifiers correctly when used on inline fragment (#10645) * Migrate skip and include directive tests to a new file * Add test for aliased field * Add test for include directive, inline fragment cases * Refactor selection set to object to reflect current usages * Standardise type, parsing, fragment directive handling and fix conditional when inline fragment is used * Add inline fragment skip directive test * Add changeset --- .changeset/tender-snakes-hang.md | 5 + .../src/selection-set-to-object.ts | 299 +++++---- .../other/visitor-plugin-common/src/types.ts | 6 +- .../other/visitor-plugin-common/src/utils.ts | 25 +- .../__snapshots__/ts-documents.spec.ts.snap | 10 - ...-documents.skip-include-directives.spec.ts | 623 ++++++++++++++++++ .../operations/tests/ts-documents.spec.ts | 439 ------------ 7 files changed, 827 insertions(+), 580 deletions(-) create mode 100644 .changeset/tender-snakes-hang.md create mode 100644 packages/plugins/typescript/operations/tests/ts-documents.skip-include-directives.spec.ts diff --git a/.changeset/tender-snakes-hang.md b/.changeset/tender-snakes-hang.md new file mode 100644 index 00000000000..244560ae0ba --- /dev/null +++ b/.changeset/tender-snakes-hang.md @@ -0,0 +1,5 @@ +--- +'@graphql-codegen/typescript-operations': patch +--- + +Fix `@skip` and `@include` not applying conditional modifiers correctly when used on inline fragment diff --git a/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts b/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts index 40bdc55a86f..d70a7fb5b48 100644 --- a/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts +++ b/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts @@ -35,9 +35,8 @@ import { ProcessResult, type SelectionSetProcessorConfig as BaseSelectionSetProcessorConfig, } from './selection-set-processor/base.js'; -import { +import type { ConvertNameFn, - FragmentDirectives, GetFragmentSuffixFn, LoadedFragment, NormalizedScalarsMap, @@ -59,6 +58,17 @@ type FragmentSpreadUsage = { typeName: string; onType: string; selectionNodes: Array; + fragmentDirectives: DirectiveNode[]; +}; + +/** + * @description EnrichedFieldNode are field nodes enriched with Codegen metadata for subsequent processing + */ +type EnrichedFieldNode = FieldNode & { + /** + * A field node may implicitly inherit fragment directives from parents + * For example, if the field's parent is marked with `@skip`, the field is implicitly marked with `@skip` as well + */ fragmentDirectives?: DirectiveNode[]; }; @@ -68,8 +78,17 @@ interface DependentType { isUnionType?: boolean; } -type CollectedFragmentNode = (SelectionNode | FragmentSpreadUsage | DirectiveNode) & - FragmentDirectives; +/** + * Each grouped TypeName has an array of nodes. + * These are collected when parsing the selection set, + * then turned into TypeScript strings + */ +type GroupedTypeNameNode = + | EnrichedFieldNode + | FragmentSpreadNode + | InlineFragmentNode + | FragmentSpreadUsage + | DirectiveNode; type GroupedStringifiedTypes = Record>; const operationTypes: string[] = ['Query', 'Mutation', 'Subscription']; @@ -135,9 +154,9 @@ export class SelectionSetToObject< */ _collectInlineFragments( parentType: GraphQLNamedType, - nodes: Array, - types: Map>, - ) { + nodes: Array, + types: Map>, + ): void { if (isListType(parentType) || isNonNullType(parentType)) { return this._collectInlineFragments(parentType.ofType as GraphQLNamedType, nodes, types); } @@ -155,9 +174,9 @@ export class SelectionSetToObject< // that can be associated back to the fields in the fragment, to // support things like making those fields optional when deferring a // fragment (using @defer). - const fieldsWithFragmentDirectives: CollectedFragmentNode[] = fields.map(field => ({ + const fieldsWithFragmentDirectives: EnrichedFieldNode[] = fields.map(field => ({ ...field, - fragmentDirectives: field.fragmentDirectives || directives, + fragmentDirectives: directives, })); if (isObjectType(typeOnSchema)) { @@ -256,27 +275,6 @@ export class SelectionSetToObject< } } - protected _createInlineFragmentForFieldNodes( - parentType: GraphQLNamedType, - fieldNodes: FieldNode[], - ): InlineFragmentNode { - return { - kind: Kind.INLINE_FRAGMENT, - typeCondition: { - kind: Kind.NAMED_TYPE, - name: { - kind: Kind.NAME, - value: parentType.name, - }, - }, - directives: [], - selectionSet: { - kind: Kind.SELECTION_SET, - selections: fieldNodes, - }, - }; - } - /** * The `buildFragmentSpreadsUsage` method is used to collect fields from fragment spreads in the selection set. * It creates a record of fragment spread usages, which includes the fragment name, type name, and the selection nodes @@ -321,9 +319,20 @@ export class SelectionSetToObject< protected flattenSelectionSet( selections: ReadonlyArray, parentSchemaType?: GraphQLObjectType, - ): Map> { - const selectionNodesByTypeName = new Map>(); + ): { + selectionNodesByTypeName: Map>; + selectionNodesByTypeNameConditional: Array>>; + } { + const result: ReturnType = { + selectionNodesByTypeName: new Map>(), + selectionNodesByTypeNameConditional: [], + }; + const inlineFragmentSelections: InlineFragmentNode[] = []; + /** + * Inline fragments marked with `@skip` or `@include` + */ + const inlineFragmentConditionalSelections: InlineFragmentNode[] = []; const fieldNodes: FieldNode[] = []; const fragmentSpreads: FragmentSpreadNode[] = []; for (const selection of selections) { @@ -332,6 +341,10 @@ export class SelectionSetToObject< fieldNodes.push(selection); break; case Kind.INLINE_FRAGMENT: + if (hasConditionalDirectives(selection.directives)) { + inlineFragmentConditionalSelections.push(selection); + break; + } inlineFragmentSelections.push(selection); break; case Kind.FRAGMENT_SPREAD: @@ -340,33 +353,61 @@ export class SelectionSetToObject< } } + // 1. Merge all selection sets that are mergable into one object. This includes: + // - field + // - field with conditional directives + // - inline fragment without conditional directives + // - fragment spreads + + // Turn field nodes into one inline fragments to simplify collecting fields from selections using _collectInlineFragments if (fieldNodes.length) { - inlineFragmentSelections.push( - this._createInlineFragmentForFieldNodes( - parentSchemaType ?? this._parentSchemaType, - fieldNodes, - ), - ); + inlineFragmentSelections.push({ + kind: Kind.INLINE_FRAGMENT, + typeCondition: { + kind: Kind.NAMED_TYPE, + name: { + kind: Kind.NAME, + value: (parentSchemaType ?? this._parentSchemaType).name, + }, + }, + directives: [], + selectionSet: { + kind: Kind.SELECTION_SET, + selections: fieldNodes, + }, + }); } - this._collectInlineFragments( parentSchemaType ?? this._parentSchemaType, inlineFragmentSelections, - selectionNodesByTypeName, + result.selectionNodesByTypeName, ); const fragmentsUsage = this.buildFragmentSpreadsUsage(fragmentSpreads); for (const [typeName, records] of Object.entries(fragmentsUsage)) { - this._appendToTypeMap(selectionNodesByTypeName, typeName, records); + this._appendToTypeMap(result.selectionNodesByTypeName, typeName, records); } - return selectionNodesByTypeName; + // 2. Push conditional inline fragments into the result.selectionNodesByTypeNameConditional + // This is treated differently from result.selectionNodesByTypeName + // because every field in result.selectionNodesByTypeNameConditional is optional + for (const inlineFragmentConditionalSelection of inlineFragmentConditionalSelections) { + const selectionNodes = new Map>(); + this._collectInlineFragments( + parentSchemaType ?? this._parentSchemaType, + [inlineFragmentConditionalSelection], + selectionNodes, + ); + result.selectionNodesByTypeNameConditional.push(selectionNodes); + } + + return result; } - private _appendToTypeMap( - types: Map>, + private _appendToTypeMap( + types: Map>, typeName: string, - nodes: Array, + nodes: Array, ): void { if (!types.has(typeName)) { types.set(typeName, []); @@ -386,7 +427,8 @@ export class SelectionSetToObject< return { grouped: {}, mustAddEmptyObject: true, dependentTypes: [] }; } - const selectionNodesByTypeName = this.flattenSelectionSet(this._selectionSet.selections); + const { selectionNodesByTypeName, selectionNodesByTypeNameConditional } = + this.flattenSelectionSet(this._selectionSet.selections); // in case there is not a selection for each type, we need to add a empty type. let mustAddEmptyObject = false; @@ -395,6 +437,17 @@ export class SelectionSetToObject< const dependentTypes: DependentType[] = []; if (!this._config.mergeFragmentTypes || this._config.inlineFragmentTypes === 'mask') { + // Each grouped type contains an array of stringified objects to be merged. + // Once merged, the type would be the TypeScript representative of the GraphQL selection set + // For example: + // const grouped = { + // User: [ + // '{ createdAt: string, id: string }', + // '{ name?: string, nickName?: string }', + // '{ age?: number }' + // ] + // } + // type merged = { createdAt: string, id: string } & { name?: string, nickName?: string } & { age?: number } const grouped = possibleTypes.reduce((prev, type) => { const typeName = type.name; const schemaType = this._schema.getType(typeName); @@ -405,76 +458,85 @@ export class SelectionSetToObject< ); } - const allNodes = selectionNodesByTypeName.get(typeName) || []; - prev[typeName] ||= []; - // incrementalNodes are the ones flagged with @defer, meaning they become nullable - const { incrementalNodes, selectionNodes, fragmentSpreads } = allNodes.reduce<{ - selectionNodes: (SelectionNode | FragmentSpreadUsage)[]; - incrementalNodes: FragmentSpreadUsage[]; - fragmentSpreads: string[]; - }>( - (acc, node) => { - if ( - 'fragmentDirectives' in node && - hasIncrementalDeliveryDirectives(node.fragmentDirectives) - ) { - acc.incrementalNodes.push(node); - } else { - acc.selectionNodes.push(node); - } - return acc; - }, - { selectionNodes: [], incrementalNodes: [], fragmentSpreads: [] }, - ); + const collectGrouped = (nodes: GroupedTypeNameNode[]): void => { + // incrementalNodes are the ones flagged with @defer, meaning they become nullable + const { selectionNodes, incrementalNodes, fragmentSpreads } = nodes.reduce<{ + selectionNodes: GroupedTypeNameNode[]; + incrementalNodes: FragmentSpreadUsage[]; + fragmentSpreads: string[]; + }>( + (acc, node) => { + if ( + 'fragmentDirectives' in node && + hasIncrementalDeliveryDirectives(node.fragmentDirectives) + ) { + acc.incrementalNodes.push(node as FragmentSpreadUsage); // FIXME: check whether @defer would pick up EnrichedFieldNode here too? + } else { + acc.selectionNodes.push(node); + } + return acc; + }, + { selectionNodes: [], incrementalNodes: [], fragmentSpreads: [] }, + ); - const { fields, dependentTypes: subDependentTypes } = this.buildSelectionSet( - schemaType, - selectionNodes, - { - parentFieldName: this.buildParentFieldName(typeName, parentName), - }, - ); - const transformedSet = this.selectionSetStringFromFields(fields); + const { fields, dependentTypes: subDependentTypes } = this.buildSelectionSet( + schemaType, + selectionNodes, + { + parentFieldName: this.buildParentFieldName(typeName, parentName), + }, + ); + const transformedSet = this.selectionSetStringFromFields(fields); - if (transformedSet) { - prev[typeName].push(transformedSet); - } - dependentTypes.push(...subDependentTypes); - if (!transformedSet && !fragmentSpreads.length) { - mustAddEmptyObject = true; - } + if (transformedSet) { + prev[typeName].push(transformedSet); + } + dependentTypes.push(...subDependentTypes); + if (!transformedSet && !fragmentSpreads.length) { + mustAddEmptyObject = true; + } + + for (const incrementalNode of incrementalNodes) { + // 1. fragment masking + if (this._config.inlineFragmentTypes === 'mask' && 'fragmentName' in incrementalNode) { + const { fields: incrementalFields, dependentTypes: incrementalDependentTypes } = + this.buildSelectionSet(schemaType, [incrementalNode], { + unsetTypes: true, + parentFieldName: parentName, + }); + const incrementalSet = this.selectionSetStringFromFields(incrementalFields); + prev[typeName].push(incrementalSet); + dependentTypes.push(...incrementalDependentTypes); + + continue; + } - for (const incrementalNode of incrementalNodes) { - // 1. fragment masking - if (this._config.inlineFragmentTypes === 'mask' && 'fragmentName' in incrementalNode) { - const { fields: incrementalFields, dependentTypes: incrementalDependentTypes } = + // 2. @defer + const { fields: initialFields, dependentTypes: initialDependentTypes } = + this.buildSelectionSet(schemaType, [incrementalNode], { + parentFieldName: parentName, + }); + + const { fields: subsequentFields, dependentTypes: subsequentDependentTypes } = this.buildSelectionSet(schemaType, [incrementalNode], { unsetTypes: true, parentFieldName: parentName, }); - const incrementalSet = this.selectionSetStringFromFields(incrementalFields); - prev[typeName].push(incrementalSet); - dependentTypes.push(...incrementalDependentTypes); - continue; + const initialSet = this.selectionSetStringFromFields(initialFields); + const subsequentSet = this.selectionSetStringFromFields(subsequentFields); + dependentTypes.push(...initialDependentTypes, ...subsequentDependentTypes); + prev[typeName].push({ union: [initialSet, subsequentSet] }); } + }; - // 2. @defer - const { fields: initialFields, dependentTypes: initialDependentTypes } = - this.buildSelectionSet(schemaType, [incrementalNode], { parentFieldName: parentName }); - - const { fields: subsequentFields, dependentTypes: subsequentDependentTypes } = - this.buildSelectionSet(schemaType, [incrementalNode], { - unsetTypes: true, - parentFieldName: parentName, - }); + const selectionNodes = selectionNodesByTypeName.get(typeName) || []; + collectGrouped(selectionNodes); - const initialSet = this.selectionSetStringFromFields(initialFields); - const subsequentSet = this.selectionSetStringFromFields(subsequentFields); - dependentTypes.push(...initialDependentTypes, ...subsequentDependentTypes); - prev[typeName].push({ union: [initialSet, subsequentSet] }); + for (const conditionalNodes of selectionNodesByTypeNameConditional) { + collectGrouped(conditionalNodes.get(typeName) || []); } return prev; @@ -594,11 +656,11 @@ export class SelectionSetToObject< protected buildSelectionSet( parentSchemaType: GraphQLObjectType, - selectionNodes: Array, + selectionNodes: Array, options: { unsetTypes?: boolean; parentFieldName?: string }, ) { - const primitiveFields = new Map(); - const primitiveAliasFields = new Map(); + const primitiveFields = new Map(); + const primitiveAliasFields = new Map(); const linkFieldSelectionSets = new Map< string, { @@ -617,7 +679,7 @@ export class SelectionSetToObject< for (const selectionNode of selectionNodes) { // 1. Handle Field or Directtives selection nodes if ('kind' in selectionNode) { - if (selectionNode.kind === 'Field') { + if (selectionNode.kind === Kind.FIELD) { if (selectionNode.selectionSet) { let selectedField: GraphQLField = null; @@ -659,8 +721,8 @@ export class SelectionSetToObject< } else { primitiveFields.set(selectionNode.name.value, selectionNode); } - } else if (selectionNode.kind === 'Directive') { - if (['skip', 'include'].includes(selectionNode?.name?.value)) { + } else if (selectionNode.kind === Kind.DIRECTIVE) { + if (hasConditionalDirectives([selectionNode])) { inlineFragmentConditional = true; } } else { @@ -714,11 +776,14 @@ export class SelectionSetToObject< fragmentType.getTypes().find(objectType => objectType.name === parentSchemaType.name)) ) { // also process fields from fragment that apply for this parentType - const flatten = this.flattenSelectionSet(selectionNode.selectionNodes, parentSchemaType); - const typeNodes = flatten.get(parentSchemaType.name) ?? []; + const { selectionNodesByTypeName } = this.flattenSelectionSet( + selectionNode.selectionNodes, + parentSchemaType, + ); + const typeNodes = selectionNodesByTypeName.get(parentSchemaType.name) ?? []; selectionNodes.push(...typeNodes); for (const iinterface of parentSchemaType.getInterfaces()) { - const typeNodes = flatten.get(iinterface.name) ?? []; + const typeNodes = selectionNodesByTypeName.get(iinterface.name) ?? []; selectionNodes.push(...typeNodes); } } @@ -735,7 +800,7 @@ export class SelectionSetToObject< ); linkFieldsInterfaces.push(...selectionSetObjects.dependentTypes); - const isConditional = hasConditionalDirectives(field) || inlineFragmentConditional; + const isConditional = hasConditionalDirectives(field.directives) || inlineFragmentConditional; linkFields.push({ alias: field.alias ? this._processor.config.formatNamedField({ @@ -772,7 +837,9 @@ export class SelectionSetToObject< ...this._processor.transformPrimitiveFields( parentSchemaType, Array.from(primitiveFields.values()).map(field => ({ - isConditional: hasConditionalDirectives(field), + isConditional: + hasConditionalDirectives(field.directives) || + hasConditionalDirectives(field.fragmentDirectives), fieldName: field.name.value, })), options.unsetTypes, @@ -782,7 +849,9 @@ export class SelectionSetToObject< Array.from(primitiveAliasFields.values()).map(field => ({ alias: field.alias.value, fieldName: field.name.value, - isConditional: hasConditionalDirectives(field), + isConditional: + hasConditionalDirectives(field.directives) || + hasConditionalDirectives(field.fragmentDirectives), })), options.unsetTypes, ), diff --git a/packages/plugins/other/visitor-plugin-common/src/types.ts b/packages/plugins/other/visitor-plugin-common/src/types.ts index f578446919b..e794e091218 100644 --- a/packages/plugins/other/visitor-plugin-common/src/types.ts +++ b/packages/plugins/other/visitor-plugin-common/src/types.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-empty-object-type */ -import { ASTNode, DirectiveNode, FragmentDefinitionNode } from 'graphql'; +import { ASTNode, FragmentDefinitionNode } from 'graphql'; import { ParsedMapper } from './mappers.js'; /** @@ -123,10 +123,6 @@ export interface ParsedImport { propName: string; } -export type FragmentDirectives = { - fragmentDirectives?: Array; -}; - export interface ResolversNonOptionalTypenameConfig { unionMember?: boolean; interfaceImplementingType?: boolean; diff --git a/packages/plugins/other/visitor-plugin-common/src/utils.ts b/packages/plugins/other/visitor-plugin-common/src/utils.ts index 32654d4f48e..ae1d7ce4e56 100644 --- a/packages/plugins/other/visitor-plugin-common/src/utils.ts +++ b/packages/plugins/other/visitor-plugin-common/src/utils.ts @@ -29,13 +29,7 @@ import { import { RawConfig } from './base-visitor.js'; import { parseMapper } from './mappers.js'; import { DEFAULT_SCALARS } from './scalars.js'; -import { - FragmentDirectives, - LoadedFragment, - NormalizedScalarsMap, - ParsedScalarsMap, - ScalarsMap, -} from './types.js'; +import { LoadedFragment, NormalizedScalarsMap, ParsedScalarsMap, ScalarsMap } from './types.js'; export const getConfigValue = (value: T, defaultValue: T): T => { if (value === null || value === undefined) { @@ -508,7 +502,7 @@ export const getFieldNodeNameValue = (node: FieldNode): string => { }; export function separateSelectionSet(selections: ReadonlyArray): { - fields: (FieldNode & FragmentDirectives)[]; + fields: FieldNode[]; spreads: FragmentSpreadNode[]; inlines: InlineFragmentNode[]; } { @@ -536,9 +530,12 @@ export function getPossibleTypes( return []; } -export function hasConditionalDirectives(field: FieldNode): boolean { +/** + * Check if any of the directives are conditional i.e. `@skip` and `@include` + */ +export function hasConditionalDirectives(directives: readonly DirectiveNode[] = []): boolean { const CONDITIONAL_DIRECTIVES = ['skip', 'include']; - return field.directives?.some(directive => CONDITIONAL_DIRECTIVES.includes(directive.name.value)); + return directives.some(directive => CONDITIONAL_DIRECTIVES.includes(directive.name.value)); } export function hasIncrementalDeliveryDirectives(directives: DirectiveNode[]): boolean { @@ -755,7 +752,13 @@ const getDeprecationReason = (directive: DirectiveNode): string | void => { * @param {string} params.pattern - The pattern of the Maybe type. This is usually `T | null | undefined` or `T | null` * @returns {string} The TypeScript type as string */ -export const printTypeScriptMaybeType = ({ type, pattern }: { type: string; pattern: string }): string => { +export const printTypeScriptMaybeType = ({ + type, + pattern, +}: { + type: string; + pattern: string; +}): string => { if (type === 'any' || type === 'unknown') { return type; } diff --git a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap index e15d308cbc5..fdfa43db9b4 100644 --- a/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap +++ b/packages/plugins/typescript/operations/tests/__snapshots__/ts-documents.spec.ts.snap @@ -1,15 +1,5 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`TypeScript Operations Plugin > Config > should include fragment variable definitions when experimentalFragmentVariables is set 1`] = ` -"export type TextNotificationFragmentFragment = { text?: string }; - - -export type TextNotificationFragmentFragmentVariables = Exact<{ - skip: boolean; -}>; -" -`; - exports[`TypeScript Operations Plugin > Issues > #2699 - Issues with multiple interfaces and unions 1`] = ` "export type GetEntityBrandDataQueryVariables = Exact<{ gid: string | number; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.skip-include-directives.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.skip-include-directives.spec.ts new file mode 100644 index 00000000000..3a613d12872 --- /dev/null +++ b/packages/plugins/typescript/operations/tests/ts-documents.skip-include-directives.spec.ts @@ -0,0 +1,623 @@ +import { buildSchema, parse } from 'graphql'; +import { plugin } from '../src/index.js'; +import { schema } from './shared/schema.js'; + +describe('TypeScript Operations Plugin - @include directives', () => { + it('should resolve optionals according to maybeValue', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User! + } + + type User { + name: String! + age: Int + address: String! + nicknames: [String!] + parents: [User!]! + } + `); + + const fragment = parse(/* GraphQL */ ` + query user($showProperty: Boolean!) { + user { + name + age + address @include(if: $showProperty) + nicknames @include(if: $showProperty) + parents @include(if: $showProperty) + } + } + `); + + const { content } = await plugin( + schema, + [{ location: '', document: fragment }], + { maybeValue: "T | 'specialType'" }, + { outputFile: 'graphql.ts' } + ); + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + showProperty: boolean; + }>; + + + export type UserQuery = { user: { name: string, age: number | 'specialType', address?: string, nicknames?: Array | 'specialType', parents?: Array } }; + " + `); + }); + + it('should add undefined as possible value according to allowUndefinedQueryVariables', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User! + } + + type User { + name: String! + age: Int + address: String! + nicknames: [String!] + parents: [User!]! + } + `); + + const fragment = parse(/* GraphQL */ ` + query user($showProperty: Boolean!) { + user { + name + age + address @include(if: $showProperty) + nicknames @include(if: $showProperty) + parents @include(if: $showProperty) + } + } + `); + + const { content } = await plugin( + schema, + [{ location: '', document: fragment }], + { allowUndefinedQueryVariables: true }, + { outputFile: 'graphql.ts' } + ); + + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + showProperty: boolean; + }> | undefined; + + + export type UserQuery = { user: { name: string, age: number | null, address?: string, nicknames?: Array | null, parents?: Array } }; + " + `); + }); + + it('#2506 - inline fragment without typeCondition specified', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User + } + + type User { + name: String + } + `); + + const fragment = parse(/* GraphQL */ ` + query user($withUser: Boolean! = false) { + ... @include(if: $withUser) { + user { + name + } + } + } + `); + + const { content } = await plugin(schema, [{ location: '', document: fragment }], {}, { outputFile: 'graphql.ts' }); + + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + withUser?: boolean; + }>; + + + export type UserQuery = + | { user?: { name: string | null } | null } + | Record + ; + " + `); + }); + + it('fields with @include should pre resolve into optional', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User! + } + + type User { + name: String! + address: String! + nicknames: [String!] + parents: [User!]! + } + `); + + const fragment = parse(/* GraphQL */ ` + query user($showAddress: Boolean!) { + user { + name + address @include(if: $showAddress) + nicknames @include(if: $showNicknames) + parents @include(if: $showParents) + } + } + `); + + const { content } = await plugin(schema, [{ location: '', document: fragment }], {}, { outputFile: 'graphql.ts' }); + + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + showAddress: boolean; + }>; + + + export type UserQuery = { user: { name: string, address?: string, nicknames?: Array | null, parents?: Array } }; + " + `); + }); + + it('objects with @include should pre resolve into optional', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User! + } + + type User { + id: String! + name: String! + address: Address! + friends: [User!]! + moreFriends: [User!]! + } + + type Address { + city: String! + } + `); + + const fragment = parse(/* GraphQL */ ` + query user($showAddress: Boolean!, $showName: Boolean!) { + user { + id + name @include(if: $showName) + address @include(if: $showAddress) { + city + } + friends @include(if: $isFriendly) { + id + } + } + } + `); + + const { content } = await plugin(schema, [{ location: '', document: fragment }], {}, { outputFile: 'graphql.ts' }); + + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + showAddress: boolean; + showName: boolean; + }>; + + + export type UserQuery = { user: { id: string, name?: string, address?: { city: string }, friends?: Array<{ id: string }> } }; + " + `); + }); + + it('optionals (?) on types should be avoided by default', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + me: User! + } + + type User { + messages: [Message!]! + } + + type Message { + content: String! + } + `); + + const fragment = parse(/* GraphQL */ ` + query MyQuery($include: Boolean!) { + me { + messages @include(if: $include) { + content + } + } + } + `); + + const { content } = await plugin( + schema, + [{ location: '', document: fragment }], + { nonOptionalTypename: true }, + { outputFile: 'graphql.ts' } + ); + + expect(content).toMatchInlineSnapshot(` + "export type MyQueryQueryVariables = Exact<{ + include: boolean; + }>; + + + export type MyQueryQuery = { __typename: 'Query', me: { __typename: 'User', messages?: Array<{ __typename: 'Message', content: string }> } }; + " + `); + }); + + it('inline fragment with conditional directives', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User + group: Group! + } + + type User { + name: String + } + + type Group { + id: Int! + } + `); + + const fragment = parse(/* GraphQL */ ` + query user($withUser: Boolean! = false) { + ... @include(if: $withUser) { + user { + name + } + group { + id + } + } + } + `); + + const { content } = await plugin(schema, [{ location: '', document: fragment }], {}, { outputFile: 'graphql.ts' }); + + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + withUser?: boolean; + }>; + + + export type UserQuery = + | { user?: { name: string | null } | null, group?: { id: number } } + | Record + ; + " + `); + }); + + it('resolve optionals according to maybeValue and conditional directives', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User! + } + + type User { + name: String! + age: Int + address: String! + nicknames: [String!] + parents: [User!]! + } + `); + + const fragment = parse(/* GraphQL */ ` + query user($showProperty: Boolean!) { + user { + name + age + address @include(if: $showProperty) + nicknames @include(if: $showProperty) + parents @include(if: $showProperty) + } + } + `); + + const { content } = await plugin( + schema, + [{ location: '', document: fragment }], + { maybeValue: "T | 'specialType'" }, + { outputFile: 'graphql.ts' } + ); + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + showProperty: boolean; + }>; + + + export type UserQuery = { user: { name: string, age: number | 'specialType', address?: string, nicknames?: Array | 'specialType', parents?: Array } }; + " + `); + }); + + it('generates optional field when @include is used on an aliased field', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + users: [User!]! + } + + type User { + id: ID! + name: String! + } + `); + + const document = parse(/* GraphQL */ ` + query GetUsers($included: Boolean!) { + aliasedUsers: users @include(if: $included) { + id + userName: name @include(if: $included) + } + users { + id + userName: name @include(if: $included) + } + } + `); + + const { content } = await plugin(schema, [{ location: '', document }], {}, { outputFile: 'graphql.ts' }); + + expect(content).toMatchInlineSnapshot(` + "export type GetUsersQueryVariables = Exact<{ + included: boolean; + }>; + + + export type GetUsersQuery = { aliasedUsers?: Array<{ id: string, userName?: string }>, users: Array<{ id: string, userName?: string }> }; + " + `); + }); + + it('generates optional object when @include is used on an inline fragment', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User + users: [User!]! + } + + type User { + id: ID! + name: String! + nickName: String! + age: Int! + createdAt: String! + } + `); + + const document = parse(/* GraphQL */ ` + query User($included: Boolean!) { + user { + id + ... @include(if: $included) { + name + niName: nickName + } + ... on User @include(if: $included) { + age + } + ... { + createdAt + } + } + } + query GetUsers($included: Boolean!) { + users { + id + ... @include(if: $included) { + name + niName: nickName + } + ... on User @include(if: $included) { + age + } + } + } + `); + + const { content } = await plugin(schema, [{ location: '', document }], {}, { outputFile: 'graphql.ts' }); + + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + included: boolean; + }>; + + + export type UserQuery = { user: { createdAt: string, id: string } & { name?: string, niName?: string } & { age?: number } | null }; + + export type GetUsersQueryVariables = Exact<{ + included: boolean; + }>; + + + export type GetUsersQuery = { users: Array<{ id: string } & { name?: string, niName?: string } & { age?: number }> }; + " + `); + }); +}); + +describe('TypeScript Operations Plugin - @skip directive', () => { + it('#8461 - conditional directives are ignored on fields with alias', async () => { + const testSchema = buildSchema(/* GraphQL */ ` + type User { + firstName: String! + lastName: Int! + address: Address! + } + + type Address { + postalCode: String! + } + + type Query { + viewer: User! + } + `); + + const query = parse(/* GraphQL */ ` + query UserQuery($skipFirstName: Boolean!, $skipAddress: Boolean!) { + viewer { + givenName: firstName @skip(if: $skipFirstName) + lastName + mailingAddress: address @skip(if: $skipAddress) { + postalCode + } + } + } + `); + + const { content } = await plugin(testSchema, [{ location: '', document: query }], {}, { outputFile: 'graphql.ts' }); + + expect(content).toMatchInlineSnapshot(` + "export type UserQueryQueryVariables = Exact<{ + skipFirstName: boolean; + skipAddress: boolean; + }>; + + + export type UserQueryQuery = { viewer: { lastName: number, givenName?: string, mailingAddress?: { postalCode: string } } }; + " + `); + }); + + it('should include fragment variable definitions when experimentalFragmentVariables is set', async () => { + const ast = parse( + /* GraphQL */ ` + fragment TextNotificationFragment($skip: Boolean!) on TextNotification { + text @skip(if: $skip) + } + `, + // < v15 compatibility + { experimentalFragmentVariables: true, allowLegacyFragmentVariables: true } as any + ); + const config = { experimentalFragmentVariables: true }; + const { content } = await plugin(schema, [{ location: 'test-file.ts', document: ast }], config, { + outputFile: '', + }); + expect(content).toMatchInlineSnapshot(` + "export type TextNotificationFragmentFragment = { text?: string }; + + + export type TextNotificationFragmentFragmentVariables = Exact<{ + skip: boolean; + }>; + " + `); + }); + + it('generates optional field when @skip is used on an aliased field', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + users: [User!]! + } + + type User { + id: ID! + name: String! + } + `); + + const document = parse(/* GraphQL */ ` + query GetUsers($skipName: Boolean!) { + users { + id + userName: name @skip(if: $skipName) + } + } + `); + + const { content } = await plugin(schema, [{ location: '', document }], {}, { outputFile: 'graphql.ts' }); + + expect(content).toMatchInlineSnapshot(` + "export type GetUsersQueryVariables = Exact<{ + skipName: boolean; + }>; + + + export type GetUsersQuery = { users: Array<{ id: string, userName?: string }> }; + " + `); + }); + + it('generates optional object when @skip is used on an inline fragment', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User + users: [User!]! + } + + type User { + id: ID! + name: String! + nickName: String! + age: Int! + createdAt: String! + } + `); + + const document = parse(/* GraphQL */ ` + query User($skip: Boolean!) { + user { + id + ... @skip(if: $skip) { + name + niName: nickName + } + ... on User @skip(if: $included) { + age + } + ... { + createdAt + } + } + } + query GetUsers($skip: Boolean!) { + users { + id + ... @skip(if: $skip) { + name + niName: nickName + } + ... on User @skip(if: $skip) { + age + } + } + } + `); + + const { content } = await plugin(schema, [{ location: '', document }], {}, { outputFile: 'graphql.ts' }); + + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + skip: boolean; + }>; + + + export type UserQuery = { user: { createdAt: string, id: string } & { name?: string, niName?: string } & { age?: number } | null }; + + export type GetUsersQueryVariables = Exact<{ + skip: boolean; + }>; + + + export type GetUsersQuery = { users: Array<{ id: string } & { name?: string, niName?: string } & { age?: number }> }; + " + `); + }); +}); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts index ea59956a13b..2708dec92c1 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.spec.ts @@ -150,126 +150,6 @@ describe('TypeScript Operations Plugin', () => { `); await validate(content); }); - - it('should include fragment variable definitions when experimentalFragmentVariables is set', async () => { - const ast = parse( - /* GraphQL */ ` - fragment TextNotificationFragment($skip: Boolean!) on TextNotification { - text @skip(if: $skip) - } - `, - // < v15 compatibility - { - experimentalFragmentVariables: true, - allowLegacyFragmentVariables: true, - } as any, - ); - const config = { experimentalFragmentVariables: true }; - const { content } = await plugin( - schema, - [{ location: 'test-file.ts', document: ast }], - config, - { - outputFile: '', - }, - ); - expect(content).toMatchSnapshot(); - }); - - it('should resolve optionals according to maybeValue', async () => { - const schema = buildSchema(/* GraphQL */ ` - type Query { - user: User! - } - - type User { - name: String! - age: Int - address: String! - nicknames: [String!] - parents: [User!]! - } - `); - - const fragment = parse(/* GraphQL */ ` - query user($showProperty: Boolean!) { - user { - name - age - address @include(if: $showProperty) - nicknames @include(if: $showProperty) - parents @include(if: $showProperty) - } - } - `); - - const { content } = await plugin( - schema, - [{ location: '', document: fragment }], - { - maybeValue: "T | 'specialType'", - }, - { - outputFile: 'graphql.ts', - }, - ); - expect(content).toMatchInlineSnapshot(` - "export type UserQueryVariables = Exact<{ - showProperty: boolean; - }>; - - - export type UserQuery = { user: { name: string, age: number | 'specialType', address?: string, nicknames?: Array | 'specialType', parents?: Array } }; - " - `); - }); - - it('should add undefined as possible value according to allowUndefinedQueryVariables', async () => { - const schema = buildSchema(/* GraphQL */ ` - type Query { - user: User! - } - - type User { - name: String! - age: Int - address: String! - nicknames: [String!] - parents: [User!]! - } - `); - - const fragment = parse(/* GraphQL */ ` - query user($showProperty: Boolean!) { - user { - name - age - address @include(if: $showProperty) - nicknames @include(if: $showProperty) - parents @include(if: $showProperty) - } - } - `); - - const { content } = await plugin( - schema, - [{ location: '', document: fragment }], - { - allowUndefinedQueryVariables: true, - }, - { outputFile: 'graphql.ts' }, - ); - - expect(content).toMatchInlineSnapshot(` - "export type UserQueryVariables = Exact<{ - showProperty: boolean; - }> | undefined; - - - export type UserQuery = { user: { name: string, age: number | null, address?: string, nicknames?: Array | null, parents?: Array } }; - " - `); - }); }); describe('Custom Operation Result Name Suffix', () => { @@ -4843,45 +4723,6 @@ function test(q: GetEntityBrandDataQuery): void { `); }); - it('#2506 - inline fragment without typeCondition specified', async () => { - const schema = buildSchema(/* GraphQL */ ` - type Query { - user: User - } - - type User { - name: String - } - `); - - const fragment = parse(/* GraphQL */ ` - query user($withUser: Boolean! = false) { - ... @include(if: $withUser) { - user { - name - } - } - } - `); - - const { content } = await plugin( - schema, - [{ location: '', document: fragment }], - {}, - { outputFile: 'graphql.ts' }, - ); - - expect(content).toMatchInlineSnapshot(` - "export type UserQueryVariables = Exact<{ - withUser?: boolean; - }>; - - - export type UserQuery = { user?: { name: string | null } | null }; - " - `); - }); - it('#2436 - interface with field of same name but different type is correctly handled', async () => { const schema = buildSchema(/* GraphQL */ ` interface DashboardTile { @@ -5640,286 +5481,6 @@ function test(q: GetEntityBrandDataQuery): void { " `); }); - - it('#8461 - conditional directives are ignored on fields with alias', async () => { - const testSchema = buildSchema(/* GraphQL */ ` - type User { - firstName: String! - lastName: Int! - address: Address! - } - - type Address { - postalCode: String! - } - - type Query { - viewer: User! - } - `); - - const query = parse(/* GraphQL */ ` - query UserQuery($skipFirstName: Boolean!, $skipAddress: Boolean!) { - viewer { - givenName: firstName @skip(if: $skipFirstName) - lastName - mailingAddress: address @skip(if: $skipAddress) { - postalCode - } - } - } - `); - - const { content } = await plugin( - testSchema, - [{ location: '', document: query }], - {}, - { outputFile: 'graphql.ts' }, - ); - - expect(content).toMatchInlineSnapshot(` - "export type UserQueryQueryVariables = Exact<{ - skipFirstName: boolean; - skipAddress: boolean; - }>; - - - export type UserQueryQuery = { viewer: { lastName: number, givenName?: string, mailingAddress?: { postalCode: string } } }; - " - `); - }); - }); - - describe('conditional directives handling', () => { - it('fields with @skip, @include should pre resolve into optional', async () => { - const schema = buildSchema(/* GraphQL */ ` - type Query { - user: User! - } - - type User { - name: String! - address: String! - nicknames: [String!] - parents: [User!]! - } - `); - - const fragment = parse(/* GraphQL */ ` - query user($showAddress: Boolean!) { - user { - name - address @include(if: $showAddress) - nicknames @include(if: $showNicknames) - parents @include(if: $showParents) - } - } - `); - - const { content } = await plugin( - schema, - [{ location: '', document: fragment }], - {}, - { outputFile: 'graphql.ts' }, - ); - - expect(content).toMatchInlineSnapshot(` - "export type UserQueryVariables = Exact<{ - showAddress: boolean; - }>; - - - export type UserQuery = { user: { name: string, address?: string, nicknames?: Array | null, parents?: Array } }; - " - `); - }); - - it('objects with @skip, @include should pre resolve into optional', async () => { - const schema = buildSchema(/* GraphQL */ ` - type Query { - user: User! - } - - type User { - id: String! - name: String! - address: Address! - friends: [User!]! - moreFriends: [User!]! - } - - type Address { - city: String! - } - `); - - const fragment = parse(/* GraphQL */ ` - query user($showAddress: Boolean!, $showName: Boolean!) { - user { - id - name @include(if: $showName) - address @include(if: $showAddress) { - city - } - friends @include(if: $isFriendly) { - id - } - } - } - `); - - const { content } = await plugin( - schema, - [{ location: '', document: fragment }], - {}, - { outputFile: 'graphql.ts' }, - ); - - expect(content).toMatchInlineSnapshot(` - "export type UserQueryVariables = Exact<{ - showAddress: boolean; - showName: boolean; - }>; - - - export type UserQuery = { user: { id: string, name?: string, address?: { city: string }, friends?: Array<{ id: string }> } }; - " - `); - }); - - it('optionals (?) on types should be avoided by default', async () => { - const schema = buildSchema(/* GraphQL */ ` - type Query { - me: User! - } - - type User { - messages: [Message!]! - } - - type Message { - content: String! - } - `); - - const fragment = parse(/* GraphQL */ ` - query MyQuery($include: Boolean!) { - me { - messages @include(if: $include) { - content - } - } - } - `); - - const { content } = await plugin( - schema, - [{ location: '', document: fragment }], - { nonOptionalTypename: true }, - { outputFile: 'graphql.ts' }, - ); - - expect(content).toMatchInlineSnapshot(` - "export type MyQueryQueryVariables = Exact<{ - include: boolean; - }>; - - - export type MyQueryQuery = { __typename: 'Query', me: { __typename: 'User', messages?: Array<{ __typename: 'Message', content: string }> } }; - " - `); - }); - - it('inline fragment with conditional directives', async () => { - const schema = buildSchema(/* GraphQL */ ` - type Query { - user: User - group: Group! - } - - type User { - name: String - } - - type Group { - id: Int! - } - `); - - const fragment = parse(/* GraphQL */ ` - query user($withUser: Boolean! = false) { - ... @include(if: $withUser) { - user { - name - } - group { - id - } - } - } - `); - - const { content } = await plugin( - schema, - [{ location: '', document: fragment }], - {}, - { outputFile: 'graphql.ts' }, - ); - - expect(content).toMatchInlineSnapshot(` - "export type UserQueryVariables = Exact<{ - withUser?: boolean; - }>; - - - export type UserQuery = { user?: { name: string | null } | null, group?: { id: number } }; - " - `); - }); - - it('resolve optionals according to maybeValue and conditional directives', async () => { - const schema = buildSchema(/* GraphQL */ ` - type Query { - user: User! - } - - type User { - name: String! - age: Int - address: String! - nicknames: [String!] - parents: [User!]! - } - `); - - const fragment = parse(/* GraphQL */ ` - query user($showProperty: Boolean!) { - user { - name - age - address @include(if: $showProperty) - nicknames @include(if: $showProperty) - parents @include(if: $showProperty) - } - } - `); - - const { content } = await plugin( - schema, - [{ location: '', document: fragment }], - { maybeValue: "T | 'specialType'" }, - { outputFile: 'graphql.ts' }, - ); - expect(content).toMatchInlineSnapshot(` - "export type UserQueryVariables = Exact<{ - showProperty: boolean; - }>; - - - export type UserQuery = { user: { name: string, age: number | 'specialType', address?: string, nicknames?: Array | 'specialType', parents?: Array } }; - " - `); - }); }); describe('incremental delivery directive handling', () => { From f27de9e3b9e6272b664f631f7b360b1cb5e56dd9 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Thu, 19 Mar 2026 01:10:52 +1100 Subject: [PATCH 54/69] [typescript-operations] Fix @skip and @include not applying conditional modifiers correctly when used on fragment spread (#10646) * Set up TDD * WIP implement conditional fragmentspread * Fix empty object detection logic * Format/cleanup * Add test for include+skip+defer * Add changeset * Fix test --- .changeset/tiny-baboons-fry.md | 5 + .../src/selection-set-to-object.ts | 217 ++++++++++++------ .../other/visitor-plugin-common/src/utils.ts | 5 +- ...-documents.skip-include-directives.spec.ts | 214 +++++++++++++++++ 4 files changed, 370 insertions(+), 71 deletions(-) create mode 100644 .changeset/tiny-baboons-fry.md diff --git a/.changeset/tiny-baboons-fry.md b/.changeset/tiny-baboons-fry.md new file mode 100644 index 00000000000..7ffa62adc80 --- /dev/null +++ b/.changeset/tiny-baboons-fry.md @@ -0,0 +1,5 @@ +--- +'@graphql-codegen/typescript-operations': patch +--- + +Fix `@skip` and `@include` not applying conditional modifiers correctly when used on fragment sread, and `@defer` fragments diff --git a/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts b/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts index d70a7fb5b48..69cdce1906a 100644 --- a/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts +++ b/packages/plugins/other/visitor-plugin-common/src/selection-set-to-object.ts @@ -57,7 +57,7 @@ type FragmentSpreadUsage = { fragmentName: string; typeName: string; onType: string; - selectionNodes: Array; + selectionNodes: Array; fragmentDirectives: DirectiveNode[]; }; @@ -302,11 +302,23 @@ export class SelectionSetToObject< selectionNodesByTypeName[possibleType.name] ||= []; + const fragmentSelectionNodes: FragmentSpreadUsage['selectionNodes'] = [ + ...fragmentSpreadObject.node.selectionSet.selections, + ].map(originalNode => { + if (originalNode.kind === Kind.FIELD) { + return { + ...originalNode, + fragmentDirectives: [...spread.directives], + } satisfies EnrichedFieldNode; + } + return originalNode; + }); + selectionNodesByTypeName[possibleType.name].push({ fragmentName: spread.name.value, typeName: usage, onType: fragmentSpreadObject.onType, - selectionNodes: [...fragmentSpreadObject.node.selectionSet.selections], + selectionNodes: fragmentSelectionNodes, fragmentDirectives: [...spread.directives], }); } @@ -330,24 +342,39 @@ export class SelectionSetToObject< const inlineFragmentSelections: InlineFragmentNode[] = []; /** - * Inline fragments marked with `@skip` or `@include` + * Inline fragments marked with `@skip`, `@include` or `@defer` */ const inlineFragmentConditionalSelections: InlineFragmentNode[] = []; const fieldNodes: FieldNode[] = []; const fragmentSpreads: FragmentSpreadNode[] = []; + /** + * Fragment spreads marked with `@skip` or `@include` or `@defer` + */ + const fragmentSpreadsConditionalSelections: FragmentSpreadNode[] = []; + for (const selection of selections) { switch (selection.kind) { case Kind.FIELD: fieldNodes.push(selection); break; case Kind.INLINE_FRAGMENT: - if (hasConditionalDirectives(selection.directives)) { + if ( + hasConditionalDirectives(selection.directives) || + hasIncrementalDeliveryDirectives(selection.directives) + ) { inlineFragmentConditionalSelections.push(selection); break; } inlineFragmentSelections.push(selection); break; case Kind.FRAGMENT_SPREAD: + if ( + hasConditionalDirectives(selection.directives) || + hasIncrementalDeliveryDirectives(selection.directives) + ) { + fragmentSpreadsConditionalSelections.push(selection); + break; + } fragmentSpreads.push(selection); break; } @@ -356,8 +383,8 @@ export class SelectionSetToObject< // 1. Merge all selection sets that are mergable into one object. This includes: // - field // - field with conditional directives - // - inline fragment without conditional directives - // - fragment spreads + // - inline fragment without conditional/incremental directives + // - fragment spreads without conditional/incremental directives // Turn field nodes into one inline fragments to simplify collecting fields from selections using _collectInlineFragments if (fieldNodes.length) { @@ -382,15 +409,16 @@ export class SelectionSetToObject< inlineFragmentSelections, result.selectionNodesByTypeName, ); - const fragmentsUsage = this.buildFragmentSpreadsUsage(fragmentSpreads); + // Add fragment spreads into selection nodes so it becomes part of the base selection + const fragmentSpreadsUsage = this.buildFragmentSpreadsUsage(fragmentSpreads); - for (const [typeName, records] of Object.entries(fragmentsUsage)) { + for (const [typeName, records] of Object.entries(fragmentSpreadsUsage)) { this._appendToTypeMap(result.selectionNodesByTypeName, typeName, records); } // 2. Push conditional inline fragments into the result.selectionNodesByTypeNameConditional // This is treated differently from result.selectionNodesByTypeName - // because every field in result.selectionNodesByTypeNameConditional is optional + // because fields in result.selectionNodesByTypeNameConditional are optional for (const inlineFragmentConditionalSelection of inlineFragmentConditionalSelections) { const selectionNodes = new Map>(); this._collectInlineFragments( @@ -401,6 +429,20 @@ export class SelectionSetToObject< result.selectionNodesByTypeNameConditional.push(selectionNodes); } + // 3. Push conditional FragmentSpreadUsage into the result.selectionNodesByTypeNameConditional + // This is important to track because fields in a conditional Fragment Spread are optional + for (const fragmentSpreadsConditionalSelection of fragmentSpreadsConditionalSelections) { + const conditionalFragmentSpreadsUsage = this.buildFragmentSpreadsUsage([ + fragmentSpreadsConditionalSelection, + ]); + + for (const [typeName, records] of Object.entries(conditionalFragmentSpreadsUsage)) { + const selectionNodes = new Map>(); + this._appendToTypeMap(selectionNodes, typeName, records); + result.selectionNodesByTypeNameConditional.push(selectionNodes); + } + } + return result; } @@ -430,13 +472,13 @@ export class SelectionSetToObject< const { selectionNodesByTypeName, selectionNodesByTypeNameConditional } = this.flattenSelectionSet(this._selectionSet.selections); - // in case there is not a selection for each type, we need to add a empty type. - let mustAddEmptyObject = false; - const possibleTypes = getPossibleTypes(this._schema, this._parentSchemaType); const dependentTypes: DependentType[] = []; if (!this._config.mergeFragmentTypes || this._config.inlineFragmentTypes === 'mask') { + // in case there is not a selection for each type, we need to add a empty type. + let mustAddEmptyObject = false; + // Each grouped type contains an array of stringified objects to be merged. // Once merged, the type would be the TypeScript representative of the GraphQL selection set // For example: @@ -460,27 +502,9 @@ export class SelectionSetToObject< prev[typeName] ||= []; - const collectGrouped = (nodes: GroupedTypeNameNode[]): void => { - // incrementalNodes are the ones flagged with @defer, meaning they become nullable - const { selectionNodes, incrementalNodes, fragmentSpreads } = nodes.reduce<{ - selectionNodes: GroupedTypeNameNode[]; - incrementalNodes: FragmentSpreadUsage[]; - fragmentSpreads: string[]; - }>( - (acc, node) => { - if ( - 'fragmentDirectives' in node && - hasIncrementalDeliveryDirectives(node.fragmentDirectives) - ) { - acc.incrementalNodes.push(node as FragmentSpreadUsage); // FIXME: check whether @defer would pick up EnrichedFieldNode here too? - } else { - acc.selectionNodes.push(node); - } - return acc; - }, - { selectionNodes: [], incrementalNodes: [], fragmentSpreads: [] }, - ); - + const collectGrouped = ( + selectionNodes: GroupedTypeNameNode[], + ): { hasTransformedSelectionSet: boolean } => { const { fields, dependentTypes: subDependentTypes } = this.buildSelectionSet( schemaType, selectionNodes, @@ -494,49 +518,98 @@ export class SelectionSetToObject< prev[typeName].push(transformedSet); } dependentTypes.push(...subDependentTypes); - if (!transformedSet && !fragmentSpreads.length) { - mustAddEmptyObject = true; + + return { + hasTransformedSelectionSet: !!transformedSet, + }; + }; + + const { hasTransformedSelectionSet } = collectGrouped( + selectionNodesByTypeName.get(typeName) || [], + ); + if (!hasTransformedSelectionSet) { + mustAddEmptyObject = true; + } + + for (const conditionalNodes of selectionNodesByTypeNameConditional) { + const selectionNodes = (conditionalNodes.get(typeName) || []).filter( + (node): node is EnrichedFieldNode | FragmentSpreadUsage => 'fragmentDirectives' in node, + ); + + let conditionalDirectivesFound = false; + let incrementalDirectivesFound = false; + for (const selectionNode of selectionNodes) { + if (hasConditionalDirectives(selectionNode.fragmentDirectives)) { + conditionalDirectivesFound = true; + } + if (hasIncrementalDeliveryDirectives(selectionNode.fragmentDirectives)) { + incrementalDirectivesFound = true; + } } - for (const incrementalNode of incrementalNodes) { - // 1. fragment masking - if (this._config.inlineFragmentTypes === 'mask' && 'fragmentName' in incrementalNode) { - const { fields: incrementalFields, dependentTypes: incrementalDependentTypes } = + if (conditionalDirectivesFound) { + // When a FragmentSpreadUsage is marked as conditional, + // it should just be treated like an Inline Fragment + // i.e. every field in the fragment's selection set should be optional + const flattenedSelectionNodes = selectionNodes.reduce( + (prev, node) => { + if ('kind' in node) { + prev.push(node); + return prev; + } + + // When a node is a FragmentSpreadUsage, + // We just "inline" all the field in its selection set. Note: each field has fragmentDirectives which should contain `@skip` or `@inlcude` + // So, `buildSelectionSet` function below can correctly make said fields optional + for (const fragmentSpreadUsageSelectionNode of node.selectionNodes) { + prev.push(fragmentSpreadUsageSelectionNode); + } + return prev; + }, + [], + ); + + collectGrouped(flattenedSelectionNodes); + } + + if (incrementalDirectivesFound) { + for (const incrementalNode of selectionNodes) { + // 1. fragment masking + if ( + this._config.inlineFragmentTypes === 'mask' && + 'fragmentName' in incrementalNode + ) { + const { fields: incrementalFields, dependentTypes: incrementalDependentTypes } = + this.buildSelectionSet(schemaType, [incrementalNode], { + unsetTypes: true, + parentFieldName: parentName, + }); + const incrementalSet = this.selectionSetStringFromFields(incrementalFields); + prev[typeName].push(incrementalSet); + dependentTypes.push(...incrementalDependentTypes); + + continue; + } + + // 2. @defer + const { fields: initialFields, dependentTypes: initialDependentTypes } = + this.buildSelectionSet(schemaType, [incrementalNode], { + parentFieldName: parentName, + }); + + const { fields: subsequentFields, dependentTypes: subsequentDependentTypes } = this.buildSelectionSet(schemaType, [incrementalNode], { unsetTypes: true, parentFieldName: parentName, }); - const incrementalSet = this.selectionSetStringFromFields(incrementalFields); - prev[typeName].push(incrementalSet); - dependentTypes.push(...incrementalDependentTypes); - continue; - } + const initialSet = this.selectionSetStringFromFields(initialFields); + const subsequentSet = this.selectionSetStringFromFields(subsequentFields); + dependentTypes.push(...initialDependentTypes, ...subsequentDependentTypes); - // 2. @defer - const { fields: initialFields, dependentTypes: initialDependentTypes } = - this.buildSelectionSet(schemaType, [incrementalNode], { - parentFieldName: parentName, - }); - - const { fields: subsequentFields, dependentTypes: subsequentDependentTypes } = - this.buildSelectionSet(schemaType, [incrementalNode], { - unsetTypes: true, - parentFieldName: parentName, - }); - - const initialSet = this.selectionSetStringFromFields(initialFields); - const subsequentSet = this.selectionSetStringFromFields(subsequentFields); - dependentTypes.push(...initialDependentTypes, ...subsequentDependentTypes); - prev[typeName].push({ union: [initialSet, subsequentSet] }); + prev[typeName].push({ union: [initialSet, subsequentSet] }); + } } - }; - - const selectionNodes = selectionNodesByTypeName.get(typeName) || []; - collectGrouped(selectionNodes); - - for (const conditionalNodes of selectionNodesByTypeNameConditional) { - collectGrouped(conditionalNodes.get(typeName) || []); } return prev; @@ -544,6 +617,7 @@ export class SelectionSetToObject< return { grouped, mustAddEmptyObject, dependentTypes }; } + // Accumulate a map of selected fields to the typenames that // share the exact same selected fields. When we find multiple // typenames with the same set of fields, we can collapse the @@ -635,7 +709,7 @@ export class SelectionSetToObject< return acc; }, {}); - return { grouped: compacted, mustAddEmptyObject, dependentTypes }; + return { grouped: compacted, mustAddEmptyObject: false, dependentTypes }; } protected selectionSetStringFromFields(fields: (string | NameAndType)[]): string | null { @@ -665,7 +739,7 @@ export class SelectionSetToObject< string, { selectedFieldType: GraphQLOutputType; - field: FieldNode; + field: EnrichedFieldNode; } >(); let requireTypename = false; @@ -800,7 +874,10 @@ export class SelectionSetToObject< ); linkFieldsInterfaces.push(...selectionSetObjects.dependentTypes); - const isConditional = hasConditionalDirectives(field.directives) || inlineFragmentConditional; + const isConditional = + hasConditionalDirectives(field.directives) || + hasConditionalDirectives(field.fragmentDirectives) || + inlineFragmentConditional; linkFields.push({ alias: field.alias ? this._processor.config.formatNamedField({ diff --git a/packages/plugins/other/visitor-plugin-common/src/utils.ts b/packages/plugins/other/visitor-plugin-common/src/utils.ts index ae1d7ce4e56..c60626e9f12 100644 --- a/packages/plugins/other/visitor-plugin-common/src/utils.ts +++ b/packages/plugins/other/visitor-plugin-common/src/utils.ts @@ -538,7 +538,10 @@ export function hasConditionalDirectives(directives: readonly DirectiveNode[] = return directives.some(directive => CONDITIONAL_DIRECTIVES.includes(directive.name.value)); } -export function hasIncrementalDeliveryDirectives(directives: DirectiveNode[]): boolean { +/** + * Check if any of the directives are incremental i.e. `@defer` + */ +export function hasIncrementalDeliveryDirectives(directives: readonly DirectiveNode[] = []): boolean { const INCREMENTAL_DELIVERY_DIRECTIVES = ['defer']; return directives?.some(directive => INCREMENTAL_DELIVERY_DIRECTIVES.includes(directive.name.value), diff --git a/packages/plugins/typescript/operations/tests/ts-documents.skip-include-directives.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.skip-include-directives.spec.ts index 3a613d12872..7c61096196e 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.skip-include-directives.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.skip-include-directives.spec.ts @@ -450,6 +450,80 @@ describe('TypeScript Operations Plugin - @include directives', () => { " `); }); + + it('generates optional object when @include is used on a fragment spread', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User + users: [User!]! + } + + type User { + id: ID! + name: String! + nickName: String! + age: Int! + createdAt: String! + } + `); + + const document = parse(/* GraphQL */ ` + query User($included: Boolean!) { + user { + id + ...User_Name @include(if: $included) + ...User_Age @include + ...User_CreatedAt # This is not conditional, so it should be merged with base selection set that includes the id field + } + } + query GetUsers($included: Boolean!) { + users { + id + ...User_Name @include(if: $included) + ...User_Age @include(if: $included) + ...User_CreatedAt + } + } + + fragment User_Name on User { + name + niName: nickName + } + + fragment User_Age on User { + age + } + + fragment User_CreatedAt on User { + createdAt + } + `); + + const { content } = await plugin(schema, [{ location: '', document }], {}, { outputFile: 'graphql.ts' }); + + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + included: boolean; + }>; + + + export type UserQuery = { user: { id: string, createdAt: string } & { name?: string, niName?: string } & { age?: number } | null }; + + export type GetUsersQueryVariables = Exact<{ + included: boolean; + }>; + + + export type GetUsersQuery = { users: Array<{ id: string, createdAt: string } & { name?: string, niName?: string } & { age?: number }> }; + + export type User_NameFragment = { name: string, niName: string }; + + export type User_AgeFragment = { age: number }; + + export type User_CreatedAtFragment = { createdAt: string }; + " + `); + }); }); describe('TypeScript Operations Plugin - @skip directive', () => { @@ -620,4 +694,144 @@ describe('TypeScript Operations Plugin - @skip directive', () => { " `); }); + + it('generates optional object when @skip is used on a fragment spread', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User + users: [User!]! + } + + type User { + id: ID! + name: String! + nickName: String! + age: Int! + createdAt: String! + } + `); + + const document = parse(/* GraphQL */ ` + query User($skip: Boolean!) { + user { + id + ...User_Name @skip(if: $skip) + ...User_Age @skip + ...User_CreatedAt # This is not conditional, so it should be merged with base selection set that includes the id field + } + } + query GetUsers($skip: Boolean!) { + users { + id + ...User_Name @skip(if: $skip) + ...User_Age @skip(if: $skip) + ...User_CreatedAt + } + } + + fragment User_Name on User { + name + niName: nickName + } + + fragment User_Age on User { + age + } + + fragment User_CreatedAt on User { + createdAt + } + `); + + const { content } = await plugin(schema, [{ location: '', document }], {}, { outputFile: 'graphql.ts' }); + + expect(content).toMatchInlineSnapshot(` + "export type UserQueryVariables = Exact<{ + skip: boolean; + }>; + + + export type UserQuery = { user: { id: string, createdAt: string } & { name?: string, niName?: string } & { age?: number } | null }; + + export type GetUsersQueryVariables = Exact<{ + skip: boolean; + }>; + + + export type GetUsersQuery = { users: Array<{ id: string, createdAt: string } & { name?: string, niName?: string } & { age?: number }> }; + + export type User_NameFragment = { name: string, niName: string }; + + export type User_AgeFragment = { age: number }; + + export type User_CreatedAtFragment = { createdAt: string }; + " + `); + }); +}); + +describe('TypeScript Operations Plugin - @include and @skip with @defer', () => { + it('generates conditional object with defer fields when @skip and @include are used with defer', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User + users: [User!]! + } + + type User { + id: ID! + name: String! + nickName: String! + age: Int! + createdAt: String! + } + `); + + const document = parse(/* GraphQL */ ` + query UserSkip { + user { + id + ...User_Name @skip + ...User_Age @skip @defer + } + } + + query UserInclude { + user { + id + ...User_Name @include + ...User_Age @include @defer + } + } + + fragment User_Name on User { + name + niName: nickName + } + + fragment User_Age on User { + age + createdAt + } + `); + + const { content } = await plugin(schema, [{ location: '', document }], {}, { outputFile: 'graphql.ts' }); + + expect(content).toMatchInlineSnapshot(` + "export type UserSkipQueryVariables = Exact<{ [key: string]: never; }>; + + + export type UserSkipQuery = { user: { id: string } & { name?: string, niName?: string } & { age?: number, createdAt?: string } & ({ age: number, createdAt: string } | { age?: never, createdAt?: never }) | null }; + + export type UserIncludeQueryVariables = Exact<{ [key: string]: never; }>; + + + export type UserIncludeQuery = { user: { id: string } & { name?: string, niName?: string } & { age?: number, createdAt?: string } & ({ age: number, createdAt: string } | { age?: never, createdAt?: never }) | null }; + + export type User_NameFragment = { name: string, niName: string }; + + export type User_AgeFragment = { age: number, createdAt: string }; + " + `); + }); }); From 3a834f27d9fe3a9247edf38e39af7c53cfe81ff1 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Thu, 19 Mar 2026 22:19:51 +1100 Subject: [PATCH 55/69] Add test case (#10647) --- ...-documents.skip-include-directives.spec.ts | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/packages/plugins/typescript/operations/tests/ts-documents.skip-include-directives.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.skip-include-directives.spec.ts index 7c61096196e..7167019694d 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.skip-include-directives.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.skip-include-directives.spec.ts @@ -129,6 +129,51 @@ describe('TypeScript Operations Plugin - @include directives', () => { `); }); + it('#10616 - @include on fragment with inlineFragmentTypes:combine should generate optional fragment', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user: User + } + + type User { + name: String + } + `); + + const document = parse(/* GraphQL */ ` + fragment Name on User { + name + } + query user($withName: Boolean! = false) { + user { + ...Name @include(if: $withName) + } + } + `); + + const { content } = await plugin( + schema, + [{ location: '', document }], + { inlineFragmentTypes: 'combine' }, + { outputFile: '' } + ); + + expect(content).toMatchInlineSnapshot(` + "export type NameFragment = { name: string | null }; + + export type UserQueryVariables = Exact<{ + withName?: boolean; + }>; + + + export type UserQuery = { user: + | { name?: string | null } + | Record + | null }; + " + `); + }); + it('fields with @include should pre resolve into optional', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { From 393677f62ba3bbb941cb486f92a61a411faa2371 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Thu, 19 Mar 2026 23:28:02 +1100 Subject: [PATCH 56/69] [Major version release] Drop Node 20 tests for normal runs (#10648) * Drop Node 20 tests for normal runs * Add changeset * Drop Node 20 support for watcher tests * Revert "Drop Node 20 support for watcher tests" This reverts commit cc52a81e5eb7d0f62a6f5c31ba1eebb5b34ef99f. --- .changeset/huge-hounds-arrive.md | 22 ++++++++++++++++++++++ .github/workflows/main.yml | 4 ++-- 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 .changeset/huge-hounds-arrive.md diff --git a/.changeset/huge-hounds-arrive.md b/.changeset/huge-hounds-arrive.md new file mode 100644 index 00000000000..97f7c348bda --- /dev/null +++ b/.changeset/huge-hounds-arrive.md @@ -0,0 +1,22 @@ +--- +'@graphql-codegen/visitor-plugin-common': major +'@graphql-codegen/typescript-operations': major +'@graphql-codegen/typescript': major +'@graphql-codegen/typescript-resolvers': major +'@graphql-codegen/cli': major +'@graphql-codegen/client-preset': major +'@graphql-codegen/core': major +'@graphql-codegen/add': major +'@graphql-codegen/fragment-matcher': major +'@graphql-codegen/introspection': major +'@graphql-codegen/schema-ast': major +'@graphql-codegen/time': major +'@graphql-codegen/typescript-document-nodes': major +'@graphql-codegen/gql-tag-operations': major +'@graphql-codegen/typed-document-node': major +'@graphql-codegen/graphql-modules-preset': major +'@graphql-codegen/testing': major +'@graphql-codegen/plugin-helpers': major +--- + +BREAKING CHANGE: Drop Node 20 support diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 066d1a06e03..7e621065b7c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -139,10 +139,10 @@ jobs: strategy: matrix: os: [ubuntu-latest] # remove windows to speed up the tests - node_version: [20, 22, 24] + node_version: [22, 24] graphql_version: [15, 16] include: - - node-version: 20 + - node-version: 22 os: windows-latest graphql_version: 16 steps: From 31bb77335efeb5745d26c490853e6680ff42ca21 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Sun, 22 Mar 2026 19:05:19 +1100 Subject: [PATCH 57/69] Update package deps (#10650) * Bump ESM packages - detect-indent v7 - auto-bind v5 - chalk v5 - log-symbols v7 - debounce v3 * Bum all package deps to latest * chore(dependencies): updated changesets for modified dependencies * Revert @inquirer/prompts to v7 to be handled later * chore(dependencies): updated changesets for modified dependencies --------- Co-authored-by: github-actions[bot] --- ...@graphql-codegen_cli-10650-dependencies.md | 11 ++ ...n_gql-tag-operations-10650-dependencies.md | 5 + ...aphql-modules-preset-10650-dependencies.md | 5 + ...degen_plugin-helpers-10650-dependencies.md | 5 + ..._typed-document-node-10650-dependencies.md | 6 + ...l-codegen_typescript-10650-dependencies.md | 5 + ...cript-document-nodes-10650-dependencies.md | 5 + ...ypescript-operations-10650-dependencies.md | 5 + ...typescript-resolvers-10650-dependencies.md | 5 + ...isitor-plugin-common-10650-dependencies.md | 6 + packages/graphql-codegen-cli/package.json | 16 +-- .../other/visitor-plugin-common/package.json | 4 +- .../typescript/document-nodes/package.json | 2 +- .../gql-tag-operations/package.json | 2 +- .../typescript/operations/package.json | 2 +- .../plugins/typescript/resolvers/package.json | 2 +- .../typed-document-node/package.json | 4 +- .../typescript/typescript/package.json | 4 +- packages/presets/graphql-modules/package.json | 2 +- packages/utils/plugins-helpers/package.json | 2 +- yarn.lock | 132 ++++++++++++++++-- 21 files changed, 196 insertions(+), 34 deletions(-) create mode 100644 .changeset/@graphql-codegen_cli-10650-dependencies.md create mode 100644 .changeset/@graphql-codegen_gql-tag-operations-10650-dependencies.md create mode 100644 .changeset/@graphql-codegen_graphql-modules-preset-10650-dependencies.md create mode 100644 .changeset/@graphql-codegen_plugin-helpers-10650-dependencies.md create mode 100644 .changeset/@graphql-codegen_typed-document-node-10650-dependencies.md create mode 100644 .changeset/@graphql-codegen_typescript-10650-dependencies.md create mode 100644 .changeset/@graphql-codegen_typescript-document-nodes-10650-dependencies.md create mode 100644 .changeset/@graphql-codegen_typescript-operations-10650-dependencies.md create mode 100644 .changeset/@graphql-codegen_typescript-resolvers-10650-dependencies.md create mode 100644 .changeset/@graphql-codegen_visitor-plugin-common-10650-dependencies.md diff --git a/.changeset/@graphql-codegen_cli-10650-dependencies.md b/.changeset/@graphql-codegen_cli-10650-dependencies.md new file mode 100644 index 00000000000..0b9986b071b --- /dev/null +++ b/.changeset/@graphql-codegen_cli-10650-dependencies.md @@ -0,0 +1,11 @@ +--- +"@graphql-codegen/cli": patch +--- +dependencies updates: + - Updated dependency [`chalk@^5.6.0` ↗︎](https://www.npmjs.com/package/chalk/v/5.6.0) (from `^4.1.0`, in `dependencies`) + - Updated dependency [`debounce@^3.0.0` ↗︎](https://www.npmjs.com/package/debounce/v/3.0.0) (from `^2.0.0`, in `dependencies`) + - Updated dependency [`detect-indent@^7.0.0` ↗︎](https://www.npmjs.com/package/detect-indent/v/7.0.0) (from `^6.0.0`, in `dependencies`) + - Updated dependency [`listr2@^10.2.1` ↗︎](https://www.npmjs.com/package/listr2/v/10.2.1) (from `^9.0.0`, in `dependencies`) + - Updated dependency [`log-symbols@^7.0.0` ↗︎](https://www.npmjs.com/package/log-symbols/v/7.0.0) (from `^4.0.0`, in `dependencies`) + - Updated dependency [`ts-log@^3.0.0` ↗︎](https://www.npmjs.com/package/ts-log/v/3.0.0) (from `^2.2.3`, in `dependencies`) + - Updated dependency [`yargs@^18.0.0` ↗︎](https://www.npmjs.com/package/yargs/v/18.0.0) (from `^17.0.0`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_gql-tag-operations-10650-dependencies.md b/.changeset/@graphql-codegen_gql-tag-operations-10650-dependencies.md new file mode 100644 index 00000000000..e3e963598c8 --- /dev/null +++ b/.changeset/@graphql-codegen_gql-tag-operations-10650-dependencies.md @@ -0,0 +1,5 @@ +--- +"@graphql-codegen/gql-tag-operations": patch +--- +dependencies updates: + - Updated dependency [`auto-bind@^5.0.0` ↗︎](https://www.npmjs.com/package/auto-bind/v/5.0.0) (from `~4.0.0`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_graphql-modules-preset-10650-dependencies.md b/.changeset/@graphql-codegen_graphql-modules-preset-10650-dependencies.md new file mode 100644 index 00000000000..25df99c250f --- /dev/null +++ b/.changeset/@graphql-codegen_graphql-modules-preset-10650-dependencies.md @@ -0,0 +1,5 @@ +--- +"@graphql-codegen/graphql-modules-preset": patch +--- +dependencies updates: + - Updated dependency [`change-case-all@^2.1.0` ↗︎](https://www.npmjs.com/package/change-case-all/v/2.1.0) (from `1.0.15`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_plugin-helpers-10650-dependencies.md b/.changeset/@graphql-codegen_plugin-helpers-10650-dependencies.md new file mode 100644 index 00000000000..692a0ed9378 --- /dev/null +++ b/.changeset/@graphql-codegen_plugin-helpers-10650-dependencies.md @@ -0,0 +1,5 @@ +--- +"@graphql-codegen/plugin-helpers": patch +--- +dependencies updates: + - Updated dependency [`change-case-all@^2.1.0` ↗︎](https://www.npmjs.com/package/change-case-all/v/2.1.0) (from `1.0.15`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typed-document-node-10650-dependencies.md b/.changeset/@graphql-codegen_typed-document-node-10650-dependencies.md new file mode 100644 index 00000000000..52788e4aeeb --- /dev/null +++ b/.changeset/@graphql-codegen_typed-document-node-10650-dependencies.md @@ -0,0 +1,6 @@ +--- +"@graphql-codegen/typed-document-node": patch +--- +dependencies updates: + - Updated dependency [`change-case-all@^2.1.0` ↗︎](https://www.npmjs.com/package/change-case-all/v/2.1.0) (from `1.0.15`, in `dependencies`) + - Updated dependency [`auto-bind@^5.0.0` ↗︎](https://www.npmjs.com/package/auto-bind/v/5.0.0) (from `~4.0.0`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typescript-10650-dependencies.md b/.changeset/@graphql-codegen_typescript-10650-dependencies.md new file mode 100644 index 00000000000..e7efcd336f4 --- /dev/null +++ b/.changeset/@graphql-codegen_typescript-10650-dependencies.md @@ -0,0 +1,5 @@ +--- +"@graphql-codegen/typescript": patch +--- +dependencies updates: + - Updated dependency [`auto-bind@^5.0.0` ↗︎](https://www.npmjs.com/package/auto-bind/v/5.0.0) (from `~4.0.0`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typescript-document-nodes-10650-dependencies.md b/.changeset/@graphql-codegen_typescript-document-nodes-10650-dependencies.md new file mode 100644 index 00000000000..72924f13846 --- /dev/null +++ b/.changeset/@graphql-codegen_typescript-document-nodes-10650-dependencies.md @@ -0,0 +1,5 @@ +--- +"@graphql-codegen/typescript-document-nodes": patch +--- +dependencies updates: + - Updated dependency [`auto-bind@^5.0.0` ↗︎](https://www.npmjs.com/package/auto-bind/v/5.0.0) (from `~4.0.0`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typescript-operations-10650-dependencies.md b/.changeset/@graphql-codegen_typescript-operations-10650-dependencies.md new file mode 100644 index 00000000000..b710cf54928 --- /dev/null +++ b/.changeset/@graphql-codegen_typescript-operations-10650-dependencies.md @@ -0,0 +1,5 @@ +--- +"@graphql-codegen/typescript-operations": patch +--- +dependencies updates: + - Updated dependency [`auto-bind@^5.0.0` ↗︎](https://www.npmjs.com/package/auto-bind/v/5.0.0) (from `~4.0.0`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typescript-resolvers-10650-dependencies.md b/.changeset/@graphql-codegen_typescript-resolvers-10650-dependencies.md new file mode 100644 index 00000000000..f779c89b2d9 --- /dev/null +++ b/.changeset/@graphql-codegen_typescript-resolvers-10650-dependencies.md @@ -0,0 +1,5 @@ +--- +"@graphql-codegen/typescript-resolvers": patch +--- +dependencies updates: + - Updated dependency [`auto-bind@^5.0.0` ↗︎](https://www.npmjs.com/package/auto-bind/v/5.0.0) (from `~4.0.0`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_visitor-plugin-common-10650-dependencies.md b/.changeset/@graphql-codegen_visitor-plugin-common-10650-dependencies.md new file mode 100644 index 00000000000..c38bdfe56b8 --- /dev/null +++ b/.changeset/@graphql-codegen_visitor-plugin-common-10650-dependencies.md @@ -0,0 +1,6 @@ +--- +"@graphql-codegen/visitor-plugin-common": patch +--- +dependencies updates: + - Updated dependency [`auto-bind@^5.0.0` ↗︎](https://www.npmjs.com/package/auto-bind/v/5.0.0) (from `~4.0.0`, in `dependencies`) + - Updated dependency [`change-case-all@^2.1.0` ↗︎](https://www.npmjs.com/package/change-case-all/v/2.1.0) (from `1.0.15`, in `dependencies`) diff --git a/packages/graphql-codegen-cli/package.json b/packages/graphql-codegen-cli/package.json index 83b7bdaf053..0cbfe27a1a0 100644 --- a/packages/graphql-codegen-cli/package.json +++ b/packages/graphql-codegen-cli/package.json @@ -91,23 +91,23 @@ "@graphql-tools/utils": "^11.0.0", "@inquirer/prompts": "^7.8.2", "@whatwg-node/fetch": "^0.10.0", - "chalk": "^4.1.0", + "chalk": "^5.6.0", "cosmiconfig": "^9.0.0", - "debounce": "^2.0.0", - "detect-indent": "^6.0.0", + "debounce": "^3.0.0", + "detect-indent": "^7.0.0", "graphql-config": "^5.1.6", "is-glob": "^4.0.1", "jiti": "^2.3.0", "json-to-pretty-yaml": "^1.2.2", - "listr2": "^9.0.0", - "log-symbols": "^4.0.0", + "listr2": "^10.2.1", + "log-symbols": "^7.0.0", "micromatch": "^4.0.5", "shell-quote": "^1.7.3", "string-env-interpolation": "^1.0.1", - "ts-log": "^2.2.3", + "ts-log": "^3.0.0", "tslib": "^2.4.0", "yaml": "^2.3.1", - "yargs": "^17.0.0" + "yargs": "^18.0.0" }, "devDependencies": { "@parcel/watcher": "^2.1.0", @@ -116,7 +116,7 @@ "@types/micromatch": "^4.0.2", "@types/shell-quote": "1.7.5", "bdd-stdin": "0.2.0", - "change-case-all": "1.0.15", + "change-case-all": "2.1.0", "js-yaml": "4.1.1", "make-dir": "5.1.0", "prettier": "3.8.2" diff --git a/packages/plugins/other/visitor-plugin-common/package.json b/packages/plugins/other/visitor-plugin-common/package.json index f2c8e2e8f3a..3f3928b00d7 100644 --- a/packages/plugins/other/visitor-plugin-common/package.json +++ b/packages/plugins/other/visitor-plugin-common/package.json @@ -43,8 +43,8 @@ "@graphql-tools/optimize": "^2.0.0", "@graphql-tools/relay-operation-optimizer": "^7.1.1", "@graphql-tools/utils": "^11.0.0", - "auto-bind": "~4.0.0", - "change-case-all": "1.0.15", + "auto-bind": "^5.0.0", + "change-case-all": "^2.1.0", "dependency-graph": "^1.0.0", "graphql-tag": "^2.11.0", "parse-filepath": "^1.0.2", diff --git a/packages/plugins/typescript/document-nodes/package.json b/packages/plugins/typescript/document-nodes/package.json index 75c06cf5033..6dab78a0867 100644 --- a/packages/plugins/typescript/document-nodes/package.json +++ b/packages/plugins/typescript/document-nodes/package.json @@ -42,7 +42,7 @@ "dependencies": { "@graphql-codegen/plugin-helpers": "^6.3.0", "@graphql-codegen/visitor-plugin-common": "^6.3.0", - "auto-bind": "~4.0.0", + "auto-bind": "^5.0.0", "tslib": "^2.8.0" }, "publishConfig": { diff --git a/packages/plugins/typescript/gql-tag-operations/package.json b/packages/plugins/typescript/gql-tag-operations/package.json index c6b24dc0aa1..c1b549dde47 100644 --- a/packages/plugins/typescript/gql-tag-operations/package.json +++ b/packages/plugins/typescript/gql-tag-operations/package.json @@ -43,7 +43,7 @@ "@graphql-codegen/plugin-helpers": "^6.3.0", "@graphql-codegen/visitor-plugin-common": "^6.3.0", "@graphql-tools/utils": "^11.0.0", - "auto-bind": "~4.0.0", + "auto-bind": "^5.0.0", "tslib": "^2.8.0" }, "publishConfig": { diff --git a/packages/plugins/typescript/operations/package.json b/packages/plugins/typescript/operations/package.json index b8c9abf5480..ef2bbc1bf13 100644 --- a/packages/plugins/typescript/operations/package.json +++ b/packages/plugins/typescript/operations/package.json @@ -49,7 +49,7 @@ "@graphql-codegen/plugin-helpers": "^6.3.0", "@graphql-codegen/schema-ast": "^5.0.1", "@graphql-codegen/visitor-plugin-common": "^6.3.0", - "auto-bind": "~4.0.0", + "auto-bind": "^5.0.0", "tslib": "^2.8.0" }, "devDependencies": { diff --git a/packages/plugins/typescript/resolvers/package.json b/packages/plugins/typescript/resolvers/package.json index 1f074cd5193..3b1c91623a6 100644 --- a/packages/plugins/typescript/resolvers/package.json +++ b/packages/plugins/typescript/resolvers/package.json @@ -50,7 +50,7 @@ "@graphql-codegen/typescript": "^5.0.10", "@graphql-codegen/visitor-plugin-common": "^6.3.0", "@graphql-tools/utils": "^11.0.0", - "auto-bind": "~4.0.0", + "auto-bind": "^5.0.0", "tslib": "^2.8.0" }, "devDependencies": { diff --git a/packages/plugins/typescript/typed-document-node/package.json b/packages/plugins/typescript/typed-document-node/package.json index 0de4bca6e85..72b15d6de47 100644 --- a/packages/plugins/typescript/typed-document-node/package.json +++ b/packages/plugins/typescript/typed-document-node/package.json @@ -42,8 +42,8 @@ "dependencies": { "@graphql-codegen/plugin-helpers": "^6.3.0", "@graphql-codegen/visitor-plugin-common": "^6.3.0", - "auto-bind": "~4.0.0", - "change-case-all": "1.0.15", + "auto-bind": "^5.0.0", + "change-case-all": "^2.1.0", "tslib": "^2.8.0" }, "publishConfig": { diff --git a/packages/plugins/typescript/typescript/package.json b/packages/plugins/typescript/typescript/package.json index 00c343092d4..9e224ee64ff 100644 --- a/packages/plugins/typescript/typescript/package.json +++ b/packages/plugins/typescript/typescript/package.json @@ -43,8 +43,8 @@ "@graphql-codegen/plugin-helpers": "^6.3.0", "@graphql-codegen/schema-ast": "^5.0.2", "@graphql-codegen/visitor-plugin-common": "^6.3.0", - "auto-bind": "~4.0.0", - "tslib": "^2.8.0" + "auto-bind": "^5.0.0", + "tslib": "~2.6.0" }, "publishConfig": { "directory": "dist", diff --git a/packages/presets/graphql-modules/package.json b/packages/presets/graphql-modules/package.json index 6d63e140309..b5c686bdf43 100644 --- a/packages/presets/graphql-modules/package.json +++ b/packages/presets/graphql-modules/package.json @@ -42,7 +42,7 @@ "@graphql-codegen/plugin-helpers": "^6.3.0", "@graphql-codegen/visitor-plugin-common": "^6.3.0", "@graphql-tools/utils": "^11.0.0", - "change-case-all": "1.0.15", + "change-case-all": "^2.1.0", "parse-filepath": "^1.0.2", "tslib": "^2.8.0" }, diff --git a/packages/utils/plugins-helpers/package.json b/packages/utils/plugins-helpers/package.json index 3506e830e64..b6b54b0b94c 100644 --- a/packages/utils/plugins-helpers/package.json +++ b/packages/utils/plugins-helpers/package.json @@ -41,7 +41,7 @@ }, "dependencies": { "@graphql-tools/utils": "^11.0.0", - "change-case-all": "1.0.15", + "change-case-all": "^2.1.0", "common-tags": "1.8.2", "import-from": "4.0.0", "tslib": "^2.8.0" diff --git a/yarn.lock b/yarn.lock index 9c893aa777a..6dd735c7388 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6150,6 +6150,11 @@ at-least-node@^1.0.0: resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== +auto-bind@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-5.0.1.tgz#50d8e63ea5a1dddcb5e5e36451c1a8266ffbb2ae" + integrity sha512-ooviqdwwgfIfNmDwo94wlshcdzfO64XV0Cg6oDsDYBJfITDz1EngD2z7DkbvCWn+XIMsIqW27sEVF6qcpJrRcg== + auto-bind@~4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-4.0.0.tgz#e3589fc6c2da8f7ca43ba9f84fa52a744fc997fb" @@ -6570,7 +6575,7 @@ chalk-template@0.4.0: dependencies: chalk "^4.1.2" -chalk@5.0.1, chalk@^5.0.0, chalk@^5.0.1: +chalk@5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.0.1.tgz#ca57d71e82bb534a296df63bbacc4a1c22b2a4b6" integrity sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w== @@ -6583,6 +6588,11 @@ chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^5.0.0, chalk@^5.0.1, chalk@^5.6.0: + version "5.6.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.6.2.tgz#b1238b6e23ea337af71c7f8a295db5af0c158aea" + integrity sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA== + change-case-all@1.0.14: version "1.0.14" resolved "https://registry.yarnpkg.com/change-case-all/-/change-case-all-1.0.14.tgz#bac04da08ad143278d0ac3dda7eccd39280bfba1" @@ -6615,6 +6625,16 @@ change-case-all@1.0.15: upper-case "^2.0.2" upper-case-first "^2.0.2" +change-case-all@2.1.0, change-case-all@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/change-case-all/-/change-case-all-2.1.0.tgz#c838988531bba9fa9e4db124f2d3f53a9607acc1" + integrity sha512-v6b0WWWkZUMHVuYk82l+WROgkUm4qEN2w5hKRNWtEOYwWqUGoi8C6xH0l1RLF1EoWqDFK6MFclmN3od6ws3/uw== + dependencies: + change-case "^5.2.0" + sponge-case "^2.0.2" + swap-case "^3.0.2" + title-case "^3.0.3" + change-case@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/change-case/-/change-case-4.1.2.tgz#fedfc5f136045e2398c0410ee441f95704641e12" @@ -6633,6 +6653,11 @@ change-case@^4.1.2: snake-case "^3.0.4" tslib "^2.0.3" +change-case@^5.2.0: + version "5.4.4" + resolved "https://registry.yarnpkg.com/change-case/-/change-case-5.4.4.tgz#0d52b507d8fb8f204343432381d1a6d7bff97a02" + integrity sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w== + character-entities-html4@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-2.1.0.tgz#1f1adb940c971a4b22ba39ddca6b618dc6e56b2b" @@ -6766,7 +6791,7 @@ cli-truncate@^2.1.0: slice-ansi "^3.0.0" string-width "^4.2.0" -cli-truncate@^5.0.0: +cli-truncate@^5.0.0, cli-truncate@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-5.2.0.tgz#c8e72aaca8339c773d128c36e0a17c6315b694eb" integrity sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw== @@ -6820,6 +6845,15 @@ cliui@^8.0.1: strip-ansi "^6.0.1" wrap-ansi "^7.0.0" +cliui@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-9.0.1.tgz#6f7890f386f6f1f79953adc1f78dec46fcc2d291" + integrity sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w== + dependencies: + string-width "^7.2.0" + strip-ansi "^7.1.0" + wrap-ansi "^9.0.0" + clsx@2.1.1, clsx@^2.0.0, clsx@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" @@ -7489,10 +7523,10 @@ debounce@^1.2.1: resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5" integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug== -debounce@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/debounce/-/debounce-2.2.0.tgz#f895fa2fbdb579a0f0d3dcf5dde19657e50eaad5" - integrity sha512-Xks6RUDLZFdz8LIdR6q0MTH44k7FikOmnh5xkSjMig6ch45afc8sjTjRQf3P6ax8dMgcQrYO/AR2RGWURrruqw== +debounce@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/debounce/-/debounce-3.0.0.tgz#7633adff3bcd92cdfe13370c2f46e87bdb946a1b" + integrity sha512-64byRbF0/AirwbuHqB3/ZpMG9/nckDa6ZA0yd6UnaQNwbbemCOwvz2sL5sjXLHhZHADyiwLm0M5qMhltUUx+TA== debug@2.6.9: version "2.6.9" @@ -7597,6 +7631,11 @@ detect-indent@^6.0.0: resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6" integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA== +detect-indent@^7.0.0: + version "7.0.2" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-7.0.2.tgz#16c516bf75d4b2f759f68214554996d467c8d648" + integrity sha512-y+8xyqdGLL+6sh0tVeHcfP/QDd8gUgbasolJJpY7NgeQGSZ739bDtSiaiDgtoicy+mtYB81dKLxO9xRhCyIB3A== + detect-libc@^2.0.3, detect-libc@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad" @@ -8539,7 +8578,7 @@ eventemitter2@6.4.7: resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.7.tgz#a7f6c4d7abf28a14c1ef3442f21cb306a054271d" integrity sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg== -eventemitter3@^5.0.1: +eventemitter3@^5.0.1, eventemitter3@^5.0.4: version "5.0.4" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.4.tgz#a86d66170433712dde814707ac52b5271ceb1feb" integrity sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw== @@ -10108,6 +10147,11 @@ is-unicode-supported@^0.1.0: resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== +is-unicode-supported@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz#09f0ab0de6d3744d48d265ebb98f65d11f2a9b3a" + integrity sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ== + is-upper-case@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-upper-case/-/is-upper-case-2.0.2.tgz#f1105ced1fe4de906a5f39553e7d3803fd804649" @@ -10600,6 +10644,17 @@ lint-staged@16.4.0: tinyexec "^1.0.4" yaml "^2.8.2" +listr2@^10.2.1: + version "10.2.1" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-10.2.1.tgz#fb44e1e9e5f8b15ab817296d45149d295c47bee9" + integrity sha512-7I5knELsJKTUjXG+A6BkKAiGkW1i25fNa/xlUl9hFtk15WbE9jndA89xu5FzQKrY5llajE1hfZZFMILXkDHk/Q== + dependencies: + cli-truncate "^5.2.0" + eventemitter3 "^5.0.4" + log-update "^6.1.0" + rfdc "^1.4.1" + wrap-ansi "^10.0.0" + listr2@^3.8.3: version "3.14.0" resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.14.0.tgz#23101cc62e1375fd5836b248276d1d2b51fdbe9e" @@ -10614,7 +10669,7 @@ listr2@^3.8.3: through "^2.3.8" wrap-ansi "^7.0.0" -listr2@^9.0.0, listr2@^9.0.5: +listr2@^9.0.5: version "9.0.5" resolved "https://registry.yarnpkg.com/listr2/-/listr2-9.0.5.tgz#92df7c4416a6da630eb9ef46da469b70de97b316" integrity sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g== @@ -10745,6 +10800,14 @@ log-symbols@^4.0.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" +log-symbols@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-7.0.1.tgz#f52e68037d96f589fc572ff2193dc424d48c195b" + integrity sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg== + dependencies: + is-unicode-supported "^2.0.0" + yoctocolors "^2.1.1" + log-update@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1" @@ -14047,6 +14110,11 @@ sponge-case@^1.0.1: dependencies: tslib "^2.0.3" +sponge-case@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/sponge-case/-/sponge-case-2.0.3.tgz#9e004d04332c307e4895b79eeb6c1f3da86eb203" + integrity sha512-i4h9ZGRfxV6Xw3mpZSFOfbXjf0cQcYmssGWutgNIfFZ2VM+YIWfD71N/kjjwK6X/AAHzBr+rciEcn/L34S8TGw== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -14177,7 +14245,7 @@ string-width@^6.0.0: emoji-regex "^10.2.1" strip-ansi "^7.0.1" -string-width@^7.0.0: +string-width@^7.0.0, string-width@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.2.0.tgz#b5bb8e2165ce275d4d43476dd2700ad9091db6dc" integrity sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ== @@ -14440,6 +14508,11 @@ swap-case@^2.0.2: dependencies: tslib "^2.0.3" +swap-case@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/swap-case/-/swap-case-3.0.3.tgz#363883b0e8a2837c24d2e0eccb6bdff92e32d711" + integrity sha512-6p4op8wE9CQv7uDFzulI6YXUw4lD9n4oQierdbFThEKVWVQcbQcUjdP27W8XE7V4QnWmnq9jueSHceyyQnqQVA== + swr@^2.0.0: version "2.4.1" resolved "https://registry.yarnpkg.com/swr/-/swr-2.4.1.tgz#c9e48abff6bf4b04846342e2f1f6be108a078cf6" @@ -14713,10 +14786,10 @@ ts-invariant@^0.10.3: dependencies: tslib "^2.1.0" -ts-log@^2.2.3: - version "2.2.7" - resolved "https://registry.yarnpkg.com/ts-log/-/ts-log-2.2.7.tgz#4f4512144898b77c9984e91587076fcb8518688e" - integrity sha512-320x5Ggei84AxzlXp91QkIGSw5wgaLT6GeAH0KsqDmRZdVWW2OiSeVvElVoatk3f7nicwXlElXsoFkARiGE2yg== +ts-log@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ts-log/-/ts-log-3.0.0.tgz#74a84ca54ebeea02d6a6d052d21a8c47889c119a" + integrity sha512-dOh2B+XwtPsIt+bOy0krUiGGO9fbqUCrR4nkNNir/EObVmEJYd4q6KkfF2Ni8/QG1Lji3JwX8TrTa7LHftPWsA== ts-node@10.9.2, ts-node@^10.9.1: version "10.9.2" @@ -15794,6 +15867,15 @@ wrangler@4.81.1: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-10.0.0.tgz#b83ddcc14dbc5596f1b07e153bf6f863c1acbb57" + integrity sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ== + dependencies: + ansi-styles "^6.2.3" + string-width "^8.2.0" + strip-ansi "^7.1.2" + wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" @@ -15896,6 +15978,11 @@ yargs-parser@^21.1.1: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== +yargs-parser@^22.0.0: + version "22.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-22.0.0.tgz#87b82094051b0567717346ecd00fd14804b357c8" + integrity sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw== + yargs@^15.3.1: version "15.4.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" @@ -15913,7 +16000,7 @@ yargs@^15.3.1: y18n "^4.0.0" yargs-parser "^18.1.2" -yargs@^17.0.0, yargs@^17.1.1, yargs@^17.6.2: +yargs@^17.1.1, yargs@^17.6.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== @@ -15926,6 +16013,18 @@ yargs@^17.0.0, yargs@^17.1.1, yargs@^17.6.2: y18n "^5.0.5" yargs-parser "^21.1.1" +yargs@^18.0.0: + version "18.0.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-18.0.0.tgz#6c84259806273a746b09f579087b68a3c2d25bd1" + integrity sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg== + dependencies: + cliui "^9.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + string-width "^7.2.0" + y18n "^5.0.5" + yargs-parser "^22.0.0" + yauzl@^2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" @@ -15954,6 +16053,11 @@ yoctocolors-cjs@^2.1.3: resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz#7e4964ea8ec422b7a40ac917d3a344cfd2304baa" integrity sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw== +yoctocolors@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yoctocolors/-/yoctocolors-2.1.2.tgz#d795f54d173494e7d8db93150cec0ed7f678c83a" + integrity sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug== + youch-core@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/youch-core/-/youch-core-0.3.3.tgz#c5d3d85aeea0d8bc7b36e9764ed3f14b7ceddc7d" From 0e17bca1c160c8126818e84618ffaef86dfc75f3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 22 Mar 2026 08:05:44 +0000 Subject: [PATCH 58/69] chore(dependencies): updated changesets for modified dependencies --- .changeset/@graphql-codegen_cli-10496-dependencies.md | 11 +++++++++++ ...l-codegen_gql-tag-operations-10496-dependencies.md | 5 +++++ ...degen_graphql-modules-preset-10496-dependencies.md | 5 +++++ ...aphql-codegen_plugin-helpers-10496-dependencies.md | 5 +++++ ...-codegen_typed-document-node-10496-dependencies.md | 6 ++++++ .../@graphql-codegen_typescript-10496-dependencies.md | 5 +++++ ...en_typescript-document-nodes-10496-dependencies.md | 5 +++++ ...odegen_typescript-operations-10496-dependencies.md | 1 + ...codegen_typescript-resolvers-10496-dependencies.md | 5 +++++ ...odegen_visitor-plugin-common-10496-dependencies.md | 6 ++++++ 10 files changed, 54 insertions(+) create mode 100644 .changeset/@graphql-codegen_cli-10496-dependencies.md create mode 100644 .changeset/@graphql-codegen_gql-tag-operations-10496-dependencies.md create mode 100644 .changeset/@graphql-codegen_graphql-modules-preset-10496-dependencies.md create mode 100644 .changeset/@graphql-codegen_plugin-helpers-10496-dependencies.md create mode 100644 .changeset/@graphql-codegen_typed-document-node-10496-dependencies.md create mode 100644 .changeset/@graphql-codegen_typescript-10496-dependencies.md create mode 100644 .changeset/@graphql-codegen_typescript-document-nodes-10496-dependencies.md create mode 100644 .changeset/@graphql-codegen_typescript-resolvers-10496-dependencies.md create mode 100644 .changeset/@graphql-codegen_visitor-plugin-common-10496-dependencies.md diff --git a/.changeset/@graphql-codegen_cli-10496-dependencies.md b/.changeset/@graphql-codegen_cli-10496-dependencies.md new file mode 100644 index 00000000000..0b9986b071b --- /dev/null +++ b/.changeset/@graphql-codegen_cli-10496-dependencies.md @@ -0,0 +1,11 @@ +--- +"@graphql-codegen/cli": patch +--- +dependencies updates: + - Updated dependency [`chalk@^5.6.0` ↗︎](https://www.npmjs.com/package/chalk/v/5.6.0) (from `^4.1.0`, in `dependencies`) + - Updated dependency [`debounce@^3.0.0` ↗︎](https://www.npmjs.com/package/debounce/v/3.0.0) (from `^2.0.0`, in `dependencies`) + - Updated dependency [`detect-indent@^7.0.0` ↗︎](https://www.npmjs.com/package/detect-indent/v/7.0.0) (from `^6.0.0`, in `dependencies`) + - Updated dependency [`listr2@^10.2.1` ↗︎](https://www.npmjs.com/package/listr2/v/10.2.1) (from `^9.0.0`, in `dependencies`) + - Updated dependency [`log-symbols@^7.0.0` ↗︎](https://www.npmjs.com/package/log-symbols/v/7.0.0) (from `^4.0.0`, in `dependencies`) + - Updated dependency [`ts-log@^3.0.0` ↗︎](https://www.npmjs.com/package/ts-log/v/3.0.0) (from `^2.2.3`, in `dependencies`) + - Updated dependency [`yargs@^18.0.0` ↗︎](https://www.npmjs.com/package/yargs/v/18.0.0) (from `^17.0.0`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_gql-tag-operations-10496-dependencies.md b/.changeset/@graphql-codegen_gql-tag-operations-10496-dependencies.md new file mode 100644 index 00000000000..e3e963598c8 --- /dev/null +++ b/.changeset/@graphql-codegen_gql-tag-operations-10496-dependencies.md @@ -0,0 +1,5 @@ +--- +"@graphql-codegen/gql-tag-operations": patch +--- +dependencies updates: + - Updated dependency [`auto-bind@^5.0.0` ↗︎](https://www.npmjs.com/package/auto-bind/v/5.0.0) (from `~4.0.0`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_graphql-modules-preset-10496-dependencies.md b/.changeset/@graphql-codegen_graphql-modules-preset-10496-dependencies.md new file mode 100644 index 00000000000..25df99c250f --- /dev/null +++ b/.changeset/@graphql-codegen_graphql-modules-preset-10496-dependencies.md @@ -0,0 +1,5 @@ +--- +"@graphql-codegen/graphql-modules-preset": patch +--- +dependencies updates: + - Updated dependency [`change-case-all@^2.1.0` ↗︎](https://www.npmjs.com/package/change-case-all/v/2.1.0) (from `1.0.15`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_plugin-helpers-10496-dependencies.md b/.changeset/@graphql-codegen_plugin-helpers-10496-dependencies.md new file mode 100644 index 00000000000..692a0ed9378 --- /dev/null +++ b/.changeset/@graphql-codegen_plugin-helpers-10496-dependencies.md @@ -0,0 +1,5 @@ +--- +"@graphql-codegen/plugin-helpers": patch +--- +dependencies updates: + - Updated dependency [`change-case-all@^2.1.0` ↗︎](https://www.npmjs.com/package/change-case-all/v/2.1.0) (from `1.0.15`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typed-document-node-10496-dependencies.md b/.changeset/@graphql-codegen_typed-document-node-10496-dependencies.md new file mode 100644 index 00000000000..52788e4aeeb --- /dev/null +++ b/.changeset/@graphql-codegen_typed-document-node-10496-dependencies.md @@ -0,0 +1,6 @@ +--- +"@graphql-codegen/typed-document-node": patch +--- +dependencies updates: + - Updated dependency [`change-case-all@^2.1.0` ↗︎](https://www.npmjs.com/package/change-case-all/v/2.1.0) (from `1.0.15`, in `dependencies`) + - Updated dependency [`auto-bind@^5.0.0` ↗︎](https://www.npmjs.com/package/auto-bind/v/5.0.0) (from `~4.0.0`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typescript-10496-dependencies.md b/.changeset/@graphql-codegen_typescript-10496-dependencies.md new file mode 100644 index 00000000000..e7efcd336f4 --- /dev/null +++ b/.changeset/@graphql-codegen_typescript-10496-dependencies.md @@ -0,0 +1,5 @@ +--- +"@graphql-codegen/typescript": patch +--- +dependencies updates: + - Updated dependency [`auto-bind@^5.0.0` ↗︎](https://www.npmjs.com/package/auto-bind/v/5.0.0) (from `~4.0.0`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typescript-document-nodes-10496-dependencies.md b/.changeset/@graphql-codegen_typescript-document-nodes-10496-dependencies.md new file mode 100644 index 00000000000..72924f13846 --- /dev/null +++ b/.changeset/@graphql-codegen_typescript-document-nodes-10496-dependencies.md @@ -0,0 +1,5 @@ +--- +"@graphql-codegen/typescript-document-nodes": patch +--- +dependencies updates: + - Updated dependency [`auto-bind@^5.0.0` ↗︎](https://www.npmjs.com/package/auto-bind/v/5.0.0) (from `~4.0.0`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md b/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md index 28e7577253f..6ed72635910 100644 --- a/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md +++ b/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md @@ -2,5 +2,6 @@ "@graphql-codegen/typescript-operations": patch --- dependencies updates: + - Updated dependency [`auto-bind@^5.0.0` ↗︎](https://www.npmjs.com/package/auto-bind/v/5.0.0) (from `~4.0.0`, in `dependencies`) - Added dependency [`@graphql-codegen/schema-ast@^5.0.1` ↗︎](https://www.npmjs.com/package/@graphql-codegen/schema-ast/v/5.0.1) (to `dependencies`) - Removed dependency [`@graphql-codegen/typescript@^5.0.9` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.9) (from `dependencies`) diff --git a/.changeset/@graphql-codegen_typescript-resolvers-10496-dependencies.md b/.changeset/@graphql-codegen_typescript-resolvers-10496-dependencies.md new file mode 100644 index 00000000000..f779c89b2d9 --- /dev/null +++ b/.changeset/@graphql-codegen_typescript-resolvers-10496-dependencies.md @@ -0,0 +1,5 @@ +--- +"@graphql-codegen/typescript-resolvers": patch +--- +dependencies updates: + - Updated dependency [`auto-bind@^5.0.0` ↗︎](https://www.npmjs.com/package/auto-bind/v/5.0.0) (from `~4.0.0`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_visitor-plugin-common-10496-dependencies.md b/.changeset/@graphql-codegen_visitor-plugin-common-10496-dependencies.md new file mode 100644 index 00000000000..c38bdfe56b8 --- /dev/null +++ b/.changeset/@graphql-codegen_visitor-plugin-common-10496-dependencies.md @@ -0,0 +1,6 @@ +--- +"@graphql-codegen/visitor-plugin-common": patch +--- +dependencies updates: + - Updated dependency [`auto-bind@^5.0.0` ↗︎](https://www.npmjs.com/package/auto-bind/v/5.0.0) (from `~4.0.0`, in `dependencies`) + - Updated dependency [`change-case-all@^2.1.0` ↗︎](https://www.npmjs.com/package/change-case-all/v/2.1.0) (from `1.0.15`, in `dependencies`) From 90c8c2a66e3cb877bd3669371f8cba09523c290d Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Mon, 23 Mar 2026 00:30:11 +1100 Subject: [PATCH 59/69] Bump inquirer and improve related tests (#10651) * Bump inquirer * chore(dependencies): updated changesets for modified dependencies * WIP fix test * Swap bddstd for inquirer/testing * Fix spec tsconfig to fix ts import issue in tests ESM * Fix unnecessary Promise * Update init tests to use @inquirer/testing --------- Co-authored-by: github-actions[bot] --- ...@graphql-codegen_cli-10651-dependencies.md | 5 + packages/graphql-codegen-cli/package.json | 4 +- .../graphql-codegen-cli/src/init/index.ts | 2 +- .../graphql-codegen-cli/src/init/targets.ts | 2 +- .../tests/__snapshots__/init.spec.ts.snap | 134 --- .../graphql-codegen-cli/tests/init.spec.ts | 859 +++++++++++++----- tsconfig.spec.json | 2 + yarn.lock | 306 ++++--- 8 files changed, 803 insertions(+), 511 deletions(-) create mode 100644 .changeset/@graphql-codegen_cli-10651-dependencies.md delete mode 100644 packages/graphql-codegen-cli/tests/__snapshots__/init.spec.ts.snap diff --git a/.changeset/@graphql-codegen_cli-10651-dependencies.md b/.changeset/@graphql-codegen_cli-10651-dependencies.md new file mode 100644 index 00000000000..635d380e7bc --- /dev/null +++ b/.changeset/@graphql-codegen_cli-10651-dependencies.md @@ -0,0 +1,5 @@ +--- +"@graphql-codegen/cli": patch +--- +dependencies updates: + - Updated dependency [`@inquirer/prompts@^8.3.2` ↗︎](https://www.npmjs.com/package/@inquirer/prompts/v/8.3.2) (from `^7.8.2`, in `dependencies`) diff --git a/packages/graphql-codegen-cli/package.json b/packages/graphql-codegen-cli/package.json index 0cbfe27a1a0..c732d160bef 100644 --- a/packages/graphql-codegen-cli/package.json +++ b/packages/graphql-codegen-cli/package.json @@ -89,7 +89,7 @@ "@graphql-tools/merge": "^9.0.6", "@graphql-tools/url-loader": "^9.0.6", "@graphql-tools/utils": "^11.0.0", - "@inquirer/prompts": "^7.8.2", + "@inquirer/prompts": "^8.3.2", "@whatwg-node/fetch": "^0.10.0", "chalk": "^5.6.0", "cosmiconfig": "^9.0.0", @@ -110,12 +110,12 @@ "yargs": "^18.0.0" }, "devDependencies": { + "@inquirer/testing": "3.3.2", "@parcel/watcher": "^2.1.0", "@types/is-glob": "4.0.4", "@types/js-yaml": "4.0.9", "@types/micromatch": "^4.0.2", "@types/shell-quote": "1.7.5", - "bdd-stdin": "0.2.0", "change-case-all": "2.1.0", "js-yaml": "4.1.1", "make-dir": "5.1.0", diff --git a/packages/graphql-codegen-cli/src/init/index.ts b/packages/graphql-codegen-cli/src/init/index.ts index 53ce1b85a1a..6abcfa28b3b 100644 --- a/packages/graphql-codegen-cli/src/init/index.ts +++ b/packages/graphql-codegen-cli/src/init/index.ts @@ -15,7 +15,7 @@ export async function init() { Answer few questions and we will setup everything for you. `); - const possibleTargets = await guessTargets(); + const possibleTargets = guessTargets(); const answers = await getAnswers(possibleTargets); // define config diff --git a/packages/graphql-codegen-cli/src/init/targets.ts b/packages/graphql-codegen-cli/src/init/targets.ts index 1c536dd895f..8d4f3e87ea7 100644 --- a/packages/graphql-codegen-cli/src/init/targets.ts +++ b/packages/graphql-codegen-cli/src/init/targets.ts @@ -2,7 +2,7 @@ import { readFileSync } from 'fs'; import { resolve } from 'path'; import { Tags } from './types.js'; -export async function guessTargets(): Promise> { +export function guessTargets(): Record { const pkg = JSON.parse(readFileSync(resolve(process.cwd(), 'package.json'), 'utf8')); const dependencies = Object.keys({ ...pkg.dependencies, diff --git a/packages/graphql-codegen-cli/tests/__snapshots__/init.spec.ts.snap b/packages/graphql-codegen-cli/tests/__snapshots__/init.spec.ts.snap deleted file mode 100644 index 0782ac6737f..00000000000 --- a/packages/graphql-codegen-cli/tests/__snapshots__/init.spec.ts.snap +++ /dev/null @@ -1,134 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`init > custom setup 1`] = ` -" -import type { CodegenConfig } from '@graphql-codegen/cli'; - -const config: CodegenConfig = { - overwrite: true, - schema: "http://localhost:4000", - documents: "graphql/*.ts", - generates: { - "src/gql/": { - preset: "client", - plugins: [] - }, - "./graphql.schema.json": { - plugins: ["introspection"] - } - } -}; - -export default config; -" -`; - -exports[`init > plugins suggestions for client-side setup > should use angular related plugins when @angular/core is found 1`] = ` -" -import type { CodegenConfig } from '@graphql-codegen/cli'; - -const config: CodegenConfig = { - overwrite: true, - schema: "http://localhost:4000", - documents: "src/**/*.ts", - generates: { - "src/generated/graphql.ts": { - plugins: ["typescript-apollo-angular"] - } - } -}; - -export default config; -" -`; - -exports[`init > plugins suggestions for client-side setup > should use react related plugins when react is found 1`] = ` -" -import type { CodegenConfig } from '@graphql-codegen/cli'; - -const config: CodegenConfig = { - overwrite: true, - schema: "http://localhost:4000", - documents: "src/**/*.tsx", - generates: { - "src/gql/": { - preset: "client", - plugins: [] - } - } -}; - -export default config; -" -`; - -exports[`init > plugins suggestions for client-side setup > should use stencil related plugins when @stencil/core is found 1`] = ` -" -import type { CodegenConfig } from '@graphql-codegen/cli'; - -const config: CodegenConfig = { - overwrite: true, - schema: "http://localhost:4000", - documents: "src/**/*.graphql", - generates: { - "src/generated/graphql.tsx": { - plugins: ["typescript", "typescript-operations", "typescript-stencil-apollo"] - } - } -}; - -export default config; -" -`; - -exports[`init > plugins suggestions non client-side setup > should use typescript related plugins when typescript is found (node) 1`] = ` -" -import type { CodegenConfig } from '@graphql-codegen/cli'; - -const config: CodegenConfig = { - overwrite: true, - schema: "http://localhost:4000", - generates: { - "src/generated/graphql.ts": { - plugins: ["typescript", "typescript-resolvers"] - } - } -}; - -export default config; -" -`; - -exports[`init > should have few default values for Angular 1`] = ` -" -import type { CodegenConfig } from '@graphql-codegen/cli'; - -const config: CodegenConfig = { - overwrite: true, - schema: "http://localhost:4000", - documents: "src/**/*.tsx", - generates: { - "src/gql/": { - preset: "client", - plugins: [] - } - } -}; - -export default config; -" -`; - -exports[`init > should have few default values for React 1`] = ` -"overwrite: true -schema: "./schema.ts" -documents: "graphql/**/*.graphql" -generates: - graphql/index.ts: - preset: "client" - plugins: [] - ./graphql.schema.json: - plugins: - - "introspection" -" -`; diff --git a/packages/graphql-codegen-cli/tests/init.spec.ts b/packages/graphql-codegen-cli/tests/init.spec.ts index 738bae293f1..31850c57789 100644 --- a/packages/graphql-codegen-cli/tests/init.spec.ts +++ b/packages/graphql-codegen-cli/tests/init.spec.ts @@ -1,6 +1,6 @@ import { resolve } from 'path'; -import bddStdin from 'bdd-stdin'; import { fs, vol } from 'memfs'; +import { screen } from '@inquirer/testing/vitest'; import { bold } from '../src/init/helpers.js'; import { init } from '../src/init/index.js'; import { getApplicationTypeChoices, getPluginChoices } from '../src/init/questions.js'; @@ -12,11 +12,7 @@ vi.mock('../src/utils/get-latest-version.ts', () => { }); vi.mock('fs', () => require('./__mocks__/fs.cjs')); -const { version } = require('../package.json'); - -const SELECT = ' '; // checkbox -const ENTER = '\n'; -// const DOWN = bddStdin.keys.down; +const version = '888.888.888'; // Mocked CLI version, not important const packageJson = { withAngular: JSON.stringify({ @@ -87,45 +83,45 @@ describe('init', () => { }); describe('guessTargets()', () => { - it('should guess angular projects', async () => { + it('should guess angular projects', () => { vol.fromJSON({ ['package.json']: packageJson.withAngular }, process.cwd()); - const targets = await guessTargets(); + const targets = guessTargets(); expect(targets.Angular).toEqual(true); }); - it('should guess typescript projects', async () => { + it('should guess typescript projects', () => { vol.fromJSON({ ['package.json']: packageJson.withTypescript }, process.cwd()); - const targets = await guessTargets(); + const targets = guessTargets(); expect(targets.TypeScript).toEqual(true); }); - it('should guess react projects', async () => { + it('should guess react projects', () => { vol.fromJSON({ ['package.json']: packageJson.withReact }, process.cwd()); - const targets = await guessTargets(); + const targets = guessTargets(); expect(targets.React).toEqual(true); }); - it('should guess stencil projects', async () => { + it('should guess stencil projects', () => { vol.fromJSON({ ['package.json']: packageJson.withStencil }, process.cwd()); - const targets = await guessTargets(); + const targets = guessTargets(); expect(targets.Stencil).toEqual(true); }); - it('should guess flow projects', async () => { + it('should guess flow projects', () => { vol.fromJSON({ ['package.json']: packageJson.withFlow }, process.cwd()); - const targets = await guessTargets(); + const targets = guessTargets(); expect(targets.Flow).toEqual(true); }); - it('should guess vue projects', async () => { + it('should guess vue projects', () => { vol.fromJSON({ ['package.json']: packageJson.withVue }, process.cwd()); - const targets = await guessTargets(); + const targets = guessTargets(); expect(targets.Vue).toEqual(true); }); - it('should guess graphql-request projects', async () => { + it('should guess graphql-request projects', () => { vol.fromJSON({ ['package.json']: packageJson.withGraphqlRequest }, process.cwd()); - const targets = await guessTargets(); + const targets = guessTargets(); expect(targets.graphqlRequest).toEqual(true); }); }); @@ -134,100 +130,398 @@ describe('init', () => { it('should use angular related plugins when @angular/core is found', async () => { vol.fromJSON({ ['package.json']: packageJson.withAngular }, process.cwd()); const writeFileSpy = vi.spyOn(fs, 'writeFileSync'); - // silent - vi.spyOn(console, 'log').mockImplementation(() => {}); - - useInputs({ - onTarget: [ENTER], // confirm target - onSchema: [ENTER], // use default - onDocuments: [ENTER], - onPlugins: [ENTER], // use selected packages - onOutput: [ENTER], // use default output path - onIntrospection: ['n', ENTER], // no introspection, - onConfig: [ENTER], // use default config path - onScript: ['graphql', ENTER], // use custom npm script - }); - - await init(); + const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); // silent + + const result = init(); + + // targets + expect(screen.getScreen()).toMatchInlineSnapshot(` + "? What type of application are you building? + Backend - API or server + ❯ Application built with Angular + Application built with React + Application built with Stencil + Application built with Vue + Application using graphql-request + Application built with other framework or vanilla JS + + ↑↓ navigate • ⏎ select" + `); + screen.keypress('enter'); + await screen.next(); + + // schema + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? Where is your schema?: (path or url) (http://localhost:4000)"`, + ); + screen.keypress('enter'); + await screen.next(); + + // documents + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? Where are your operations and fragments?: (src/**/*.ts)"`, + ); + screen.keypress('enter'); + await screen.next(); + + // plugins + expect(screen.getScreen()).toMatchInlineSnapshot(` + "? Pick plugins: + ❯◯ Introspection Fragment Matcher (for Apollo Client) + ◉ TypeScript Apollo Angular (typed GQL services) + + ↑↓ navigate • space select • a all • i invert • ⏎ submit" + `); + screen.keypress('enter'); + await screen.next(); + + // output + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? Where to write the output: (src/generated/graphql.ts)"`, + ); + screen.keypress('enter'); + await screen.next(); + + // introspection + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? Do you want to generate an introspection file? (y/N)"`, + ); + screen.keypress('n'); + screen.keypress('enter'); + await screen.next(); + + // config + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? How to name the config file? (codegen.ts)"`, + ); + screen.keypress('enter'); + await screen.next(); + + // script + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? What script in package.json should run the codegen? (codegen)"`, + ); + screen.keypress('enter'); + await result; + + expect(await screen.getFullOutput()).toMatchInlineSnapshot( + ` + "✔ What type of application are you building? Application built with Angular + ✔ Where is your schema?: (path or url) http://localhost:4000 + ✔ Where are your operations and fragments?: src/**/*.ts + ✔ Pick plugins: TypeScript Apollo Angular (typed GQL services) + ✔ Where to write the output: src/generated/graphql.ts + ✔ Do you want to generate an introspection file? No + ✔ How to name the config file? codegen.ts + ✔ What script in package.json should run the codegen? codegen" + `, + ); + + expect(logSpy.mock.calls[2][0]).toContain(`Config file generated at ${bold('codegen.ts')}`); expect(writeFileSpy).toHaveBeenCalledTimes(2); const pkg = JSON.parse(writeFileSpy.mock.calls[1][1] as string); + expect(pkg).toMatchInlineSnapshot(` + { + "dependencies": { + "@angular/core": "x.x.x", + }, + "devDependencies": { + "@graphql-codegen/cli": "1.0.0", + "@graphql-codegen/typescript-apollo-angular": "1.0.0", + }, + "scripts": { + "codegen": "graphql-codegen --config codegen.ts", + }, + "version": "888.888.888", + } + `); + + const configFile = writeFileSpy.mock.calls[0][0] as string; const config = writeFileSpy.mock.calls[0][1] as string; - - expect(config).toMatchSnapshot(); - - // expected plugins - expect(pkg.devDependencies).toEqual({ - '@graphql-codegen/cli': '1.0.0', - '@graphql-codegen/typescript-apollo-angular': '1.0.0', - }); + expect(config).toMatchInlineSnapshot(` + " + import type { CodegenConfig } from '@graphql-codegen/cli'; + + const config: CodegenConfig = { + overwrite: true, + schema: "http://localhost:4000", + documents: "src/**/*.ts", + generates: { + "src/generated/graphql.ts": { + plugins: ["typescript-apollo-angular"] + } + } + }; + + export default config; + " + `); + expect(configFile).toEqual(resolve(process.cwd(), 'codegen.ts')); }); it('should use react related plugins when react is found', async () => { vol.fromJSON({ ['package.json']: packageJson.withReact }, process.cwd()); const writeFileSpy = vi.spyOn(fs, 'writeFileSync'); - // silent - vi.spyOn(console, 'log').mockImplementation(() => {}); - - useInputs({ - onTarget: [ENTER], // confirm react target - onSchema: [ENTER], // use default - onDocuments: [ENTER], - onOutput: [ENTER], // use default output path - onIntrospection: ['n', ENTER], // no introspection, - onConfig: [ENTER], // use default config path - onScript: ['graphql', ENTER], // use custom npm script - }); - - await init(); + const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); + + const result = init(); + + // targets + expect(screen.getScreen()).toMatchInlineSnapshot(` + "? What type of application are you building? + Backend - API or server + Application built with Angular + ❯ Application built with React + Application built with Stencil + Application built with Vue + Application using graphql-request + Application built with other framework or vanilla JS + + ↑↓ navigate • ⏎ select" + `); + screen.keypress('enter'); + await screen.next(); + + // schema + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? Where is your schema?: (path or url) (http://localhost:4000)"`, + ); + screen.keypress('enter'); + await screen.next(); + + // documents + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? Where are your operations and fragments?: (src/**/*.tsx)"`, + ); + screen.keypress('enter'); + await screen.next(); + + // output + expect(screen.getScreen()).toMatchInlineSnapshot(`"? Where to write the output: (src/gql/)"`); + screen.keypress('enter'); + await screen.next(); + + // introspection + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? Do you want to generate an introspection file? (y/N)"`, + ); + screen.keypress('enter'); + await screen.next(); + + // config + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? How to name the config file? (codegen.ts)"`, + ); + screen.keypress('enter'); + await screen.next(); + + // script + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? What script in package.json should run the codegen? (codegen)"`, + ); + screen.keypress('enter'); + await result; + + expect(await screen.getFullOutput()).toMatchInlineSnapshot( + ` + "✔ What type of application are you building? Application built with React + ✔ Where is your schema?: (path or url) http://localhost:4000 + ✔ Where are your operations and fragments?: src/**/*.tsx + ✔ Where to write the output: src/gql/ + ✔ Do you want to generate an introspection file? No + ✔ How to name the config file? codegen.ts + ✔ What script in package.json should run the codegen? codegen" + `, + ); + + expect(logSpy.mock.calls[2][0]).toContain(`Config file generated at codegen.ts`); expect(writeFileSpy).toHaveBeenCalledTimes(2); const pkg = JSON.parse(writeFileSpy.mock.calls[1][1] as string); + expect(pkg).toMatchInlineSnapshot(` + { + "dependencies": { + "react": "x.x.x", + }, + "devDependencies": { + "@graphql-codegen/cli": "1.0.0", + "@graphql-codegen/client-preset": "1.0.0", + }, + "scripts": { + "codegen": "graphql-codegen --config codegen.ts", + }, + "version": "888.888.888", + } + `); + + const configFile = writeFileSpy.mock.calls[0][0] as string; const config = writeFileSpy.mock.calls[0][1] as string; - - expect(config).toMatchSnapshot(); - - // expected plugins - expect(pkg.devDependencies).toHaveProperty('@graphql-codegen/cli'); - expect(pkg.devDependencies).toHaveProperty('@graphql-codegen/client-preset'); - // should not have other plugins - expect(Object.keys(pkg.devDependencies)).toHaveLength(2); + expect(configFile).toEqual(resolve(process.cwd(), 'codegen.ts')); + expect(config).toMatchInlineSnapshot(` + " + import type { CodegenConfig } from '@graphql-codegen/cli'; + + const config: CodegenConfig = { + overwrite: true, + schema: "http://localhost:4000", + documents: "src/**/*.tsx", + generates: { + "src/gql/": { + preset: "client", + plugins: [] + } + } + }; + + export default config; + " + `); }); it('should use stencil related plugins when @stencil/core is found', async () => { vol.fromJSON({ ['package.json']: packageJson.withStencil }, process.cwd()); const writeFileSpy = vi.spyOn(fs, 'writeFileSync'); - // silent - vi.spyOn(console, 'log').mockImplementation(() => {}); - - useInputs({ - onTarget: [ENTER], // confirm stencil target - onSchema: [ENTER], // use default - onDocuments: [ENTER], - onPlugins: [ENTER], // use selected packages - onOutput: [ENTER], // use default output path - onIntrospection: ['n', ENTER], // no introspection, - onConfig: [ENTER], // use default config path - onScript: ['graphql', ENTER], // use custom npm script - }); - - await init(); + const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); // silent + + const result = init(); + + // targets + expect(screen.getScreen()).toMatchInlineSnapshot(` + "? What type of application are you building? + Backend - API or server + Application built with Angular + Application built with React + ❯ Application built with Stencil + Application built with Vue + Application using graphql-request + Application built with other framework or vanilla JS + + ↑↓ navigate • ⏎ select" + `); + screen.keypress('enter'); + await screen.next(); + + // schema + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? Where is your schema?: (path or url) (http://localhost:4000)"`, + ); + screen.keypress('enter'); + await screen.next(); + + // documents + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? Where are your operations and fragments?: (src/**/*.graphql)"`, + ); + screen.keypress('enter'); + await screen.next(); + + // plugins + expect(screen.getScreen()).toMatchInlineSnapshot( + ` + "? Pick plugins: + ❯◉ TypeScript (required by other typescript plugins) + ◉ TypeScript Operations (operations and fragments) + ◉ TypeScript Stencil Apollo (typed components) + ◯ TypeScript GraphQL files modules (declarations for .graphql files) + ◯ TypeScript GraphQL document nodes (embedded GraphQL document) + ◯ Introspection Fragment Matcher (for Apollo Client) + ◯ Urql Introspection (for Urql Client) + + ↑↓ navigate • space select • a all • i invert • ⏎ submit" + `, + ); + screen.keypress('enter'); + await screen.next(); + + // output + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? Where to write the output: (src/generated/graphql.tsx)"`, + ); + screen.keypress('enter'); + await screen.next(); + + // introspection + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? Do you want to generate an introspection file? (y/N)"`, + ); + screen.keypress('n'); + screen.keypress('enter'); + await screen.next(); + + // config + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? How to name the config file? (codegen.ts)"`, + ); + screen.keypress('enter'); + await screen.next(); + + // script + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? What script in package.json should run the codegen? (codegen)"`, + ); + screen.keypress('enter'); + await result; + + expect(await screen.getFullOutput()).toMatchInlineSnapshot( + ` + "✔ What type of application are you building? Application built with Stencil + ✔ Where is your schema?: (path or url) http://localhost:4000 + ✔ Where are your operations and fragments?: src/**/*.graphql + ✔ Pick plugins: TypeScript (required by other typescript plugins), TypeScript Operations (operations and fragments), TypeScript Stencil Apollo (typed components) + ✔ Where to write the output: src/generated/graphql.tsx + ✔ Do you want to generate an introspection file? No + ✔ How to name the config file? codegen.ts + ✔ What script in package.json should run the codegen? codegen" + `, + ); + + expect(logSpy.mock.calls[2][0]).toContain(`Config file generated at codegen.ts`); expect(writeFileSpy).toHaveBeenCalledTimes(2); const pkg = JSON.parse(writeFileSpy.mock.calls[1][1] as string); + expect(pkg).toMatchInlineSnapshot(` + { + "dependencies": { + "@stencil/core": "x.x.x", + }, + "devDependencies": { + "@graphql-codegen/cli": "1.0.0", + "@graphql-codegen/typescript": "1.0.0", + "@graphql-codegen/typescript-operations": "1.0.0", + "@graphql-codegen/typescript-stencil-apollo": "1.0.0", + }, + "scripts": { + "codegen": "graphql-codegen --config codegen.ts", + }, + "version": "888.888.888", + } + `); + + const configFile = writeFileSpy.mock.calls[0][0] as string; const config = writeFileSpy.mock.calls[0][1] as string; - - expect(config).toMatchSnapshot(); - - // expected plugins - expect(pkg.devDependencies).toHaveProperty('@graphql-codegen/typescript'); - expect(pkg.devDependencies).toHaveProperty('@graphql-codegen/typescript-operations'); - expect(pkg.devDependencies).toHaveProperty('@graphql-codegen/typescript-stencil-apollo'); - // should not have other plugins - expect(Object.keys(pkg.devDependencies)).toHaveLength(4); + expect(configFile).toEqual(resolve(process.cwd(), 'codegen.ts')); + expect(config).toMatchInlineSnapshot(` + " + import type { CodegenConfig } from '@graphql-codegen/cli'; + + const config: CodegenConfig = { + overwrite: true, + schema: "http://localhost:4000", + documents: "src/**/*.graphql", + generates: { + "src/generated/graphql.tsx": { + plugins: ["typescript", "typescript-operations", "typescript-stencil-apollo"] + } + } + }; + + export default config; + " + `); }); }); @@ -235,144 +529,275 @@ describe('init', () => { it('should use typescript related plugins when typescript is found (node)', async () => { vol.fromJSON({ ['package.json']: packageJson.withTypescript }, process.cwd()); const writeFileSpy = vi.spyOn(fs, 'writeFileSync'); - // silent - vi.spyOn(console, 'log').mockImplementation(() => {}); - - useInputs({ - onTarget: [SELECT, ENTER], // confirm api target - onSchema: [ENTER], // use default - onPlugins: [ENTER], // use selected packages - onOutput: [ENTER], // use default output path - onIntrospection: ['n', ENTER], // no introspection, - onConfig: [ENTER], // use default config path - onScript: ['graphql', ENTER], // use custom npm script - }); - - await init(); + const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); // silent + + const result = init(); + + // targets + expect(screen.getScreen()).toMatchInlineSnapshot(` + "? What type of application are you building? + ❯ Backend - API or server + Application built with Angular + Application built with React + Application built with Stencil + Application built with Vue + Application using graphql-request + Application built with other framework or vanilla JS + + ↑↓ navigate • ⏎ select" + `); + screen.keypress('enter'); + await screen.next(); + + // schema + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? Where is your schema?: (path or url) (http://localhost:4000)"`, + ); + screen.keypress('enter'); + await screen.next(); + + // documents + expect(screen.getScreen()).toMatchInlineSnapshot( + ` + "? Pick plugins: + ❯◉ TypeScript (required by other typescript plugins) + ◉ TypeScript Resolvers (strongly typed resolve functions) + ◯ TypeScript MongoDB (typed MongoDB objects) + ◯ TypeScript GraphQL document nodes (embedded GraphQL document) + + ↑↓ navigate • space select • a all • i invert • ⏎ submit" + `, + ); + screen.keypress('enter'); + await screen.next(); + + // output + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? Where to write the output: (src/generated/graphql.ts)"`, + ); + screen.keypress('enter'); + await screen.next(); + + // introspection + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? Do you want to generate an introspection file? (y/N)"`, + ); + screen.keypress('n'); + screen.keypress('enter'); + await screen.next(); + + // config + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? How to name the config file? (codegen.ts)"`, + ); + screen.keypress('enter'); + await screen.next(); + + // script + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? What script in package.json should run the codegen? (codegen)"`, + ); + screen.keypress('enter'); + + await result; + + expect(await screen.getFullOutput()).toMatchInlineSnapshot( + ` + "✔ What type of application are you building? Backend - API or server + ✔ Where is your schema?: (path or url) http://localhost:4000 + ✔ Pick plugins: TypeScript (required by other typescript plugins), TypeScript Resolvers (strongly typed resolve functions) + ✔ Where to write the output: src/generated/graphql.ts + ✔ Do you want to generate an introspection file? No + ✔ How to name the config file? codegen.ts + ✔ What script in package.json should run the codegen? codegen" + `, + ); + + expect(logSpy.mock.calls[2][0]).toContain(`Config file generated at codegen.ts`); expect(writeFileSpy).toHaveBeenCalledTimes(2); const pkg = JSON.parse(writeFileSpy.mock.calls[1][1] as string); + expect(pkg).toMatchInlineSnapshot(` + { + "devDependencies": { + "@graphql-codegen/cli": "1.0.0", + "@graphql-codegen/typescript": "1.0.0", + "@graphql-codegen/typescript-resolvers": "1.0.0", + "typescript": "x.x.x", + }, + "scripts": { + "codegen": "graphql-codegen --config codegen.ts", + }, + "version": "888.888.888", + } + `); + + const configFile = writeFileSpy.mock.calls[0][0] as string; const config = writeFileSpy.mock.calls[0][1] as string; - - expect(config).toMatchSnapshot(); - - // expected plugins - expect(pkg.devDependencies).toHaveProperty('@graphql-codegen/typescript'); - expect(pkg.devDependencies).toHaveProperty('@graphql-codegen/typescript-resolvers'); - // should not have other plugins - expect(Object.keys(pkg.devDependencies)).toHaveLength(4); // 3 - because we have typescript package in devDeps - }); - }); - - it('should have few default values for Angular', async () => { - vol.fromJSON({ ['package.json']: packageJson.withReact }, process.cwd()); - const writeFileSpy = vi.spyOn(fs, 'writeFileSync'); - const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); - const defaults = { - config: 'codegen.ts', - }; - - useInputs({ - onTarget: [ENTER], // confirm angular target - onSchema: [ENTER], // use default - onDocuments: [ENTER], - onOutput: [ENTER], // use default output path - onIntrospection: [ENTER], // no introspection, - onConfig: [ENTER], // use default config path - onScript: ['graphql', ENTER], // use custom npm script + expect(configFile).toEqual(resolve(process.cwd(), 'codegen.ts')); + expect(config).toMatchInlineSnapshot(` + " + import type { CodegenConfig } from '@graphql-codegen/cli'; + + const config: CodegenConfig = { + overwrite: true, + schema: "http://localhost:4000", + generates: { + "src/generated/graphql.ts": { + plugins: ["typescript", "typescript-resolvers"] + } + } + }; + + export default config; + " + `); }); - - await init(); - - const configFile = writeFileSpy.mock.calls[0][0] as string; - const config = writeFileSpy.mock.calls[0][1] as string; - const pkg = JSON.parse(writeFileSpy.mock.calls[1][1] as string); - - expect(pkg.scripts.graphql).toEqual(`graphql-codegen --config codegen.ts`); - expect(configFile).toEqual(resolve(process.cwd(), defaults.config)); - expect(config).toMatchSnapshot(); - expect(logSpy.mock.calls[2][0]).toContain(`Config file generated at ${bold(defaults.config)}`); - }); - - it('should have few default values for React', async () => { - vol.fromJSON({ ['package.json']: packageJson.withReact }, process.cwd()); - const writeFileSpy = vi.spyOn(fs, 'writeFileSync'); - const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); - const options = { - script: 'graphql', - schema: './schema.ts', - documents: 'graphql/**/*.graphql', - output: 'graphql/index.ts', - config: 'app-codegen.yml', - }; - - useInputs({ - onTarget: [ENTER], // confirm target - onSchema: [options.schema, ENTER], // use default - onDocuments: [options.documents, ENTER], - onOutput: [options.output, ENTER], // use default output path - onIntrospection: ['y', ENTER], // with introspection, - onConfig: [options.config, ENTER], // use default config path - onScript: [options.script, ENTER], // use custom npm script - }); - - await init(); - - const configFile = writeFileSpy.mock.calls[0][0] as string; - const config = writeFileSpy.mock.calls[0][1] as string; - const pkg = JSON.parse(writeFileSpy.mock.calls[1][1] as string); - - expect(pkg.scripts[options.script]).toEqual(`graphql-codegen --config ${options.config}`); - expect(configFile).toEqual(resolve(process.cwd(), options.config)); - expect(config).toMatchSnapshot(); - expect(logSpy.mock.calls[2][0]).toContain(`Config file generated at ${bold(options.config)}`); }); it('custom setup', async () => { vol.fromJSON({ ['package.json']: packageJson.withReact }, process.cwd()); - - const { init } = await import('../src/init/index.js'); const writeFileSpy = vi.spyOn(fs, 'writeFileSync'); - const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); - const documents = 'graphql/*.ts'; - const script = 'generate:types'; - - useInputs({ - onTarget: [ENTER], // confirm target - onSchema: [ENTER], // use default - onDocuments: [documents, ENTER], - onOutput: [ENTER], // use default output path - onIntrospection: ['y', ENTER], // no introspection, - onConfig: [ENTER], // use default config path - onScript: [script, ENTER], // use custom npm script - }); + const logSpy = vi.spyOn(console, 'log').mockImplementation(() => {}); // silent + + const result = init(); + + // targets + expect(screen.getScreen()).toMatchInlineSnapshot(` + "? What type of application are you building? + Backend - API or server + Application built with Angular + ❯ Application built with React + Application built with Stencil + Application built with Vue + Application using graphql-request + Application built with other framework or vanilla JS + + ↑↓ navigate • ⏎ select" + `); + screen.keypress('enter'); + await screen.next(); + + // schema + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? Where is your schema?: (path or url) (http://localhost:4000)"`, + ); + screen.type('./schema.ts'); + screen.keypress('enter'); + await screen.next(); + + // documents + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? Where are your operations and fragments?: (src/**/*.tsx)"`, + ); + screen.type('graphql/*.ts'); + screen.keypress('enter'); + await screen.next(); + + // output + expect(screen.getScreen()).toMatchInlineSnapshot(`"? Where to write the output: (src/gql/)"`); + screen.type('graphql/index.ts'); + screen.keypress('enter'); + await screen.next(); + + // introspection + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? Do you want to generate an introspection file? (y/N)"`, + ); + screen.type('y'); + screen.keypress('enter'); + await screen.next(); - await init(); + // config + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? How to name the config file? (codegen.ts)"`, + ); + screen.type('app-codegen.yml'); + screen.keypress('enter'); + await screen.next(); + + // script + expect(screen.getScreen()).toMatchInlineSnapshot( + `"? What script in package.json should run the codegen? (codegen)"`, + ); + screen.type('generate:types'); + screen.keypress('enter'); + await result; + + expect(await screen.getFullOutput()).toMatchInlineSnapshot( + ` + "✔ What type of application are you building? Application built with React + ✔ Where is your schema?: (path or url) ./schema.ts + ✔ Where are your operations and fragments?: graphql/*.ts + ✔ Where to write the output: graphql/index.ts + ✔ Do you want to generate an introspection file? Yes + ✔ How to name the config file? app-codegen.yml + ✔ What script in package.json should run the codegen? generate:types" + `, + ); + + await result; expect(writeFileSpy).toHaveBeenCalledTimes(2); const pkg = JSON.parse(writeFileSpy.mock.calls[1][1] as string); - const config = writeFileSpy.mock.calls[0][1] as string; + expect(pkg).toMatchInlineSnapshot(` + { + "dependencies": { + "react": "x.x.x", + }, + "devDependencies": { + "@graphql-codegen/cli": "1.0.0", + "@graphql-codegen/client-preset": "1.0.0", + "@graphql-codegen/introspection": "1.0.0", + }, + "scripts": { + "generate:types": "graphql-codegen --config app-codegen.yml", + }, + "version": "888.888.888", + } + `); - // config - expect(config).toMatchSnapshot(); - - // script name should match what we provided - expect(pkg.scripts[script]).toEqual('graphql-codegen --config codegen.ts'); - // expected plugins - expect(pkg.devDependencies).toHaveProperty('@graphql-codegen/introspection'); - // should not have these plugins - expect(pkg.devDependencies).not.toHaveProperty('@graphql-codegen/typescript-resolvers'); + const configFile = writeFileSpy.mock.calls[0][0] as string; + const config = writeFileSpy.mock.calls[0][1] as string; + expect(configFile).toEqual(resolve(process.cwd(), 'app-codegen.yml')); + expect(config).toMatchInlineSnapshot(` + "overwrite: true + schema: "./schema.ts" + documents: "graphql/*.ts" + generates: + graphql/index.ts: + preset: "client" + plugins: [] + ./graphql.schema.json: + plugins: + - "introspection" + " + `); // logs const welcomeMsg = logSpy.mock.calls[0][0]; const doneMsg = logSpy.mock.calls[2][0]; + expect(welcomeMsg).toMatchInlineSnapshot(` + " + Welcome to GraphQL Code Generator! + Answer few questions and we will setup everything for you. + " + `); + expect(doneMsg).toMatchInlineSnapshot(` + " + Config file generated at app-codegen.yml + + $ npm install + + To install the plugins. - expect(welcomeMsg).toContain(`Welcome to ${bold('GraphQL Code Generator')}`); - expect(doneMsg).toContain(`Config file generated at ${bold('codegen.ts')}`); - expect(doneMsg).toContain(bold('$ npm install')); - expect(doneMsg).toContain(bold(`$ npm run ${script}`)); + $ npm run generate:types + + To run GraphQL Code Generator. + " + `); }); describe('plugin choices', () => { @@ -505,27 +930,3 @@ describe('init', () => { }); }); }); - -function useInputs(inputs: { - onTarget: string[]; - onSchema: string[]; - onDocuments?: string[]; - onPlugins?: string[]; - onOutput: string[]; - onIntrospection: string[]; - onConfig: string[]; - onScript: string[]; -}) { - bddStdin( - [].concat( - inputs.onTarget, - inputs.onSchema, - inputs.onDocuments || [], - inputs.onPlugins || [], - inputs.onOutput, - inputs.onIntrospection, - inputs.onConfig, - inputs.onScript, - ), - ); -} diff --git a/tsconfig.spec.json b/tsconfig.spec.json index 633551e9fd7..82d75080116 100644 --- a/tsconfig.spec.json +++ b/tsconfig.spec.json @@ -2,6 +2,8 @@ "extends": "./tsconfig.json", "compilerOptions": { "rootDir": ".", + "module": "nodenext", + "moduleResolution": "nodenext", "composite": true, "types": ["vitest/globals"] }, diff --git a/yarn.lock b/yarn.lock index 6dd735c7388..21b0f202188 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2889,63 +2889,60 @@ resolved "https://registry.yarnpkg.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz#a81ffb00e69267cd0a1d626eaedb8a8430b2b2f8" integrity sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw== -"@inquirer/ansi@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@inquirer/ansi/-/ansi-1.0.2.tgz#674a4c4d81ad460695cb2a1fc69d78cd187f337e" - integrity sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ== +"@inquirer/ansi@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@inquirer/ansi/-/ansi-2.0.4.tgz#c767aba4e224297c17108820e2401d9def117172" + integrity sha512-DpcZrQObd7S0R/U3bFdkcT5ebRwbTTC4D3tCc1vsJizmgPLxNJBo+AAFmrZwe8zk30P2QzgzGWZ3Q9uJwWuhIg== -"@inquirer/checkbox@^4.3.2": - version "4.3.2" - resolved "https://registry.yarnpkg.com/@inquirer/checkbox/-/checkbox-4.3.2.tgz#e1483e6519d6ffef97281a54d2a5baa0d81b3f3b" - integrity sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA== - dependencies: - "@inquirer/ansi" "^1.0.2" - "@inquirer/core" "^10.3.2" - "@inquirer/figures" "^1.0.15" - "@inquirer/type" "^3.0.10" - yoctocolors-cjs "^2.1.3" - -"@inquirer/confirm@^5.1.21": - version "5.1.21" - resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-5.1.21.tgz#610c4acd7797d94890a6e2dde2c98eb1e891dd12" - integrity sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ== - dependencies: - "@inquirer/core" "^10.3.2" - "@inquirer/type" "^3.0.10" - -"@inquirer/core@^10.3.2": - version "10.3.2" - resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-10.3.2.tgz#535979ff3ff4fe1e7cc4f83e2320504c743b7e20" - integrity sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A== - dependencies: - "@inquirer/ansi" "^1.0.2" - "@inquirer/figures" "^1.0.15" - "@inquirer/type" "^3.0.10" +"@inquirer/checkbox@^5.1.2": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@inquirer/checkbox/-/checkbox-5.1.2.tgz#8cc30b3f16625b1f29425ce68fd7b65d03759807" + integrity sha512-PubpMPO2nJgMufkoB3P2wwxNXEMUXnBIKi/ACzDUYfaoPuM7gSTmuxJeMscoLVEsR4qqrCMf5p0SiYGWnVJ8kw== + dependencies: + "@inquirer/ansi" "^2.0.4" + "@inquirer/core" "^11.1.7" + "@inquirer/figures" "^2.0.4" + "@inquirer/type" "^4.0.4" + +"@inquirer/confirm@^6.0.10": + version "6.0.10" + resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-6.0.10.tgz#96366b834273421233f3eae1a55b47cd19e75228" + integrity sha512-tiNyA73pgpQ0FQ7axqtoLUe4GDYjNCDcVsbgcA5anvwg2z6i+suEngLKKJrWKJolT//GFPZHwN30binDIHgSgQ== + dependencies: + "@inquirer/core" "^11.1.7" + "@inquirer/type" "^4.0.4" + +"@inquirer/core@^11.1.7": + version "11.1.7" + resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-11.1.7.tgz#053041e54dc35d0043a9280d94f58da0e3a7b716" + integrity sha512-1BiBNDk9btIwYIzNZpkikIHXWeNzNncJePPqwDyVMhXhD1ebqbpn1mKGctpoqAbzywZfdG0O4tvmsGIcOevAPQ== + dependencies: + "@inquirer/ansi" "^2.0.4" + "@inquirer/figures" "^2.0.4" + "@inquirer/type" "^4.0.4" cli-width "^4.1.0" - mute-stream "^2.0.0" + fast-wrap-ansi "^0.2.0" + mute-stream "^3.0.0" signal-exit "^4.1.0" - wrap-ansi "^6.2.0" - yoctocolors-cjs "^2.1.3" -"@inquirer/editor@^4.2.23": - version "4.2.23" - resolved "https://registry.yarnpkg.com/@inquirer/editor/-/editor-4.2.23.tgz#fe046a3bfdae931262de98c1052437d794322e0b" - integrity sha512-aLSROkEwirotxZ1pBaP8tugXRFCxW94gwrQLxXfrZsKkfjOYC1aRvAZuhpJOb5cu4IBTJdsCigUlf2iCOu4ZDQ== +"@inquirer/editor@^5.0.10": + version "5.0.10" + resolved "https://registry.yarnpkg.com/@inquirer/editor/-/editor-5.0.10.tgz#5e019f4b8e7f3049391b366074cf566c909f912f" + integrity sha512-VJx4XyaKea7t8hEApTw5dxeIyMtWXre2OiyJcICCRZI4hkoHsMoCnl/KbUnJJExLbH9csLLHMVR144ZhFE1CwA== dependencies: - "@inquirer/core" "^10.3.2" - "@inquirer/external-editor" "^1.0.3" - "@inquirer/type" "^3.0.10" + "@inquirer/core" "^11.1.7" + "@inquirer/external-editor" "^2.0.4" + "@inquirer/type" "^4.0.4" -"@inquirer/expand@^4.0.23": - version "4.0.23" - resolved "https://registry.yarnpkg.com/@inquirer/expand/-/expand-4.0.23.tgz#a38b5f32226d75717c370bdfed792313b92bdc05" - integrity sha512-nRzdOyFYnpeYTTR2qFwEVmIWypzdAx/sIkCMeTNTcflFOovfqUk+HcFhQQVBftAh9gmGrpFj6QcGEqrDMDOiew== +"@inquirer/expand@^5.0.10": + version "5.0.10" + resolved "https://registry.yarnpkg.com/@inquirer/expand/-/expand-5.0.10.tgz#0c24970db9cf5ed3327ea0e9ce06e82103731992" + integrity sha512-fC0UHJPXsTRvY2fObiwuQYaAnHrp3aDqfwKUJSdfpgv18QUG054ezGbaRNStk/BKD5IPijeMKWej8VV8O5Q/eQ== dependencies: - "@inquirer/core" "^10.3.2" - "@inquirer/type" "^3.0.10" - yoctocolors-cjs "^2.1.3" + "@inquirer/core" "^11.1.7" + "@inquirer/type" "^4.0.4" -"@inquirer/external-editor@^1.0.2", "@inquirer/external-editor@^1.0.3": +"@inquirer/external-editor@^1.0.2": version "1.0.3" resolved "https://registry.yarnpkg.com/@inquirer/external-editor/-/external-editor-1.0.3.tgz#c23988291ee676290fdab3fd306e64010a6d13b8" integrity sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA== @@ -2953,86 +2950,100 @@ chardet "^2.1.1" iconv-lite "^0.7.0" -"@inquirer/figures@^1.0.15": - version "1.0.15" - resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.15.tgz#dbb49ed80df11df74268023b496ac5d9acd22b3a" - integrity sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g== +"@inquirer/external-editor@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@inquirer/external-editor/-/external-editor-2.0.4.tgz#1178821c52014bf70bbadd664ee6fedc37a40b5c" + integrity sha512-Prenuv9C1PHj2Itx0BcAOVBTonz02Hc2Nd2DbU67PdGUaqn0nPCnV34oDyyoaZHnmfRxkpuhh/u51ThkrO+RdA== + dependencies: + chardet "^2.1.1" + iconv-lite "^0.7.2" -"@inquirer/input@^4.3.1": - version "4.3.1" - resolved "https://registry.yarnpkg.com/@inquirer/input/-/input-4.3.1.tgz#778683b4c4c4d95d05d4b05c4a854964b73565b4" - integrity sha512-kN0pAM4yPrLjJ1XJBjDxyfDduXOuQHrBB8aLDMueuwUGn+vNpF7Gq7TvyVxx8u4SHlFFj4trmj+a2cbpG4Jn1g== +"@inquirer/figures@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-2.0.4.tgz#154986941a00db8b8171d1ed0d1df566972ed173" + integrity sha512-eLBsjlS7rPS3WEhmOmh1znQ5IsQrxWzxWDxO51e4urv+iVrSnIHbq4zqJIOiyNdYLa+BVjwOtdetcQx1lWPpiQ== + +"@inquirer/input@^5.0.10": + version "5.0.10" + resolved "https://registry.yarnpkg.com/@inquirer/input/-/input-5.0.10.tgz#0a18347e8f16d4cb01e1d801f1ca8fcca26006dc" + integrity sha512-nvZ6qEVeX/zVtZ1dY2hTGDQpVGD3R7MYPLODPgKO8Y+RAqxkrP3i/3NwF3fZpLdaMiNuK0z2NaYIx9tPwiSegQ== dependencies: - "@inquirer/core" "^10.3.2" - "@inquirer/type" "^3.0.10" + "@inquirer/core" "^11.1.7" + "@inquirer/type" "^4.0.4" -"@inquirer/number@^3.0.23": - version "3.0.23" - resolved "https://registry.yarnpkg.com/@inquirer/number/-/number-3.0.23.tgz#3fdec2540d642093fd7526818fd8d4bdc7335094" - integrity sha512-5Smv0OK7K0KUzUfYUXDXQc9jrf8OHo4ktlEayFlelCjwMXz0299Y8OrI+lj7i4gCBY15UObk76q0QtxjzFcFcg== - dependencies: - "@inquirer/core" "^10.3.2" - "@inquirer/type" "^3.0.10" - -"@inquirer/password@^4.0.23": - version "4.0.23" - resolved "https://registry.yarnpkg.com/@inquirer/password/-/password-4.0.23.tgz#b9f5187c8c92fd7aa9eceb9d8f2ead0d7e7b000d" - integrity sha512-zREJHjhT5vJBMZX/IUbyI9zVtVfOLiTO66MrF/3GFZYZ7T4YILW5MSkEYHceSii/KtRk+4i3RE7E1CUXA2jHcA== - dependencies: - "@inquirer/ansi" "^1.0.2" - "@inquirer/core" "^10.3.2" - "@inquirer/type" "^3.0.10" - -"@inquirer/prompts@^7.8.2": - version "7.10.1" - resolved "https://registry.yarnpkg.com/@inquirer/prompts/-/prompts-7.10.1.tgz#e1436c0484cf04c22548c74e2cd239e989d5f847" - integrity sha512-Dx/y9bCQcXLI5ooQ5KyvA4FTgeo2jYj/7plWfV5Ak5wDPKQZgudKez2ixyfz7tKXzcJciTxqLeK7R9HItwiByg== - dependencies: - "@inquirer/checkbox" "^4.3.2" - "@inquirer/confirm" "^5.1.21" - "@inquirer/editor" "^4.2.23" - "@inquirer/expand" "^4.0.23" - "@inquirer/input" "^4.3.1" - "@inquirer/number" "^3.0.23" - "@inquirer/password" "^4.0.23" - "@inquirer/rawlist" "^4.1.11" - "@inquirer/search" "^3.2.2" - "@inquirer/select" "^4.4.2" - -"@inquirer/rawlist@^4.1.11": - version "4.1.11" - resolved "https://registry.yarnpkg.com/@inquirer/rawlist/-/rawlist-4.1.11.tgz#313c8c3ffccb7d41e990c606465726b4a898a033" - integrity sha512-+LLQB8XGr3I5LZN/GuAHo+GpDJegQwuPARLChlMICNdwW7OwV2izlCSCxN6cqpL0sMXmbKbFcItJgdQq5EBXTw== - dependencies: - "@inquirer/core" "^10.3.2" - "@inquirer/type" "^3.0.10" - yoctocolors-cjs "^2.1.3" - -"@inquirer/search@^3.2.2": - version "3.2.2" - resolved "https://registry.yarnpkg.com/@inquirer/search/-/search-3.2.2.tgz#4cc6fd574dcd434e4399badc37c742c3fd534ac8" - integrity sha512-p2bvRfENXCZdWF/U2BXvnSI9h+tuA8iNqtUKb9UWbmLYCRQxd8WkvwWvYn+3NgYaNwdUkHytJMGG4MMLucI1kA== +"@inquirer/number@^4.0.10": + version "4.0.10" + resolved "https://registry.yarnpkg.com/@inquirer/number/-/number-4.0.10.tgz#e8d3a3f218c8795c0aade0cb1821df8a0f4682b4" + integrity sha512-Ht8OQstxiS3APMGjHV0aYAjRAysidWdwurWEo2i8yI5xbhOBWqizT0+MU1S2GCcuhIBg+3SgWVjEoXgfhY+XaA== dependencies: - "@inquirer/core" "^10.3.2" - "@inquirer/figures" "^1.0.15" - "@inquirer/type" "^3.0.10" - yoctocolors-cjs "^2.1.3" + "@inquirer/core" "^11.1.7" + "@inquirer/type" "^4.0.4" -"@inquirer/select@^4.4.2": - version "4.4.2" - resolved "https://registry.yarnpkg.com/@inquirer/select/-/select-4.4.2.tgz#2ac8fca960913f18f1d1b35323ed8fcd27d89323" - integrity sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w== +"@inquirer/password@^5.0.10": + version "5.0.10" + resolved "https://registry.yarnpkg.com/@inquirer/password/-/password-5.0.10.tgz#53cc6613ac2cb18b018f83d0731c73783ba3c353" + integrity sha512-QbNyvIE8q2GTqKLYSsA8ATG+eETo+m31DSR0+AU7x3d2FhaTWzqQek80dj3JGTo743kQc6mhBR0erMjYw5jQ0A== dependencies: - "@inquirer/ansi" "^1.0.2" - "@inquirer/core" "^10.3.2" - "@inquirer/figures" "^1.0.15" - "@inquirer/type" "^3.0.10" - yoctocolors-cjs "^2.1.3" + "@inquirer/ansi" "^2.0.4" + "@inquirer/core" "^11.1.7" + "@inquirer/type" "^4.0.4" -"@inquirer/type@^3.0.10": - version "3.0.10" - resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-3.0.10.tgz#11ed564ec78432a200ea2601a212d24af8150d50" - integrity sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA== +"@inquirer/prompts@^8.3.2": + version "8.3.2" + resolved "https://registry.yarnpkg.com/@inquirer/prompts/-/prompts-8.3.2.tgz#7d2464b53011a5fbd5cc6f22b365a61c60104a2a" + integrity sha512-yFroiSj2iiBFlm59amdTvAcQFvWS6ph5oKESls/uqPBect7rTU2GbjyZO2DqxMGuIwVA8z0P4K6ViPcd/cp+0w== + dependencies: + "@inquirer/checkbox" "^5.1.2" + "@inquirer/confirm" "^6.0.10" + "@inquirer/editor" "^5.0.10" + "@inquirer/expand" "^5.0.10" + "@inquirer/input" "^5.0.10" + "@inquirer/number" "^4.0.10" + "@inquirer/password" "^5.0.10" + "@inquirer/rawlist" "^5.2.6" + "@inquirer/search" "^4.1.6" + "@inquirer/select" "^5.1.2" + +"@inquirer/rawlist@^5.2.6": + version "5.2.6" + resolved "https://registry.yarnpkg.com/@inquirer/rawlist/-/rawlist-5.2.6.tgz#fcc00c80e2d4597ba6010eb72e373690c6c82241" + integrity sha512-jfw0MLJ5TilNsa9zlJ6nmRM0ZFVZhhTICt4/6CU2Dv1ndY7l3sqqo1gIYZyMMDw0LvE1u1nzJNisfHEhJIxq5w== + dependencies: + "@inquirer/core" "^11.1.7" + "@inquirer/type" "^4.0.4" + +"@inquirer/search@^4.1.6": + version "4.1.6" + resolved "https://registry.yarnpkg.com/@inquirer/search/-/search-4.1.6.tgz#399b87074af1e7a2c8d6924fe6bd90b993f40f41" + integrity sha512-3/6kTRae98hhDevENScy7cdFEuURnSpM3JbBNg8yfXLw88HgTOl+neUuy/l9W0No5NzGsLVydhBzTIxZP7yChQ== + dependencies: + "@inquirer/core" "^11.1.7" + "@inquirer/figures" "^2.0.4" + "@inquirer/type" "^4.0.4" + +"@inquirer/select@^5.1.2": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@inquirer/select/-/select-5.1.2.tgz#d40f6af6fe86dbdbd97587a76ba3101274fb5208" + integrity sha512-kTK8YIkHV+f02y7bWCh7E0u2/11lul5WepVTclr3UMBtBr05PgcZNWfMa7FY57ihpQFQH/spLMHTcr0rXy50tA== + dependencies: + "@inquirer/ansi" "^2.0.4" + "@inquirer/core" "^11.1.7" + "@inquirer/figures" "^2.0.4" + "@inquirer/type" "^4.0.4" + +"@inquirer/testing@3.3.2": + version "3.3.2" + resolved "https://registry.yarnpkg.com/@inquirer/testing/-/testing-3.3.2.tgz#8f111529276ba88bd99d81133d1b2aa374818c3b" + integrity sha512-kR5fSmr6eV0sz6bonnDrW8PDdVC2D15Ftv0Y4+y081fidr+4XhruPezz5/GqUHYRCvQXcBG8w1UhWGIU0zy+Vg== + dependencies: + "@inquirer/type" "^4.0.4" + "@xterm/headless" "^6.0.0" + mute-stream "^3.0.0" + +"@inquirer/type@^4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-4.0.4.tgz#ef66cf0ee6af7d240d5aa462dd7697be010a1837" + integrity sha512-PamArxO3cFJZoOzspzo6cxVlLeIftyBsZw/S9bKY5DzxqJVZgjoj1oP8d0rskKtp7sZxBycsoer1g6UeJV1BBA== "@isaacs/cliui@^8.0.2": version "8.0.2" @@ -5824,6 +5835,11 @@ resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.9.9.tgz#665b1cf4e5962d248bb4d032b5e020626f634503" integrity sha512-qycIHAucxy/LXAYIjmLmtQ8q9GPnMbnjG1KXhWm9o5sCr6pOYDATkMPiTNa6/v8eELyqOQ2FsEqeoFYmgv/gJg== +"@xterm/headless@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@xterm/headless/-/headless-6.0.0.tgz#a839dee397c49834bb220fa5951d60f4b7f0aa11" + integrity sha512-5Yj1QINYCyzrZtf8OFIHi47iQtI+0qYFPHmouEfG8dHNxbZ9Tb9YGSuLcsEwj9Z+OL75GJqPyJbyoFer80a2Hw== + "@yarnpkg/lockfile@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" @@ -6299,13 +6315,6 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" -bdd-stdin@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/bdd-stdin/-/bdd-stdin-0.2.0.tgz#04e66aa480e0e0df861e288a4062fb8557db2441" - integrity sha512-PH3Xlt0JkiIgxknpZrW4Ato1ZPkMSp1JdfKnKiDDWVMVntoKJhyTwSV9Hk0K0gTMhsaQJMFCcyazg3EsXt+9jg== - dependencies: - mock-stdin "0.3.0" - better-path-resolve@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/better-path-resolve/-/better-path-resolve-1.0.0.tgz#13a35a1104cdd48a7b74bf8758f96a1ee613f99d" @@ -8714,11 +8723,30 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-string-truncated-width@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/fast-string-truncated-width/-/fast-string-truncated-width-3.0.3.tgz#23afe0da67d752ca0727538f1e6967759728ce49" + integrity sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g== + +fast-string-width@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/fast-string-width/-/fast-string-width-3.0.2.tgz#16dbabb491ce5585b5ecb675b65c165d71688eeb" + integrity sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg== + dependencies: + fast-string-truncated-width "^3.0.2" + fast-uri@^3.0.1: version "3.1.0" resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa" integrity sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA== +fast-wrap-ansi@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/fast-wrap-ansi/-/fast-wrap-ansi-0.2.0.tgz#c0ae3f3982d061c3d657ec927196fbb47e22fe64" + integrity sha512-rLV8JHxTyhVmFYhBJuMujcrHqOT2cnO5Zxj37qROj23CP39GXubJRBUFF0z8KFK77Uc0SukZUf7JZhsVEQ6n8w== + dependencies: + fast-string-width "^3.0.2" + fast-xml-builder@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/fast-xml-builder/-/fast-xml-builder-1.1.4.tgz#0c407a1d9d5996336c0cd76f7ff785cac6413017" @@ -9666,7 +9694,7 @@ iconv-lite@0.6: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" -iconv-lite@^0.7.0: +iconv-lite@^0.7.0, iconv-lite@^0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.7.2.tgz#d0bdeac3f12b4835b7359c2ad89c422a4d1cc72e" integrity sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw== @@ -11722,11 +11750,6 @@ mlly@^1.7.4, mlly@^1.8.0: pkg-types "^1.3.1" ufo "^1.6.3" -mock-stdin@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/mock-stdin/-/mock-stdin-0.3.0.tgz#f40d2a513a114e6d547480625b5ef5190744bd4d" - integrity sha512-RgODIm+s+lEFH+BUlJbLFm2m7oeuNQNFyUU3Bvviqp14bhPJZhzIv4ovN3pdejqK/GyNqdKENLKxR55rDPDnXw== - moment@~2.30.0: version "2.30.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" @@ -11757,10 +11780,10 @@ muggle-string@^0.4.1: resolved "https://registry.yarnpkg.com/muggle-string/-/muggle-string-0.4.1.tgz#3b366bd43b32f809dc20659534dd30e7c8a0d328" integrity sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ== -mute-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-2.0.0.tgz#a5446fc0c512b71c83c44d908d5c7b7b4c493b2b" - integrity sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA== +mute-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-3.0.0.tgz#cd8014dd2acb72e1e91bb67c74f0019e620ba2d1" + integrity sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw== mvdan-sh@^0.10.1: version "0.10.1" @@ -16048,11 +16071,6 @@ yocto-queue@^1.0.0, yocto-queue@^1.1.1: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.2.2.tgz#3e09c95d3f1aa89a58c114c99223edf639152c00" integrity sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ== -yoctocolors-cjs@^2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz#7e4964ea8ec422b7a40ac917d3a344cfd2304baa" - integrity sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw== - yoctocolors@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/yoctocolors/-/yoctocolors-2.1.2.tgz#d795f54d173494e7d8db93150cec0ed7f678c83a" From 184ac19aa479668a05a56dd2ab2af6d7250d285e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 22 Mar 2026 13:30:36 +0000 Subject: [PATCH 60/69] chore(dependencies): updated changesets for modified dependencies --- .changeset/@graphql-codegen_cli-10496-dependencies.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.changeset/@graphql-codegen_cli-10496-dependencies.md b/.changeset/@graphql-codegen_cli-10496-dependencies.md index 0b9986b071b..886bea55e86 100644 --- a/.changeset/@graphql-codegen_cli-10496-dependencies.md +++ b/.changeset/@graphql-codegen_cli-10496-dependencies.md @@ -2,6 +2,7 @@ "@graphql-codegen/cli": patch --- dependencies updates: + - Updated dependency [`@inquirer/prompts@^8.3.2` ↗︎](https://www.npmjs.com/package/@inquirer/prompts/v/8.3.2) (from `^7.8.2`, in `dependencies`) - Updated dependency [`chalk@^5.6.0` ↗︎](https://www.npmjs.com/package/chalk/v/5.6.0) (from `^4.1.0`, in `dependencies`) - Updated dependency [`debounce@^3.0.0` ↗︎](https://www.npmjs.com/package/debounce/v/3.0.0) (from `^2.0.0`, in `dependencies`) - Updated dependency [`detect-indent@^7.0.0` ↗︎](https://www.npmjs.com/package/detect-indent/v/7.0.0) (from `^6.0.0`, in `dependencies`) From 57ca91ebd201a237893f7987ab77e50fd5b264a8 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Mon, 23 Mar 2026 00:44:46 +1100 Subject: [PATCH 61/69] Add ESM changeset --- .changeset/hot-toys-leave.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .changeset/hot-toys-leave.md diff --git a/.changeset/hot-toys-leave.md b/.changeset/hot-toys-leave.md new file mode 100644 index 00000000000..95a20947acc --- /dev/null +++ b/.changeset/hot-toys-leave.md @@ -0,0 +1,21 @@ +--- +'@graphql-codegen/typed-document-node': major +'@graphql-codegen/gql-tag-operations': major +'@graphql-codegen/visitor-plugin-common': major +'@graphql-codegen/typescript-document-nodes': major +'@graphql-codegen/typescript-operations': major +'@graphql-codegen/typescript': major +'@graphql-codegen/typescript-resolvers': major +'@graphql-codegen/graphql-modules-preset': major +'@graphql-codegen/plugin-helpers': major +'@graphql-codegen/cli': major +'@graphql-codegen/client-preset': major +--- + +BREAKING CHANGE: Update deps to latest, some only support ESM + +Node 20 support is dropped in this release. +Node 22 comes with `require()` support for ESM, which means it's easier to integrate ES modules into applications. Therefore, it is safe to start using ESM-only packages. + +If you are a user, please upgrade to Node 22. +If you are a lib maintainer and see ESM vs CJS issues when running Jest tests, try using Vitest. From c896d84b6884741c95f51b12a4dec82253364a1d Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Tue, 24 Mar 2026 22:29:35 +1100 Subject: [PATCH 62/69] [client-preset] Make persisted docs default hashing algorithm sha256, and follow recommended format (#10652) * Update default hash to be sha256 for persisted documents * Add changeset * chore(dependencies): updated changesets for modified dependencies * Update tests * chore(dependencies): updated changesets for modified dependencies --------- Co-authored-by: github-actions[bot] --- .changeset/sad-rules-sell.md | 5 +++ .../src/gql/graphql.ts | 2 +- .../src/gql/persisted-documents.json | 2 +- .../persisted-documents/src/gql/graphql.ts | 2 +- .../src/gql/persisted-documents.json | 2 +- packages/presets/client/src/index.ts | 4 +- .../presets/client/src/persisted-documents.ts | 7 ++- .../client/tests/client-preset.spec.ts | 44 +++++++++---------- .../pages/plugins/presets/preset-client.mdx | 4 +- 9 files changed, 41 insertions(+), 31 deletions(-) create mode 100644 .changeset/sad-rules-sell.md diff --git a/.changeset/sad-rules-sell.md b/.changeset/sad-rules-sell.md new file mode 100644 index 00000000000..d5725fe05bf --- /dev/null +++ b/.changeset/sad-rules-sell.md @@ -0,0 +1,5 @@ +--- +'@graphql-codegen/client-preset': major +--- + +BREAKING CHANGES: The default hashing algorithm is now sha256 instead of sha1. Generated sha256 format also follows the standard outlined in https://github.com/graphql/graphql-over-http/blob/52d56fb36d51c17e08a920510a23bdc2f6a720be/spec/Appendix%20A%20--%20Persisted%20Documents.md#sha256-hex-document-identifier diff --git a/examples/persisted-documents-string-mode/src/gql/graphql.ts b/examples/persisted-documents-string-mode/src/gql/graphql.ts index 1aaa31e4817..c6b1307f0cc 100644 --- a/examples/persisted-documents-string-mode/src/gql/graphql.ts +++ b/examples/persisted-documents-string-mode/src/gql/graphql.ts @@ -37,5 +37,5 @@ export const HelloQueryDocument = new TypedDocumentString( hello } `, - { hash: '86f01e23de1c770cabbc35b2d87f2e5fd7557b6f' }, + { hash: 'sha256:4c3f5d98b02279859b4c0c4efdba9553ac7acf89b9b0785eb24be68d5a67e6e8' }, ) as unknown as TypedDocumentString; diff --git a/examples/persisted-documents-string-mode/src/gql/persisted-documents.json b/examples/persisted-documents-string-mode/src/gql/persisted-documents.json index c9ef75fe915..61c91812c4e 100644 --- a/examples/persisted-documents-string-mode/src/gql/persisted-documents.json +++ b/examples/persisted-documents-string-mode/src/gql/persisted-documents.json @@ -1,3 +1,3 @@ { - "86f01e23de1c770cabbc35b2d87f2e5fd7557b6f": "query HelloQuery { hello }" + "sha256:4c3f5d98b02279859b4c0c4efdba9553ac7acf89b9b0785eb24be68d5a67e6e8": "query HelloQuery { hello }" } diff --git a/examples/persisted-documents/src/gql/graphql.ts b/examples/persisted-documents/src/gql/graphql.ts index a3786f6e6e9..e7c3b9ffd4e 100644 --- a/examples/persisted-documents/src/gql/graphql.ts +++ b/examples/persisted-documents/src/gql/graphql.ts @@ -13,7 +13,7 @@ export type HelloQueryQueryVariables = Exact<{ [key: string]: never }>; export type HelloQueryQuery = { hello: string }; export const HelloQueryDocument = { - __meta__: { hash: '86f01e23de1c770cabbc35b2d87f2e5fd7557b6f' }, + __meta__: { hash: 'sha256:4c3f5d98b02279859b4c0c4efdba9553ac7acf89b9b0785eb24be68d5a67e6e8' }, kind: 'Document', definitions: [ { diff --git a/examples/persisted-documents/src/gql/persisted-documents.json b/examples/persisted-documents/src/gql/persisted-documents.json index c9ef75fe915..61c91812c4e 100644 --- a/examples/persisted-documents/src/gql/persisted-documents.json +++ b/examples/persisted-documents/src/gql/persisted-documents.json @@ -1,3 +1,3 @@ { - "86f01e23de1c770cabbc35b2d87f2e5fd7557b6f": "query HelloQuery { hello }" + "sha256:4c3f5d98b02279859b4c0c4efdba9553ac7acf89b9b0785eb24be68d5a67e6e8": "query HelloQuery { hello }" } diff --git a/packages/presets/client/src/index.ts b/packages/presets/client/src/index.ts index 939d8dd8031..41161425b91 100644 --- a/packages/presets/client/src/index.ts +++ b/packages/presets/client/src/index.ts @@ -94,7 +94,7 @@ export type ClientPresetConfig = { * The algorithm parameter is typed with known algorithms and as a string rather than a union because it solely depends on Crypto's algorithms supported * by the version of OpenSSL on the platform. * - * @default `sha1` + * @default `sha256` */ hashAlgorithm?: 'sha1' | 'sha256' | (string & {}) | ((operation: string) => string); }; @@ -179,7 +179,7 @@ export const preset: Types.OutputPreset = { hashAlgorithm: (typeof options.presetConfig.persistedDocuments === 'object' && options.presetConfig.persistedDocuments.hashAlgorithm) || - 'sha1', + 'sha256', } : null; diff --git a/packages/presets/client/src/persisted-documents.ts b/packages/presets/client/src/persisted-documents.ts index 1fdb21a2563..356fb02d6de 100644 --- a/packages/presets/client/src/persisted-documents.ts +++ b/packages/presets/client/src/persisted-documents.ts @@ -7,6 +7,8 @@ const CONNECTION_DIRECTIVE_NAME = 'connection'; /** * This function generates a hash from a document node. + * When `sha256` algorithm is used, the hash should be prefixed with `sha256:` + * https://github.com/graphql/graphql-over-http/blob/52d56fb36d51c17e08a920510a23bdc2f6a720be/spec/Appendix%20A%20--%20Persisted%20Documents.md#sha256-hex-document-identifier */ export function generateDocumentHash( operation: string, @@ -17,7 +19,10 @@ export function generateDocumentHash( } const shasum = crypto.createHash(algorithm); shasum.update(operation); - return shasum.digest('hex'); + + const algorithmPrefix = algorithm === 'sha256' ? 'sha256:' : ''; + + return algorithmPrefix + shasum.digest('hex'); } /** diff --git a/packages/presets/client/tests/client-preset.spec.ts b/packages/presets/client/tests/client-preset.spec.ts index ebfdae04e20..9f132b6f4e2 100644 --- a/packages/presets/client/tests/client-preset.spec.ts +++ b/packages/presets/client/tests/client-preset.spec.ts @@ -1533,8 +1533,8 @@ export * from "./gql.cjs";`); expect(persistedDocuments.content).toMatchInlineSnapshot(` "{ - "b61b879c1eb0040bce65d70c8adfb1ae9360f52f": "query A { a }", - "c3ea9f3f937d47d72c70055ea55c7cf88a35e608": "query B { b }" + "sha256:7d0eedabb966107835cf307a0ebaf93b5d2cb8c30228611ffe3d27a53c211a0c": "query A { a }", + "sha256:a62a11aa72041e38d8c12ef77e1e7c208d9605db60bb5abb1717e8af98e4b410": "query B { b }" }" `); @@ -1559,8 +1559,8 @@ export * from "./gql.cjs";`); export type CFragment = { c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; - export const ADocument = {"__meta__":{"hash":"b61b879c1eb0040bce65d70c8adfb1ae9360f52f"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; - export const BDocument = {"__meta__":{"hash":"c3ea9f3f937d47d72c70055ea55c7cf88a35e608"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"B"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"b"}}]}}]} as unknown as DocumentNode;" + export const ADocument = {"__meta__":{"hash":"sha256:7d0eedabb966107835cf307a0ebaf93b5d2cb8c30228611ffe3d27a53c211a0c"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; + export const BDocument = {"__meta__":{"hash":"sha256:a62a11aa72041e38d8c12ef77e1e7c208d9605db60bb5abb1717e8af98e4b410"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"B"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"b"}}]}}]} as unknown as DocumentNode;" `); }); @@ -1597,8 +1597,8 @@ export * from "./gql.cjs";`); expect(persistedDocuments.content).toMatchInlineSnapshot(` "{ - "b61b879c1eb0040bce65d70c8adfb1ae9360f52f": "query A { a }", - "c3ea9f3f937d47d72c70055ea55c7cf88a35e608": "query B { b }" + "sha256:7d0eedabb966107835cf307a0ebaf93b5d2cb8c30228611ffe3d27a53c211a0c": "query A { a }", + "sha256:a62a11aa72041e38d8c12ef77e1e7c208d9605db60bb5abb1717e8af98e4b410": "query B { b }" }" `); @@ -1623,8 +1623,8 @@ export * from "./gql.cjs";`); export type CFragment = { c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; - export const ADocument = {"__meta__":{"hash":"b61b879c1eb0040bce65d70c8adfb1ae9360f52f"}} as unknown as DocumentNode; - export const BDocument = {"__meta__":{"hash":"c3ea9f3f937d47d72c70055ea55c7cf88a35e608"}} as unknown as DocumentNode;" + export const ADocument = {"__meta__":{"hash":"sha256:7d0eedabb966107835cf307a0ebaf93b5d2cb8c30228611ffe3d27a53c211a0c"}} as unknown as DocumentNode; + export const BDocument = {"__meta__":{"hash":"sha256:a62a11aa72041e38d8c12ef77e1e7c208d9605db60bb5abb1717e8af98e4b410"}} as unknown as DocumentNode;" `); }); @@ -1661,8 +1661,8 @@ export * from "./gql.cjs";`); expect(persistedDocuments.content).toMatchInlineSnapshot(` "{ - "b61b879c1eb0040bce65d70c8adfb1ae9360f52f": "query A { a }", - "c3ea9f3f937d47d72c70055ea55c7cf88a35e608": "query B { b }" + "sha256:7d0eedabb966107835cf307a0ebaf93b5d2cb8c30228611ffe3d27a53c211a0c": "query A { a }", + "sha256:a62a11aa72041e38d8c12ef77e1e7c208d9605db60bb5abb1717e8af98e4b410": "query B { b }" }" `); @@ -1687,8 +1687,8 @@ export * from "./gql.cjs";`); export type CFragment = { c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; - export const ADocument = {"__meta__":{"custom_property_name":"b61b879c1eb0040bce65d70c8adfb1ae9360f52f"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; - export const BDocument = {"__meta__":{"custom_property_name":"c3ea9f3f937d47d72c70055ea55c7cf88a35e608"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"B"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"b"}}]}}]} as unknown as DocumentNode;" + export const ADocument = {"__meta__":{"custom_property_name":"sha256:7d0eedabb966107835cf307a0ebaf93b5d2cb8c30228611ffe3d27a53c211a0c"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; + export const BDocument = {"__meta__":{"custom_property_name":"sha256:a62a11aa72041e38d8c12ef77e1e7c208d9605db60bb5abb1717e8af98e4b410"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"B"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"b"}}]}}]} as unknown as DocumentNode;" `); }); @@ -1749,8 +1749,8 @@ export * from "./gql.cjs";`); export type BbbQuery = { b: string | null }; - export const AaaDocument = {"__meta__":{"cacheKeys":["aaa"],"hash":"682f60dea844320c05fcb4fb6c4118015902c9a8"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"aaa"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; - export const BbbDocument = {"__meta__":{"cacheKeys":["bbb"],"hash":"2a8e0849914b13ebc13b112ba5a502678d757511"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"bbb"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"b"}}]}}]} as unknown as DocumentNode;" + export const AaaDocument = {"__meta__":{"cacheKeys":["aaa"],"hash":"sha256:a3728239db824c94acc4e31d248e0f05d527606cc8a1bdc4c31307564cd713a1"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"aaa"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; + export const BbbDocument = {"__meta__":{"cacheKeys":["bbb"],"hash":"sha256:a8badf5c61adc3e65b5c8602e35a138657025aba92b30ece37dab989e7b1264b"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"bbb"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"b"}}]}}]} as unknown as DocumentNode;" `); }); @@ -1787,8 +1787,8 @@ export * from "./gql.cjs";`); expect(persistedDocuments.content).toMatchInlineSnapshot(` "{ - "7d0eedabb966107835cf307a0ebaf93b5d2cb8c30228611ffe3d27a53c211a0c": "query A { a }", - "a62a11aa72041e38d8c12ef77e1e7c208d9605db60bb5abb1717e8af98e4b410": "query B { b }" + "sha256:7d0eedabb966107835cf307a0ebaf93b5d2cb8c30228611ffe3d27a53c211a0c": "query A { a }", + "sha256:a62a11aa72041e38d8c12ef77e1e7c208d9605db60bb5abb1717e8af98e4b410": "query B { b }" }" `); @@ -1813,8 +1813,8 @@ export * from "./gql.cjs";`); export type CFragment = { c: string | null } & { ' $fragmentName'?: 'CFragment' }; export const CFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"C"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Query"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"c"}}]}}]} as unknown as DocumentNode; - export const ADocument = {"__meta__":{"hash":"7d0eedabb966107835cf307a0ebaf93b5d2cb8c30228611ffe3d27a53c211a0c"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; - export const BDocument = {"__meta__":{"hash":"a62a11aa72041e38d8c12ef77e1e7c208d9605db60bb5abb1717e8af98e4b410"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"B"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"b"}}]}}]} as unknown as DocumentNode;" + export const ADocument = {"__meta__":{"hash":"sha256:7d0eedabb966107835cf307a0ebaf93b5d2cb8c30228611ffe3d27a53c211a0c"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"A"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"a"}}]}}]} as unknown as DocumentNode; + export const BDocument = {"__meta__":{"hash":"sha256:a62a11aa72041e38d8c12ef77e1e7c208d9605db60bb5abb1717e8af98e4b410"},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"B"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"b"}}]}}]} as unknown as DocumentNode;" `); }); @@ -2304,8 +2304,8 @@ export * from "./gql.cjs";`); export const FooFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]} as unknown as DocumentNode; export const FooFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}}]} as unknown as DocumentNode; export const FooNestedFragmentDoc = {"__meta__":{"deferredFields":{"foo":["id"]}},"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"fooNested"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"FragmentSpread","name":{"kind":"Name","value":"foo"},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}]}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"InlineFragment","typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]}}]} as unknown as DocumentNode; - export const FooDocument = {"__meta__":{"hash":"39c47d2da0fb0e6867abbe2ec942d9858f2d76c7","deferredFields":{"Foo":["value"]}},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Foo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"foo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Foo"},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}]}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]} as unknown as DocumentNode; - export const FoosDocument = {"__meta__":{"hash":"8aba765173b2302b9857334e9959d97a2168dbc8","deferredFields":{"Foo":["value"]}},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Foos"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"foos"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Foo"},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}]}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]} as unknown as DocumentNode;" + export const FooDocument = {"__meta__":{"hash":"sha256:07e5ff4a0a8921816acb51a2e854243b3a43554586f1e0a0d0b53f06126bccb6","deferredFields":{"Foo":["value"]}},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Foo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"foo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Foo"},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}]}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]} as unknown as DocumentNode; + export const FoosDocument = {"__meta__":{"hash":"sha256:f467ac02b2476a740fba9d4fb05ecf4d3660d4d073e3ab45ed274ea65865c30a","deferredFields":{"Foo":["value"]}},"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Foos"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"foos"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Foo"},"directives":[{"kind":"Directive","name":{"kind":"Name","value":"defer"}}]}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Foo"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Foo"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"value"}}]}}]} as unknown as DocumentNode;" `); }); @@ -2561,7 +2561,7 @@ export * from "./gql.cjs";`); ... on Foo @defer { value } - }\`, {"hash":"2687841b00fe0b3b4fd0dfa2e943f80936594f58","deferredFields":{"Foo":["value"]}}) as unknown as TypedDocumentString; + }\`, {"hash":"sha256:7d1874b8f21095f92812369eeb5557f9eff46319f70d6f69a4cb11eba6c3b215","deferredFields":{"Foo":["value"]}}) as unknown as TypedDocumentString; export const FoosDocument = new TypedDocumentString(\` query Foos { foos { @@ -2576,7 +2576,7 @@ export * from "./gql.cjs";`); ... on Foo @defer { value } - }\`, {"hash":"8db613cc1f12f64dbde9cd6fef167fd12246330d","deferredFields":{"Foo":["value"]}}) as unknown as TypedDocumentString;" + }\`, {"hash":"sha256:3daba53c1f6375961bee04d12a5e3528532479e152c01462918f3c11187ba0aa","deferredFields":{"Foo":["value"]}}) as unknown as TypedDocumentString;" `); }); }); diff --git a/website/src/pages/plugins/presets/preset-client.mdx b/website/src/pages/plugins/presets/preset-client.mdx index 145514d4004..4997e3cb63f 100644 --- a/website/src/pages/plugins/presets/preset-client.mdx +++ b/website/src/pages/plugins/presets/preset-client.mdx @@ -548,7 +548,7 @@ console.log(await response.json()) ### Hashing algorithm -To override the default hash algorithm of sha1 set `persistedDocuments.hashAlgorithm` +To override the default hash algorithm of sha256 set `persistedDocuments.hashAlgorithm` ```ts filename="codegen.ts" {10-12} import { type CodegenConfig } from '@graphql-codegen/cli' @@ -561,7 +561,7 @@ const config: CodegenConfig = { preset: 'client', presetConfig: { persistedDocuments: { - hashAlgorithm: 'sha256' + hashAlgorithm: 'sha1' } } } From c564942f6075dda67f70547e48cf552f00111492 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Fri, 27 Mar 2026 22:22:29 +1100 Subject: [PATCH 63/69] [typescript-operations] Add `declarationKind` support (#10654) * typescript-operations: Add support for declarationKind option * Drive-by: add fixme * Add changeset --- .changeset/beige-pets-talk.md | 11 + .../src/base-documents-visitor.ts | 76 ++- .../other/visitor-plugin-common/src/index.ts | 1 + .../src/operation-declaration-kinds.ts | 27 ++ .../operations/src/config.avoidOptionals.ts | 3 + .../typescript/operations/src/visitor.ts | 4 +- ....standalone.config.declarationKind.spec.ts | 441 ++++++++++++++++++ 7 files changed, 555 insertions(+), 8 deletions(-) create mode 100644 .changeset/beige-pets-talk.md create mode 100644 packages/plugins/other/visitor-plugin-common/src/operation-declaration-kinds.ts create mode 100644 packages/plugins/typescript/operations/tests/ts-documents.standalone.config.declarationKind.spec.ts diff --git a/.changeset/beige-pets-talk.md b/.changeset/beige-pets-talk.md new file mode 100644 index 00000000000..0265c6618ff --- /dev/null +++ b/.changeset/beige-pets-talk.md @@ -0,0 +1,11 @@ +--- +'@graphql-codegen/visitor-plugin-common': minor +'@graphql-codegen/typescript-operations': minor +--- + +Add support for declarationKind for typescript-operations + +- Input: can only be `type` or `interface` +- Variables: no support. It must always be `type` because it's an alias e.g. `Variables = Exact<{ something: type }>` +- Result: can only be `type` or `interface` + - Note: when `extractAllFieldsToTypes:true` or `extractAllFieldsToTypesCompact:true`, Results are used as type alias, so they are forced to be `type`. There is a console warning for users. diff --git a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts index b70d716d272..490ffcffbc5 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts @@ -8,6 +8,11 @@ import { VariableDefinitionNode, } from 'graphql'; import { BaseVisitor, type ParsedConfig, type RawConfig } from './base-visitor.js'; +import { + normalizeOperationDeclarationKind, + type OperationDeclarationKind, + type OperationDeclarationKindConfig, +} from './operation-declaration-kinds.js'; import { DEFAULT_INPUT_SCALARS } from './scalars.js'; import { SelectionSetToObject } from './selection-set-to-object.js'; import { CustomDirectivesConfig, NormalizedScalarsMap } from './types.js'; @@ -35,6 +40,7 @@ export interface ParsedDocumentsConfig extends ParsedConfig { generateOperationTypes: boolean; importSchemaTypesFrom: string; namespacedImportName: string | null; + declarationKind: OperationDeclarationKindConfig; } export interface RawDocumentsConfig extends RawConfig { @@ -253,6 +259,52 @@ export interface RawDocumentsConfig extends RawConfig { * When this option is enabled, `extractAllFieldsToTypes` is automatically enabled as well. */ extractAllFieldsToTypesCompact?: boolean; + /** + * @description Overrides the default output for various GraphQL types. + * @default 'type' + * @exampleMarkdown + * ## Override all declarations + * + * ```ts filename="codegen.ts" + * import type { CodegenConfig } from '@graphql-codegen/cli'; + * + * const config: CodegenConfig = { + * // ... + * generates: { + * 'path/to/file': { + * // plugins... + * config: { + * declarationKind: 'interface' + * }, + * }, + * }, + * }; + * export default config; + * ``` + * + * ## Override only specific declarations + * + * ```ts filename="codegen.ts" + * import type { CodegenConfig } from '@graphql-codegen/cli'; + * + * const config: CodegenConfig = { + * // ... + * generates: { + * 'path/to/file': { + * // plugins... + * config: { + * declarationKind: { + * input: 'interface', + * result: 'type' + * } + * }, + * }, + * }, + * }; + * export default config; + * ``` + */ + declarationKind?: OperationDeclarationKind | Partial; } export class BaseDocumentsVisitor< @@ -271,6 +323,19 @@ export class BaseDocumentsVisitor< defaultScalars: NormalizedScalarsMap = DEFAULT_INPUT_SCALARS, ) { const importSchemaTypesFrom = getConfigValue(rawConfig.importSchemaTypesFrom, ''); + const extractAllFieldsToTypes = + getConfigValue(rawConfig.extractAllFieldsToTypes, false) || + getConfigValue(rawConfig.extractAllFieldsToTypesCompact, false); + const declarationKind = normalizeOperationDeclarationKind( + getConfigValue(rawConfig.declarationKind, 'type'), + ); + if (extractAllFieldsToTypes) { + // eslint-disable-next-line no-console + console.warn( + "`declarationKind.result` has been set to `'type'` because `extractAllFieldsToTypes` or `extractAllFieldsToTypesCompact` is true", + ); + declarationKind.result = 'type'; + } super(rawConfig, { exportFragmentSpreadSubTypes: getConfigValue(rawConfig.exportFragmentSpreadSubTypes, false), @@ -289,13 +354,12 @@ export class BaseDocumentsVisitor< rawConfig.namespacedImportName, importSchemaTypesFrom ? 'Types' : null, ), - extractAllFieldsToTypes: - getConfigValue(rawConfig.extractAllFieldsToTypes, false) || - getConfigValue(rawConfig.extractAllFieldsToTypesCompact, false), + extractAllFieldsToTypes, extractAllFieldsToTypesCompact: getConfigValue( rawConfig.extractAllFieldsToTypesCompact, false, ), + declarationKind, ...((additionalConfig || {}) as any), }); @@ -423,7 +487,7 @@ export class BaseDocumentsVisitor< ? '' : new DeclarationBlock(this._declarationBlockConfig) .export() - .asKind('type') + .asKind(this.config.declarationKind.result) .withName(operationResultName) .withContent(selectionSetObjects.mergedTypeString).string; @@ -432,7 +496,7 @@ export class BaseDocumentsVisitor< blockTransformer: t => this.applyVariablesWrapper(t, operationType), }) .export() - .asKind('type') + .asKind('type') // Variables must always be `'type'` because it is an alias of `Exact` .withName( this.convertName(name, { suffix: operationTypeSuffix + 'Variables', @@ -445,7 +509,7 @@ export class BaseDocumentsVisitor< i => new DeclarationBlock(this._declarationBlockConfig) .export() - .asKind('type') + .asKind('type') // dependentTypes must always be `'type'` because they are alias types .withName(i.name) .withContent(i.content).string, ) diff --git a/packages/plugins/other/visitor-plugin-common/src/index.ts b/packages/plugins/other/visitor-plugin-common/src/index.ts index f645aa973c3..ceab9591577 100644 --- a/packages/plugins/other/visitor-plugin-common/src/index.ts +++ b/packages/plugins/other/visitor-plugin-common/src/index.ts @@ -5,6 +5,7 @@ export * from './base-types-visitor.js'; export * from './base-visitor.js'; export * from './client-side-base-visitor.js'; export * from './declaration-kinds.js'; +export * from './operation-declaration-kinds.js'; export * from './enum-values.js'; export * from './imports.js'; export * from './mappers.js'; diff --git a/packages/plugins/other/visitor-plugin-common/src/operation-declaration-kinds.ts b/packages/plugins/other/visitor-plugin-common/src/operation-declaration-kinds.ts new file mode 100644 index 00000000000..75c07a39c2e --- /dev/null +++ b/packages/plugins/other/visitor-plugin-common/src/operation-declaration-kinds.ts @@ -0,0 +1,27 @@ +export type OperationDeclarationKind = 'type' | 'interface'; + +export type OperationDeclarationKindConfig = { + input: OperationDeclarationKind; + result: OperationDeclarationKind; // Query, Mutation, Subscription +}; + +const DEFAULT_OPERATION_DECLARATION_KINDS: OperationDeclarationKindConfig = { + input: 'type', + result: 'type', +}; + +export function normalizeOperationDeclarationKind( + declarationKind: OperationDeclarationKind | Partial +): OperationDeclarationKindConfig { + if (typeof declarationKind === 'string') { + return { + input: declarationKind, + result: declarationKind, + }; + } + + return { + ...DEFAULT_OPERATION_DECLARATION_KINDS, + ...declarationKind, + }; +} diff --git a/packages/plugins/typescript/operations/src/config.avoidOptionals.ts b/packages/plugins/typescript/operations/src/config.avoidOptionals.ts index 256c85c7a55..27bdb6940a2 100644 --- a/packages/plugins/typescript/operations/src/config.avoidOptionals.ts +++ b/packages/plugins/typescript/operations/src/config.avoidOptionals.ts @@ -9,6 +9,9 @@ export interface AvoidOptionalsConfig { } export type NormalizedAvoidOptionalsConfig = Required; +// FIXME: +// 1. bring this to visitor-plugin-common +// 2. param should not be optional export const normalizeAvoidOptionals = ( avoidOptionals?: boolean | AvoidOptionalsConfig ): NormalizedAvoidOptionalsConfig => { diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 620e03029d9..3bdeb2ac469 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -255,7 +255,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< if (isOneOfInputObjectType(this._schema.getType(inputTypeName))) { return new DeclarationBlock(this._declarationBlockConfig) .export() - .asKind('type') + .asKind(this.config.declarationKind.input) .withName(this.convertName(node)) .withComment(node.description?.value) .withContent(`\n` + (node.fields || []).join('\n |')).string; @@ -263,7 +263,7 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< return new DeclarationBlock(this._declarationBlockConfig) .export() - .asKind('type') + .asKind(this.config.declarationKind.input) .withName(this.convertName(node)) .withComment(node.description?.value) .withBlock((node.fields || []).join('\n')).string; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.declarationKind.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.declarationKind.spec.ts new file mode 100644 index 00000000000..2f0475636e9 --- /dev/null +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.declarationKind.spec.ts @@ -0,0 +1,441 @@ +import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; +import { validateTs } from '@graphql-codegen/testing'; +import { buildSchema, parse } from 'graphql'; +import { plugin } from '../src/index.js'; + +const warnSpy = vi.spyOn(console, 'warn'); + +describe('TypeScript Operations Plugin - config.declarationKind', () => { + beforeEach(() => { + warnSpy.mockReset(); + warnSpy.mockImplementation(() => {}); + }); + + it('generates interface for Input and Result when declarationKind:interface', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + } + type Mutation { + updateUser(id: ID!, changes: UpdateUserChangesInput!): User + } + type Subscription { + userUpdates(id: ID!): User + } + + input UpdateUserChangesInput { + name: String + role: UserRole + } + + type User { + id: ID! + name: String! + role: UserRole! + } + + enum UserRole { + ADMIN + CUSTOMER + } + `); + const document = parse(/* GraphQL */ ` + query User($id: ID!) { + user(id: $id) { + id + name + } + } + + mutation UpdateUser($input: UpdateUserChangesInput!) { + updateUser(id: "100", input: $input) { + id + name + } + } + + subscription UserUpdates { + userUpdates(id: "200") { + id + name + } + } + `); + + const result = mergeOutputs([ + await plugin(schema, [{ document }], { declarationKind: 'interface' }, { outputFile: '' }), + ]); + + expect(result).toMatchInlineSnapshot(` + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export interface UpdateUserChangesInput { + name?: string | null | undefined; + role?: UserRole | null | undefined; + } + + export type UserRole = + | 'ADMIN' + | 'CUSTOMER'; + + export type UserQueryVariables = Exact<{ + id: string | number; + }>; + + + export interface UserQuery { user: { id: string, name: string } | null } + + export type UpdateUserMutationVariables = Exact<{ + input: UpdateUserChangesInput; + }>; + + + export interface UpdateUserMutation { updateUser: { id: string, name: string } | null } + + export type UserUpdatesSubscriptionVariables = Exact<{ [key: string]: never; }>; + + + export interface UserUpdatesSubscription { userUpdates: { id: string, name: string } | null } + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('handles partial object option correctly', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + } + type Mutation { + updateUser(id: ID!, changes: UpdateUserChangesInput!): User + } + type Subscription { + userUpdates(id: ID!): User + } + + input UpdateUserChangesInput { + name: String + role: UserRole + } + + type User { + id: ID! + name: String! + role: UserRole! + } + + enum UserRole { + ADMIN + CUSTOMER + } + `); + const document = parse(/* GraphQL */ ` + query User($id: ID!) { + user(id: $id) { + id + name + } + } + + mutation UpdateUser($input: UpdateUserChangesInput!) { + updateUser(id: "100", input: $input) { + id + name + } + } + + subscription UserUpdates { + userUpdates(id: "200") { + id + name + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + declarationKind: { + result: 'interface', // `result` value is `interface`, and `input` value is `type` (default) + }, + }, + { outputFile: '' } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UpdateUserChangesInput = { + name?: string | null | undefined; + role?: UserRole | null | undefined; + }; + + export type UserRole = + | 'ADMIN' + | 'CUSTOMER'; + + export type UserQueryVariables = Exact<{ + id: string | number; + }>; + + + export interface UserQuery { user: { id: string, name: string } | null } + + export type UpdateUserMutationVariables = Exact<{ + input: UpdateUserChangesInput; + }>; + + + export interface UpdateUserMutation { updateUser: { id: string, name: string } | null } + + export type UserUpdatesSubscriptionVariables = Exact<{ [key: string]: never; }>; + + + export interface UserUpdatesSubscription { userUpdates: { id: string, name: string } | null } + " + `); + }); + + it('generates type for Result when declarationKind.result:interface but extractAllFieldsToTypes:true, but warns user', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + } + type Mutation { + updateUser(id: ID!, changes: UpdateUserChangesInput!): User + } + type Subscription { + userUpdates(id: ID!): User + } + + input UpdateUserChangesInput { + name: String + role: UserRole + } + + type User { + id: ID! + name: String! + role: UserRole! + } + + enum UserRole { + ADMIN + CUSTOMER + } + `); + const document = parse(/* GraphQL */ ` + query User($id: ID!) { + user(id: $id) { + id + name + } + } + + mutation UpdateUser($input: UpdateUserChangesInput!) { + updateUser(id: "100", input: $input) { + id + name + } + } + + subscription UserUpdates { + userUpdates(id: "200") { + id + name + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + extractAllFieldsToTypes: true, + declarationKind: 'interface', + }, + { outputFile: '' } + ), + ]); + + expect(warnSpy).toHaveBeenCalledTimes(1); + expect(warnSpy).toHaveBeenNthCalledWith( + 1, + "`declarationKind.result` has been set to `'type'` because `extractAllFieldsToTypes` or `extractAllFieldsToTypesCompact` is true" + ); + + expect(result).toMatchInlineSnapshot(` + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export interface UpdateUserChangesInput { + name?: string | null | undefined; + role?: UserRole | null | undefined; + } + + export type UserRole = + | 'ADMIN' + | 'CUSTOMER'; + + export type UserQuery_user_User = { id: string, name: string }; + + export type UserQuery_Query = { user: UserQuery_user_User | null }; + + + export type UserQueryVariables = Exact<{ + id: string | number; + }>; + + + export type UserQuery = UserQuery_Query; + + export type UpdateUserMutation_updateUser_User = { id: string, name: string }; + + export type UpdateUserMutation_Mutation = { updateUser: UpdateUserMutation_updateUser_User | null }; + + + export type UpdateUserMutationVariables = Exact<{ + input: UpdateUserChangesInput; + }>; + + + export type UpdateUserMutation = UpdateUserMutation_Mutation; + + export type UserUpdatesSubscription_userUpdates_User = { id: string, name: string }; + + export type UserUpdatesSubscription_Subscription = { userUpdates: UserUpdatesSubscription_userUpdates_User | null }; + + + export type UserUpdatesSubscriptionVariables = Exact<{ [key: string]: never; }>; + + + export type UserUpdatesSubscription = UserUpdatesSubscription_Subscription; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('generates type for Result when declarationKind.result:interface and extractAllFieldsToTypesCompact:true, but warns user', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + user(id: ID!): User + } + type Mutation { + updateUser(id: ID!, changes: UpdateUserChangesInput!): User + } + type Subscription { + userUpdates(id: ID!): User + } + + input UpdateUserChangesInput { + name: String + role: UserRole + } + + type User { + id: ID! + name: String! + role: UserRole! + } + + enum UserRole { + ADMIN + CUSTOMER + } + `); + const document = parse(/* GraphQL */ ` + query User($id: ID!) { + user(id: $id) { + id + name + } + } + + mutation UpdateUser($input: UpdateUserChangesInput!) { + updateUser(id: "100", input: $input) { + id + name + } + } + + subscription UserUpdates { + userUpdates(id: "200") { + id + name + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + extractAllFieldsToTypesCompact: true, + declarationKind: 'interface', + }, + { outputFile: '' } + ), + ]); + + expect(warnSpy).toHaveBeenCalledTimes(1); + expect(warnSpy).toHaveBeenNthCalledWith( + 1, + "`declarationKind.result` has been set to `'type'` because `extractAllFieldsToTypes` or `extractAllFieldsToTypesCompact` is true" + ); + + expect(result).toMatchInlineSnapshot(` + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export interface UpdateUserChangesInput { + name?: string | null | undefined; + role?: UserRole | null | undefined; + } + + export type UserRole = + | 'ADMIN' + | 'CUSTOMER'; + + export type UserQuery_user = { id: string, name: string }; + + export type UserQuery = { user: UserQuery_user | null }; + + + export type UserQueryVariables = Exact<{ + id: string | number; + }>; + + export type UpdateUserMutation_updateUser = { id: string, name: string }; + + export type UpdateUserMutation = { updateUser: UpdateUserMutation_updateUser | null }; + + + export type UpdateUserMutationVariables = Exact<{ + input: UpdateUserChangesInput; + }>; + + export type UserUpdatesSubscription_userUpdates = { id: string, name: string }; + + export type UserUpdatesSubscription = { userUpdates: UserUpdatesSubscription_userUpdates | null }; + + + export type UserUpdatesSubscriptionVariables = Exact<{ [key: string]: never; }>; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); +}); From 5894f308d20a414d19b4316b2e25a8aed51ce439 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Fri, 27 Mar 2026 23:50:26 +1100 Subject: [PATCH 64/69] [typesceript-operations] Refactor operations avoidOptionals and declarationKind config (#10655) * move normalizeAvoidOptionals to visitor-plugin-common * Make normalizeOperationDeclarationKind similar to normalizeOperationAvoidOptionals * Fix issue where extractAllFieldsToTypes always causes console to warn * Fix compilation issues --- .../src/base-documents-visitor.ts | 66 ++++++++++++++++++- .../other/visitor-plugin-common/src/index.ts | 3 +- .../src/operation-avoid-optionals.ts | 29 ++++++++ .../src/operation-declaration-kinds.ts | 12 ++-- .../operations/src/config.avoidOptionals.ts | 36 ---------- .../typescript/operations/src/config.ts | 51 -------------- .../src/ts-operation-variables-to-object.ts | 6 +- .../typescript/operations/src/visitor.ts | 2 - ....standalone.config.declarationKind.spec.ts | 4 ++ 9 files changed, 108 insertions(+), 101 deletions(-) create mode 100644 packages/plugins/other/visitor-plugin-common/src/operation-avoid-optionals.ts delete mode 100644 packages/plugins/typescript/operations/src/config.avoidOptionals.ts diff --git a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts index 490ffcffbc5..32e2313bcb5 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-documents-visitor.ts @@ -8,8 +8,14 @@ import { VariableDefinitionNode, } from 'graphql'; import { BaseVisitor, type ParsedConfig, type RawConfig } from './base-visitor.js'; +import { + NormalizedOperationAvoidOptionalsConfig, + normalizeOperationAvoidOptionals, + type OperationAvoidOptionalsConfig, +} from './operation-avoid-optionals.js'; import { normalizeOperationDeclarationKind, + type NormalizedOperationDeclarationKindConfig, type OperationDeclarationKind, type OperationDeclarationKindConfig, } from './operation-declaration-kinds.js'; @@ -40,10 +46,61 @@ export interface ParsedDocumentsConfig extends ParsedConfig { generateOperationTypes: boolean; importSchemaTypesFrom: string; namespacedImportName: string | null; - declarationKind: OperationDeclarationKindConfig; + declarationKind: NormalizedOperationDeclarationKindConfig; + avoidOptionals: NormalizedOperationAvoidOptionalsConfig; } export interface RawDocumentsConfig extends RawConfig { + /** + * @description This will cause the generator to avoid using TypeScript optionals (`?`) on types, + * so the following definition: `type A { myField: String }` will output `myField: Maybe` + * instead of `myField?: Maybe`. + * @default false + * + * @exampleMarkdown + * ## Override all definition types + * + * ```ts filename="codegen.ts" + * import type { CodegenConfig } from '@graphql-codegen/cli'; + * + * const config: CodegenConfig = { + * // ... + * generates: { + * 'path/to/file.ts': { + * plugins: ['typescript-operations'], + * config: { + * avoidOptionals: true + * }, + * }, + * }, + * }; + * export default config; + * ``` + * + * ## Override only specific definition types + * + * ```ts filename="codegen.ts" + * import type { CodegenConfig } from '@graphql-codegen/cli'; + * + * const config: CodegenConfig = { + * // ... + * generates: { + * 'path/to/file.ts': { + * plugins: ['typescript-operations'], + * config: { + * avoidOptionals: { + * variableValue: true, + * inputValue: true, + * defaultValue: true, + * } + * }, + * }, + * }, + * }; + * export default config; + * ``` + */ + avoidOptionals?: boolean | OperationAvoidOptionalsConfig; /** * @default false * @description Avoid adding `__typename` for root types. This is ignored when a selection explicitly specifies `__typename`. @@ -304,7 +361,7 @@ export interface RawDocumentsConfig extends RawConfig { * export default config; * ``` */ - declarationKind?: OperationDeclarationKind | Partial; + declarationKind?: OperationDeclarationKind | OperationDeclarationKindConfig; } export class BaseDocumentsVisitor< @@ -329,7 +386,7 @@ export class BaseDocumentsVisitor< const declarationKind = normalizeOperationDeclarationKind( getConfigValue(rawConfig.declarationKind, 'type'), ); - if (extractAllFieldsToTypes) { + if (extractAllFieldsToTypes && declarationKind.result === 'interface') { // eslint-disable-next-line no-console console.warn( "`declarationKind.result` has been set to `'type'` because `extractAllFieldsToTypes` or `extractAllFieldsToTypesCompact` is true", @@ -338,6 +395,9 @@ export class BaseDocumentsVisitor< } super(rawConfig, { + avoidOptionals: normalizeOperationAvoidOptionals( + getConfigValue(rawConfig.avoidOptionals, false), + ), exportFragmentSpreadSubTypes: getConfigValue(rawConfig.exportFragmentSpreadSubTypes, false), dedupeOperationSuffix: getConfigValue(rawConfig.dedupeOperationSuffix, false), omitOperationSuffix: getConfigValue(rawConfig.omitOperationSuffix, false), diff --git a/packages/plugins/other/visitor-plugin-common/src/index.ts b/packages/plugins/other/visitor-plugin-common/src/index.ts index ceab9591577..b0a07031317 100644 --- a/packages/plugins/other/visitor-plugin-common/src/index.ts +++ b/packages/plugins/other/visitor-plugin-common/src/index.ts @@ -5,11 +5,12 @@ export * from './base-types-visitor.js'; export * from './base-visitor.js'; export * from './client-side-base-visitor.js'; export * from './declaration-kinds.js'; -export * from './operation-declaration-kinds.js'; export * from './enum-values.js'; export * from './imports.js'; export * from './mappers.js'; export * from './naming.js'; +export * from './operation-avoid-optionals.js'; +export * from './operation-declaration-kinds.js'; export * from './optimize-operations.js'; export * from './scalars.js'; export * from './selection-set-processor/base.js'; diff --git a/packages/plugins/other/visitor-plugin-common/src/operation-avoid-optionals.ts b/packages/plugins/other/visitor-plugin-common/src/operation-avoid-optionals.ts new file mode 100644 index 00000000000..cf502c9b44f --- /dev/null +++ b/packages/plugins/other/visitor-plugin-common/src/operation-avoid-optionals.ts @@ -0,0 +1,29 @@ +export interface OperationAvoidOptionalsConfig { + variableValue?: boolean; + inputValue?: boolean; + defaultValue?: boolean; +} +export type NormalizedOperationAvoidOptionalsConfig = Required; + +export const normalizeOperationAvoidOptionals = ( + avoidOptionals: boolean | OperationAvoidOptionalsConfig +): NormalizedOperationAvoidOptionalsConfig => { + const defaultAvoidOptionals: NormalizedOperationAvoidOptionalsConfig = { + variableValue: false, + inputValue: false, + defaultValue: false, + }; + + if (typeof avoidOptionals === 'boolean') { + return { + variableValue: avoidOptionals, + inputValue: avoidOptionals, + defaultValue: avoidOptionals, + }; + } + + return { + ...defaultAvoidOptionals, + ...avoidOptionals, + }; +}; diff --git a/packages/plugins/other/visitor-plugin-common/src/operation-declaration-kinds.ts b/packages/plugins/other/visitor-plugin-common/src/operation-declaration-kinds.ts index 75c07a39c2e..a68a8dffee1 100644 --- a/packages/plugins/other/visitor-plugin-common/src/operation-declaration-kinds.ts +++ b/packages/plugins/other/visitor-plugin-common/src/operation-declaration-kinds.ts @@ -1,18 +1,20 @@ export type OperationDeclarationKind = 'type' | 'interface'; export type OperationDeclarationKindConfig = { - input: OperationDeclarationKind; - result: OperationDeclarationKind; // Query, Mutation, Subscription + input?: OperationDeclarationKind; + result?: OperationDeclarationKind; // Query, Mutation, Subscription }; -const DEFAULT_OPERATION_DECLARATION_KINDS: OperationDeclarationKindConfig = { +export type NormalizedOperationDeclarationKindConfig = Required; + +const DEFAULT_OPERATION_DECLARATION_KINDS: NormalizedOperationDeclarationKindConfig = { input: 'type', result: 'type', }; export function normalizeOperationDeclarationKind( - declarationKind: OperationDeclarationKind | Partial -): OperationDeclarationKindConfig { + declarationKind: OperationDeclarationKind | OperationDeclarationKindConfig +): NormalizedOperationDeclarationKindConfig { if (typeof declarationKind === 'string') { return { input: declarationKind, diff --git a/packages/plugins/typescript/operations/src/config.avoidOptionals.ts b/packages/plugins/typescript/operations/src/config.avoidOptionals.ts deleted file mode 100644 index 27bdb6940a2..00000000000 --- a/packages/plugins/typescript/operations/src/config.avoidOptionals.ts +++ /dev/null @@ -1,36 +0,0 @@ -/** - * This version of AvoidOptionalsConfig is an alternative and cut down version of the type of the same name in `@graphql-codegen/visitor-plugins-common` - * This version only deal with types available in client use cases. - */ -export interface AvoidOptionalsConfig { - variableValue?: boolean; - inputValue?: boolean; - defaultValue?: boolean; -} -export type NormalizedAvoidOptionalsConfig = Required; - -// FIXME: -// 1. bring this to visitor-plugin-common -// 2. param should not be optional -export const normalizeAvoidOptionals = ( - avoidOptionals?: boolean | AvoidOptionalsConfig -): NormalizedAvoidOptionalsConfig => { - const defaultAvoidOptionals: NormalizedAvoidOptionalsConfig = { - variableValue: false, - inputValue: false, - defaultValue: false, - }; - - if (typeof avoidOptionals === 'boolean') { - return { - variableValue: avoidOptionals, - inputValue: avoidOptionals, - defaultValue: avoidOptionals, - }; - } - - return { - ...defaultAvoidOptionals, - ...avoidOptionals, - }; -}; diff --git a/packages/plugins/typescript/operations/src/config.ts b/packages/plugins/typescript/operations/src/config.ts index 482228cd6d9..934be5996e9 100644 --- a/packages/plugins/typescript/operations/src/config.ts +++ b/packages/plugins/typescript/operations/src/config.ts @@ -3,7 +3,6 @@ import { type EnumValuesMap, RawDocumentsConfig, } from '@graphql-codegen/visitor-plugin-common'; -import type { AvoidOptionalsConfig } from './config.avoidOptionals'; /** * @description This plugin generates TypeScript types based on your GraphQLSchema _and_ your GraphQL operations and fragments. @@ -37,56 +36,6 @@ export interface TypeScriptDocumentsPluginConfig extends RawDocumentsConfig { * ``` */ arrayInputCoercion?: boolean; - /** - * @description This will cause the generator to avoid using TypeScript optionals (`?`) on types, - * so the following definition: `type A { myField: String }` will output `myField: Maybe` - * instead of `myField?: Maybe`. - * @default false - * - * @exampleMarkdown - * ## Override all definition types - * - * ```ts filename="codegen.ts" - * import type { CodegenConfig } from '@graphql-codegen/cli'; - * - * const config: CodegenConfig = { - * // ... - * generates: { - * 'path/to/file.ts': { - * plugins: ['typescript-operations'], - * config: { - * avoidOptionals: true - * }, - * }, - * }, - * }; - * export default config; - * ``` - * - * ## Override only specific definition types - * - * ```ts filename="codegen.ts" - * import type { CodegenConfig } from '@graphql-codegen/cli'; - * - * const config: CodegenConfig = { - * // ... - * generates: { - * 'path/to/file.ts': { - * plugins: ['typescript-operations'], - * config: { - * avoidOptionals: { - * variableValue: true, - * inputValue: true, - * defaultValue: true, - * } - * }, - * }, - * }, - * }; - * export default config; - * ``` - */ - avoidOptionals?: boolean | AvoidOptionalsConfig; /** * @description Generates immutable types by adding `readonly` to properties and uses `ReadonlyArray`. * @default false diff --git a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts index d3147b3928f..58decf2307d 100644 --- a/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts +++ b/packages/plugins/typescript/operations/src/ts-operation-variables-to-object.ts @@ -1,18 +1,18 @@ import { Kind, TypeNode } from 'graphql'; import { ConvertNameFn, + DEFAULT_INPUT_SCALARS, NormalizedScalarsMap, OperationVariablesToObject, ParsedEnumValuesMap, printTypeScriptMaybeType, - DEFAULT_INPUT_SCALARS, + type NormalizedOperationAvoidOptionalsConfig, } from '@graphql-codegen/visitor-plugin-common'; -import type { NormalizedAvoidOptionalsConfig } from './config.avoidOptionals'; export class TypeScriptOperationVariablesToObject extends OperationVariablesToObject { constructor( private _config: { - avoidOptionals: NormalizedAvoidOptionalsConfig; + avoidOptionals: NormalizedOperationAvoidOptionalsConfig; immutableTypes: boolean; inputMaybeValue: string; }, diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 3bdeb2ac469..8049609c522 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -55,7 +55,6 @@ import { TypeScriptOperationVariablesToObject } from './ts-operation-variables-t export interface TypeScriptDocumentsParsedConfig extends ParsedDocumentsConfig { arrayInputCoercion: boolean; - avoidOptionals: NormalizedAvoidOptionalsConfig; immutableTypes: boolean; noExport: boolean; maybeValue: string; @@ -98,7 +97,6 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< { arrayInputCoercion: getConfigValue(config.arrayInputCoercion, true), noExport: getConfigValue(config.noExport, false), - avoidOptionals: normalizeAvoidOptionals(getConfigValue(config.avoidOptionals, false)), immutableTypes: getConfigValue(config.immutableTypes, false), nonOptionalTypename: getConfigValue(config.nonOptionalTypename, false), mergeFragmentTypes: getConfigValue(config.mergeFragmentTypes, false), diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.declarationKind.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.declarationKind.spec.ts index 2f0475636e9..fdac7d01680 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.declarationKind.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.declarationKind.spec.ts @@ -100,6 +100,7 @@ describe('TypeScript Operations Plugin - config.declarationKind', () => { export interface UserUpdatesSubscription { userUpdates: { id: string, name: string } | null } " `); + expect(warnSpy).not.toHaveBeenCalled(); validateTs(result, undefined, undefined, undefined, undefined, true); }); @@ -202,6 +203,9 @@ describe('TypeScript Operations Plugin - config.declarationKind', () => { export interface UserUpdatesSubscription { userUpdates: { id: string, name: string } | null } " `); + expect(warnSpy).not.toHaveBeenCalled(); + + validateTs(result, undefined, undefined, undefined, undefined, true); }); it('generates type for Result when declarationKind.result:interface but extractAllFieldsToTypes:true, but warns user', async () => { From 3f7c63eaea079f5a3c1907c130f3cf8d29568f48 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Mon, 30 Mar 2026 23:59:43 +1100 Subject: [PATCH 65/69] [typescript-operations] Fix enumValues not considering namingConvention in certain scenarios (#10656) * Set up test * Refactor naming functions to visitor-plugin-common/naming * Parse EnumValues with applying namingConvention on the schema type and use it for imports * Ensure converted enum type is used across imports, exports and Result * Fix enum-values.spec tests * Update implementation to match expected * Update enumValues tests * Ensure correct naming convention being applied to Input, Variables and Result types * Create a section for enumValues * add changeset --- .changeset/whole-eagles-switch.md | 7 + .../src/base-resolvers-visitor.ts | 18 +- .../src/base-types-visitor.ts | 30 +- ...schema-enum-to-declaration-block-string.ts | 62 +- .../visitor-plugin-common/src/enum-values.ts | 33 +- .../visitor-plugin-common/src/imports.ts | 18 +- .../other/visitor-plugin-common/src/naming.ts | 49 +- .../other/visitor-plugin-common/src/types.ts | 2 + .../other/visitor-plugin-common/src/utils.ts | 19 +- .../src/variables-to-object.ts | 3 +- .../tests/enum-values.spec.ts | 70 +- .../typescript/operations/src/visitor.ts | 34 +- .../ts-documents.standalone.enum.spec.ts | 786 +++++++++++------- .../typescript/typescript/src/visitor.ts | 10 +- 14 files changed, 708 insertions(+), 433 deletions(-) create mode 100644 .changeset/whole-eagles-switch.md diff --git a/.changeset/whole-eagles-switch.md b/.changeset/whole-eagles-switch.md new file mode 100644 index 00000000000..0eb3ed44429 --- /dev/null +++ b/.changeset/whole-eagles-switch.md @@ -0,0 +1,7 @@ +--- +'@graphql-codegen/visitor-plugin-common': patch +'@graphql-codegen/typescript-operations': patch +'@graphql-codegen/typescript': patch +--- + +Fix namingConvention not being applied consistently in imports, Variables, Input and Result diff --git a/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts index 05ac1c49b06..88836d2fe3e 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts @@ -762,10 +762,6 @@ export class BaseResolversVisitor< rawConfig.resolverTypeWrapperSignature, 'Promise | T', ), - enumValues: parseEnumValues({ - schema: _schema, - mapOrStr: rawConfig.enumValues, - }), addUnderscoreToArgsType: getConfigValue(rawConfig.addUnderscoreToArgsType, false), addInterfaceFieldResolverTypes: getConfigValue( rawConfig.addInterfaceFieldResolverTypes, @@ -799,6 +795,20 @@ export class BaseResolversVisitor< ...additionalConfig, } as TPluginConfig); + this.config.enumValues = parseEnumValues({ + schema: _schema, + mapOrStr: rawConfig.enumValues, + naming: { + convert: this.config.convert, + options: { + typesPrefix: this.config.typesPrefix, + typesSuffix: this.config.typesSuffix, + useTypesPrefix: this.config.enumPrefix, + useTypesSuffix: this.config.enumSuffix, + }, + }, + }); + autoBind(this); this._federation = new ApolloFederation({ enabled: this.config.federation, diff --git a/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts index 88497273365..c09973a6721 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts @@ -505,11 +505,6 @@ export class BaseTypesVisitor< onlyEnums: getConfigValue(rawConfig.onlyEnums, false), onlyOperationTypes: getConfigValue(rawConfig.onlyOperationTypes, false), addUnderscoreToArgsType: getConfigValue(rawConfig.addUnderscoreToArgsType, false), - enumValues: parseEnumValues({ - schema: _schema, - mapOrStr: rawConfig.enumValues, - ignoreEnumValuesFromSchema: rawConfig.ignoreEnumValuesFromSchema, - }), ignoreEnumValuesFromSchema: getConfigValue(rawConfig.ignoreEnumValuesFromSchema, false), declarationKind: normalizeDeclarationKind(rawConfig.declarationKind), scalars: buildScalarsFromConfig(_schema, rawConfig, defaultScalars), @@ -526,6 +521,21 @@ export class BaseTypesVisitor< ...additionalConfig, }); + this.config.enumValues = parseEnumValues({ + schema: _schema, + mapOrStr: rawConfig.enumValues, + ignoreEnumValuesFromSchema: this.config.ignoreEnumValuesFromSchema, + naming: { + convert: this.config.convert, + options: { + typesPrefix: this.config.typesPrefix, + typesSuffix: this.config.typesSuffix, + useTypesPrefix: this.config.enumPrefix, + useTypesSuffix: this.config.enumSuffix, + }, + }, + }); + // Note: Missing directive mappers but not a problem since always overriden by implementors this._argumentsTransformer = new OperationVariablesToObject(this.scalars, this.convertName); } @@ -891,10 +901,12 @@ export class BaseTypesVisitor< schema: this._schema, naming: { convert: this.config.convert, - typesPrefix: this.config.typesPrefix, - useTypesPrefix: this.config.enumPrefix, - typesSuffix: this.config.typesSuffix, - useTypesSuffix: this.config.enumSuffix, + options: { + typesPrefix: this.config.typesPrefix, + useTypesPrefix: this.config.enumPrefix, + typesSuffix: this.config.typesSuffix, + useTypesSuffix: this.config.enumSuffix, + }, }, ignoreEnumValuesFromSchema: this.config.ignoreEnumValuesFromSchema, declarationBlockConfig: this._declarationBlockConfig, diff --git a/packages/plugins/other/visitor-plugin-common/src/convert-schema-enum-to-declaration-block-string.ts b/packages/plugins/other/visitor-plugin-common/src/convert-schema-enum-to-declaration-block-string.ts index 30279ebed3a..8c857142469 100644 --- a/packages/plugins/other/visitor-plugin-common/src/convert-schema-enum-to-declaration-block-string.ts +++ b/packages/plugins/other/visitor-plugin-common/src/convert-schema-enum-to-declaration-block-string.ts @@ -8,6 +8,7 @@ import { getNodeComment, wrapWithSingleQuotes, } from './utils.js'; +import { convertName } from './naming.js'; export interface ConvertSchemaEnumToDeclarationBlockString { schema: GraphQLSchema; @@ -18,10 +19,12 @@ export interface ConvertSchemaEnumToDeclarationBlockString { ignoreEnumValuesFromSchema: boolean; naming: { convert: ConvertFn; - typesPrefix: string; - typesSuffix: string; - useTypesPrefix?: boolean; - useTypesSuffix?: boolean; + options: { + typesPrefix: string; + typesSuffix: string; + useTypesPrefix?: boolean; + useTypesSuffix?: boolean; + }; }; outputType: 'string-literal' | 'native-numeric' | 'const' | 'native-const' | 'native'; @@ -40,7 +43,7 @@ export const convertSchemaEnumToDeclarationBlockString = ({ naming, }: ConvertSchemaEnumToDeclarationBlockString): string => { if (enumValues[enumName]?.sourceFile) { - return `export { ${enumValues[enumName].typeIdentifier} };\n`; + return `export { ${enumValues[enumName].typeIdentifierConverted} };\n`; } const getValueFromConfig = (enumValue: string | number) => { @@ -53,13 +56,8 @@ export const convertSchemaEnumToDeclarationBlockString = ({ const withFutureAddedValue = [futureProofEnums ? [indent('| ' + wrapWithSingleQuotes('%future added value'))] : []]; const enumTypeName = convertName({ - options: { - typesPrefix: naming.typesPrefix, - typesSuffix: naming.typesSuffix, - useTypesPrefix: naming.useTypesPrefix, - useTypesSuffix: naming.useTypesSuffix, - }, convert: () => naming.convert(node), + options: naming.options, }); if (outputType === 'string-literal') { @@ -98,8 +96,8 @@ export const convertSchemaEnumToDeclarationBlockString = ({ const optionName = makeValidEnumIdentifier( convertName({ options: { - typesPrefix: naming.typesPrefix, - typesSuffix: naming.typesSuffix, + typesPrefix: naming.options.typesPrefix, + typesSuffix: naming.options.typesSuffix, useTypesPrefix: false, }, convert: () => naming.convert(enumOption, { transformUnderscore: true }), @@ -130,8 +128,8 @@ export const convertSchemaEnumToDeclarationBlockString = ({ const optionName = makeValidEnumIdentifier( convertName({ options: { - typesPrefix: naming.typesPrefix, - typesSuffix: naming.typesPrefix, + typesPrefix: naming.options.typesPrefix, + typesSuffix: naming.options.typesPrefix, }, convert: () => naming.convert(enumOption, { @@ -195,8 +193,8 @@ export const buildEnumValuesBlock = ({ convertName({ options: { useTypesPrefix: false, - typesPrefix: naming.typesPrefix, - typesSuffix: naming.typesSuffix, + typesPrefix: naming.options.typesPrefix, + typesSuffix: naming.options.typesSuffix, }, convert: () => naming.convert(enumOption, { @@ -236,33 +234,3 @@ const makeValidEnumIdentifier = (identifier: string): string => { } return identifier; }; - -const convertName = ({ - convert, - options, -}: { - options: { - typesPrefix: string; - useTypesPrefix?: boolean; - typesSuffix: string; - useTypesSuffix?: boolean; - }; - convert: () => string; -}): string => { - const useTypesPrefix = typeof options.useTypesPrefix === 'boolean' ? options.useTypesPrefix : true; - const useTypesSuffix = typeof options.useTypesSuffix === 'boolean' ? options.useTypesSuffix : true; - - let convertedName = ''; - - if (useTypesPrefix) { - convertedName += options.typesPrefix; - } - - convertedName += convert(); - - if (useTypesSuffix) { - convertedName += options.typesSuffix; - } - - return convertedName; -}; diff --git a/packages/plugins/other/visitor-plugin-common/src/enum-values.ts b/packages/plugins/other/visitor-plugin-common/src/enum-values.ts index 740bf3649ce..de56ab76658 100644 --- a/packages/plugins/other/visitor-plugin-common/src/enum-values.ts +++ b/packages/plugins/other/visitor-plugin-common/src/enum-values.ts @@ -1,6 +1,7 @@ import { GraphQLEnumType, GraphQLSchema, isEnumType } from 'graphql'; import { parseMapper } from './mappers.js'; -import { EnumValuesMap, ParsedEnumValuesMap } from './types.js'; +import type { ConvertFn, EnumValuesMap, ParsedEnumValuesMap } from './types.js'; +import { convertName } from './naming.js'; function escapeString(str: string) { return str.replace(/\\/g, '\\\\').replace(/\n/g, '\\n').replace(/'/g, "\\'"); @@ -10,10 +11,20 @@ export function parseEnumValues({ schema, mapOrStr = {}, ignoreEnumValuesFromSchema, + naming, }: { schema: GraphQLSchema; mapOrStr: EnumValuesMap; ignoreEnumValuesFromSchema?: boolean; + naming: { + convert: ConvertFn; + options: { + typesPrefix: string; + typesSuffix: string; + useTypesPrefix?: boolean; + useTypesSuffix?: boolean; + }; + }; }): ParsedEnumValuesMap { const allTypes = schema.getTypeMap(); const allEnums = Object.keys(allTypes).filter(t => isEnumType(allTypes[t])); @@ -43,7 +54,7 @@ export function parseEnumValues({ ); } - return Object.keys(mapOrStr).reduce((prev, gqlIdentifier) => { + return Object.keys(mapOrStr).reduce((prev, gqlIdentifier) => { const pointer = mapOrStr[gqlIdentifier]; if (typeof pointer === 'string') { @@ -54,6 +65,10 @@ export function parseEnumValues({ [gqlIdentifier]: { isDefault: mapper.isExternal && mapper.default, typeIdentifier: gqlIdentifier, + typeIdentifierConverted: convertName({ + convert: () => naming.convert(gqlIdentifier), + options: naming.options, + }), sourceFile: mapper.isExternal ? mapper.source : null, sourceIdentifier: mapper.type, importIdentifier: mapper.isExternal ? mapper.import : null, @@ -67,6 +82,10 @@ export function parseEnumValues({ [gqlIdentifier]: { isDefault: false, typeIdentifier: gqlIdentifier, + typeIdentifierConverted: convertName({ + convert: () => naming.convert(gqlIdentifier), + options: naming.options, + }), sourceFile: null, sourceIdentifier: null, importIdentifier: null, @@ -78,24 +97,28 @@ export function parseEnumValues({ `Invalid "enumValues" configuration \n Enum "${gqlIdentifier}": expected string or object (with enum values mapping)`, ); - }, {} as ParsedEnumValuesMap); + }, {}); } if (typeof mapOrStr === 'string') { return allEnums .filter(enumName => !enumName.startsWith('__')) - .reduce((prev, enumName) => { + .reduce((prev, enumName) => { return { ...prev, [enumName]: { isDefault: false, typeIdentifier: enumName, + typeIdentifierConverted: convertName({ + convert: () => naming.convert(enumName), + options: naming.options, + }), sourceFile: mapOrStr, sourceIdentifier: enumName, importIdentifier: enumName, mappedValues: null, }, }; - }, {} as ParsedEnumValuesMap); + }, {}); } return {}; diff --git a/packages/plugins/other/visitor-plugin-common/src/imports.ts b/packages/plugins/other/visitor-plugin-common/src/imports.ts index 7ad9247d1fd..2a291cc1998 100644 --- a/packages/plugins/other/visitor-plugin-common/src/imports.ts +++ b/packages/plugins/other/visitor-plugin-common/src/imports.ts @@ -115,13 +115,13 @@ export function getEnumsImports({ useTypeImports: boolean; }): string[] { function handleEnumValueMapper({ - typeIdentifier, + typeIdentifierConverted, importIdentifier, sourceIdentifier, sourceFile, useTypeImports, }: { - typeIdentifier: string; + typeIdentifierConverted: string; importIdentifier: string | null; sourceIdentifier: string | null; sourceFile: string | null; @@ -132,12 +132,16 @@ export function getEnumsImports({ // { enumValues: { MyEnum: './my-file#NS.NestedEnum' } } return [ buildTypeImport({ identifier: importIdentifier || sourceIdentifier, source: sourceFile, useTypeImports }), - `import ${typeIdentifier} = ${sourceIdentifier};`, + `import ${typeIdentifierConverted} = ${sourceIdentifier};`, ]; } - if (sourceIdentifier !== typeIdentifier) { + if (sourceIdentifier !== typeIdentifierConverted) { return [ - buildTypeImport({ identifier: `${sourceIdentifier} as ${typeIdentifier}`, source: sourceFile, useTypeImports }), + buildTypeImport({ + identifier: `${sourceIdentifier} as ${typeIdentifierConverted}`, + source: sourceFile, + useTypeImports, + }), ]; } return [buildTypeImport({ identifier: importIdentifier || sourceIdentifier, source: sourceFile, useTypeImports })]; @@ -150,7 +154,7 @@ export function getEnumsImports({ if (mappedValue.isDefault) { return [ buildTypeImport({ - identifier: mappedValue.typeIdentifier, + identifier: mappedValue.typeIdentifierConverted, source: mappedValue.sourceFile, asDefault: true, useTypeImports, @@ -159,7 +163,7 @@ export function getEnumsImports({ } return handleEnumValueMapper({ - typeIdentifier: mappedValue.typeIdentifier, + typeIdentifierConverted: mappedValue.typeIdentifierConverted, importIdentifier: mappedValue.importIdentifier, sourceIdentifier: mappedValue.sourceIdentifier, sourceFile: mappedValue.sourceFile, diff --git a/packages/plugins/other/visitor-plugin-common/src/naming.ts b/packages/plugins/other/visitor-plugin-common/src/naming.ts index e4cef23c60c..19b053bf217 100644 --- a/packages/plugins/other/visitor-plugin-common/src/naming.ts +++ b/packages/plugins/other/visitor-plugin-common/src/naming.ts @@ -2,7 +2,7 @@ import { pascalCase } from 'change-case-all'; import { ASTNode } from 'graphql'; import { resolveExternalModuleAndFn } from '@graphql-codegen/plugin-helpers'; import { ConvertFn, ConvertOptions, NamingConvention, NamingConventionMap } from './types.js'; -import { convertNameParts, getConfigValue } from './utils.js'; +import { getConfigValue } from './utils.js'; function getKind(node: ASTNode | string): keyof NamingConventionMap { if (typeof node === 'string') { @@ -61,6 +61,21 @@ function getName(node: ASTNode | string): string | undefined { } export function convertFactory(config: { namingConvention?: NamingConvention }): ConvertFn { + function convertNameParts( + str: string, + func: (str: string) => string, + removeUnderscore = false, + ): string { + if (removeUnderscore) { + return func(str); + } + + return str + .split('_') + .map(s => func(s)) + .join('_'); + } + function resolveConventionName( type: keyof NamingConventionMap, ): (str: string, opts?: ConvertOptions) => string { @@ -130,3 +145,35 @@ export function convertFactory(config: { namingConvention?: NamingConvention }): return resolveConventionName(kind)(str, opts); }; } + +export const convertName = ({ + convert, + options, +}: { + options: { + typesPrefix: string; + useTypesPrefix?: boolean; + typesSuffix: string; + useTypesSuffix?: boolean; + }; + convert: () => string; +}): string => { + const useTypesPrefix = + typeof options.useTypesPrefix === 'boolean' ? options.useTypesPrefix : true; + const useTypesSuffix = + typeof options.useTypesSuffix === 'boolean' ? options.useTypesSuffix : true; + + let convertedName = ''; + + if (useTypesPrefix) { + convertedName += options.typesPrefix; + } + + convertedName += convert(); + + if (useTypesSuffix) { + convertedName += options.typesSuffix; + } + + return convertedName; +}; diff --git a/packages/plugins/other/visitor-plugin-common/src/types.ts b/packages/plugins/other/visitor-plugin-common/src/types.ts index e794e091218..3fbef8f050f 100644 --- a/packages/plugins/other/visitor-plugin-common/src/types.ts +++ b/packages/plugins/other/visitor-plugin-common/src/types.ts @@ -53,6 +53,8 @@ export type ParsedEnumValuesMap = { mappedValues?: { [valueName: string]: string | number }; // The GraphQL enum name typeIdentifier: string; + // The GraphQL enum name after namingConvention conversion + typeIdentifierConverted: string; // The actual identifier that you should use in the code (original or aliased) sourceIdentifier?: string; // In case of external enum, this will contain the source file path diff --git a/packages/plugins/other/visitor-plugin-common/src/utils.ts b/packages/plugins/other/visitor-plugin-common/src/utils.ts index c60626e9f12..a3e4f6c2303 100644 --- a/packages/plugins/other/visitor-plugin-common/src/utils.ts +++ b/packages/plugins/other/visitor-plugin-common/src/utils.ts @@ -266,21 +266,6 @@ export function getBaseTypeNode(typeNode: TypeNode): NamedTypeNode { return typeNode; } -export function convertNameParts( - str: string, - func: (str: string) => string, - removeUnderscore = false, -): string { - if (removeUnderscore) { - return func(str); - } - - return str - .split('_') - .map(s => func(s)) - .join('_'); -} - export function buildScalarsFromConfig( schema: GraphQLSchema | undefined, config: RawConfig, @@ -541,7 +526,9 @@ export function hasConditionalDirectives(directives: readonly DirectiveNode[] = /** * Check if any of the directives are incremental i.e. `@defer` */ -export function hasIncrementalDeliveryDirectives(directives: readonly DirectiveNode[] = []): boolean { +export function hasIncrementalDeliveryDirectives( + directives: readonly DirectiveNode[] = [], +): boolean { const INCREMENTAL_DELIVERY_DIRECTIVES = ['defer']; return directives?.some(directive => INCREMENTAL_DELIVERY_DIRECTIVES.includes(directive.name.value), diff --git a/packages/plugins/other/visitor-plugin-common/src/variables-to-object.ts b/packages/plugins/other/visitor-plugin-common/src/variables-to-object.ts index 74b68a0ca7f..ca4b6ee09b3 100644 --- a/packages/plugins/other/visitor-plugin-common/src/variables-to-object.ts +++ b/packages/plugins/other/visitor-plugin-common/src/variables-to-object.ts @@ -109,7 +109,8 @@ export class OperationVariablesToObject { typeValue = this.getScalar(typeName); } else if (this._enumValues[typeName]?.sourceFile) { typeValue = - this._enumValues[typeName].typeIdentifier || this._enumValues[typeName].sourceIdentifier; + this._enumValues[typeName].typeIdentifierConverted || + this._enumValues[typeName].sourceIdentifier; } else { typeValue = `${prefix}${this._convertName(baseType, { useTypesPrefix: this._enumNames.includes(typeName) ? this._enumPrefix : true, diff --git a/packages/plugins/other/visitor-plugin-common/tests/enum-values.spec.ts b/packages/plugins/other/visitor-plugin-common/tests/enum-values.spec.ts index 91aecaf1489..c982666b064 100644 --- a/packages/plugins/other/visitor-plugin-common/tests/enum-values.spec.ts +++ b/packages/plugins/other/visitor-plugin-common/tests/enum-values.spec.ts @@ -1,5 +1,6 @@ import { buildSchema, GraphQLEnumType, GraphQLObjectType, GraphQLSchema } from 'graphql'; import { parseEnumValues } from '../src/enum-values.js'; +import { convertFactory } from '../src/naming.js'; describe('enumValues', () => { const schema = buildSchema(/* GraphQL */ ` @@ -20,12 +21,20 @@ describe('enumValues', () => { mapOrStr: { Test: `my-file#SomeNamespace.ETest`, }, + naming: { + convert: convertFactory({}), + options: { + typesPrefix: '', + typesSuffix: '', + }, + }, }); expect(result).toEqual({ Test: { isDefault: false, typeIdentifier: 'Test', + typeIdentifierConverted: 'Test', sourceFile: 'my-file', sourceIdentifier: 'SomeNamespace.ETest', importIdentifier: 'SomeNamespace', @@ -40,12 +49,20 @@ describe('enumValues', () => { mapOrStr: { Test: `my-file#ETest`, }, + naming: { + convert: convertFactory({}), + options: { + typesPrefix: '', + typesSuffix: '', + }, + }, }); expect(result).toEqual({ Test: { isDefault: false, typeIdentifier: 'Test', + typeIdentifierConverted: 'Test', sourceFile: 'my-file', sourceIdentifier: 'ETest', importIdentifier: 'ETest', @@ -60,12 +77,20 @@ describe('enumValues', () => { mapOrStr: { Test: `my-file#ETest as Something`, }, + naming: { + convert: convertFactory({}), + options: { + typesPrefix: '', + typesSuffix: '', + }, + }, }); expect(result).toEqual({ Test: { isDefault: false, typeIdentifier: 'Test', + typeIdentifierConverted: 'Test', sourceFile: 'my-file', sourceIdentifier: 'Something', importIdentifier: 'ETest as Something', @@ -106,12 +131,20 @@ describe('enumValues', () => { schema: schemaWithEnumValues, mapOrStr: {}, ignoreEnumValuesFromSchema: false, + naming: { + convert: convertFactory({}), + options: { + typesPrefix: '', + typesSuffix: '', + }, + }, }); expect(result).toEqual({ Test: { isDefault: false, typeIdentifier: 'Test', + typeIdentifierConverted: 'Test', sourceFile: null, importIdentifier: null, sourceIdentifier: null, @@ -130,22 +163,16 @@ describe('enumValues', () => { schema: schemaWithEnumValues, mapOrStr: {}, ignoreEnumValuesFromSchema: true, - }); - - expect(result).not.toEqual({ - Test: { - isDefault: false, - typeIdentifier: 'Test', - sourceFile: null, - importIdentifier: null, - sourceIdentifier: null, - mappedValues: { - A: 'a', - B: 'b', - C: 'c', + naming: { + convert: convertFactory({}), + options: { + typesPrefix: '', + typesSuffix: '', }, }, }); + + expect(result).toEqual({}); }); const schemaWithNonStringEnumValues = new GraphQLSchema({ @@ -180,20 +207,27 @@ describe('enumValues', () => { schema: schemaWithNonStringEnumValues, mapOrStr: {}, ignoreEnumValuesFromSchema: false, + naming: { + convert: convertFactory({}), + options: { + typesPrefix: '', + typesSuffix: '', + }, + }, }); - expect(result).not.toEqual({ + expect(result).toEqual({ Test: { isDefault: false, typeIdentifier: 'Test', + typeIdentifierConverted: 'Test', sourceFile: null, importIdentifier: null, sourceIdentifier: null, mappedValues: { - A: '1', - B: 'true', - C: 'null', - D: 'undefined', + A: 1, + B: true, + C: null, }, }, }); diff --git a/packages/plugins/typescript/operations/src/visitor.ts b/packages/plugins/typescript/operations/src/visitor.ts index 8049609c522..9aa3c1005ec 100644 --- a/packages/plugins/typescript/operations/src/visitor.ts +++ b/packages/plugins/typescript/operations/src/visitor.ts @@ -46,10 +46,6 @@ import { type ConvertSchemaEnumToDeclarationBlockString, type ParsedEnumValuesMap, } from '@graphql-codegen/visitor-plugin-common'; -import { - normalizeAvoidOptionals, - NormalizedAvoidOptionalsConfig, -} from './config.avoidOptionals.js'; import type { TypeScriptDocumentsPluginConfig } from './config.js'; import { TypeScriptOperationVariablesToObject } from './ts-operation-variables-to-object.js'; @@ -102,11 +98,6 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< mergeFragmentTypes: getConfigValue(config.mergeFragmentTypes, false), allowUndefinedQueryVariables: getConfigValue(config.allowUndefinedQueryVariables, false), enumType: getConfigValue(config.enumType, 'string-literal'), - enumValues: parseEnumValues({ - schema, - mapOrStr: config.enumValues, - ignoreEnumValuesFromSchema: config.ignoreEnumValuesFromSchema, - }), ignoreEnumValuesFromSchema: getConfigValue(config.ignoreEnumValuesFromSchema, false), futureProofEnums: getConfigValue(config.futureProofEnums, false), maybeValue: getConfigValue(config.maybeValue, 'T | null'), @@ -115,6 +106,21 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< schema, ); + this.config.enumValues = parseEnumValues({ + schema, + mapOrStr: config.enumValues, + ignoreEnumValuesFromSchema: config.ignoreEnumValuesFromSchema, + naming: { + convert: this.config.convert, + options: { + typesPrefix: this.config.typesPrefix, + typesSuffix: this.config.typesSuffix, + useTypesPrefix: this.config.enumPrefix, + useTypesSuffix: this.config.enumSuffix, + }, + }, + }); + this._outputPath = outputPath; autoBind(this); @@ -229,10 +235,12 @@ export class TypeScriptDocumentsVisitor extends BaseDocumentsVisitor< outputType: this.config.enumType, naming: { convert: this.config.convert, - typesPrefix: this.config.typesPrefix, - typesSuffix: this.config.typesSuffix, - useTypesPrefix: this.config.enumPrefix, - useTypesSuffix: this.config.enumSuffix, + options: { + typesPrefix: this.config.typesPrefix, + typesSuffix: this.config.typesSuffix, + useTypesPrefix: this.config.enumPrefix, + useTypesSuffix: this.config.enumSuffix, + }, }, }); } diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts index ed5988f779a..36c469748f5 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts @@ -273,7 +273,7 @@ describe('TypeScript Operations Plugin - Enum', () => { validateTs(result, undefined, undefined, undefined, undefined, true); }); - it('handles `enumValues` with `string-literal` enum', async () => { + it('removes underscore from enum values', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User @@ -295,6 +295,7 @@ describe('TypeScript Operations Plugin - Enum', () => { scalar DateTime `); + const document = parse(/* GraphQL */ ` query Me($role: UserRole!) { me { @@ -303,35 +304,19 @@ describe('TypeScript Operations Plugin - Enum', () => { } `); - const result = mergeOutputs([ - await plugin( - schema, - [{ document }], - { - enumType: 'string-literal', - enumValues: { - UserRole: { - A_B_C: 0, - X_Y_Z: 'Foo', - _TEST: 'Bar', - My_Value: 1, - }, - }, - }, - { outputFile: '' } - ), - ]); + const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' }, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - export type UserRole = - | 0 - | 'Foo' - | 'Bar' - | 1; + export enum UserRole { + ABC = 'A_B_C', + XYZ = 'X_Y_Z', + Test = '_TEST', + MyValue = 'My_Value' + } export type MeQueryVariables = Exact<{ role: UserRole; @@ -345,7 +330,7 @@ describe('TypeScript Operations Plugin - Enum', () => { validateTs(result, undefined, undefined, undefined, undefined, true); }); - it('handles `enumValues` with `const` enum', async () => { + it('keeps underscores in enum values when the value is only underscores', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User @@ -359,14 +344,14 @@ describe('TypeScript Operations Plugin - Enum', () => { } enum UserRole { - A_B_C - X_Y_Z + _ + __ _TEST - My_Value } scalar DateTime `); + const document = parse(/* GraphQL */ ` query Me($role: UserRole!) { me { @@ -375,38 +360,19 @@ describe('TypeScript Operations Plugin - Enum', () => { } `); - const result = mergeOutputs([ - await plugin( - schema, - [{ document }], - { - enumType: 'const', - enumValues: { - UserRole: { - A_B_C: 0, - X_Y_Z: 'Foo', - _TEST: 'Bar', - My_Value: 1, - }, - }, - }, - { outputFile: '' } - ), - ]); + const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' }, { outputFile: '' })]); expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - export const UserRole = { - ABC: 0, - XYZ: 'Foo', - Test: 'Bar', - MyValue: 1 - } as const; + export enum UserRole { + _ = '_', + __ = '__', + Test = '_TEST' + } - export type UserRole = typeof UserRole[keyof typeof UserRole]; export type MeQueryVariables = Exact<{ role: UserRole; }>; @@ -419,7 +385,7 @@ describe('TypeScript Operations Plugin - Enum', () => { validateTs(result, undefined, undefined, undefined, undefined, true); }); - it('handles `enumValues` with `native` enum', async () => { + it('adds typesPrefix to enum when enumPrefix is true', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User @@ -439,6 +405,7 @@ describe('TypeScript Operations Plugin - Enum', () => { scalar DateTime `); + const document = parse(/* GraphQL */ ` query Me($role: UserRole!) { me { @@ -448,45 +415,30 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const result = mergeOutputs([ - await plugin( - schema, - [{ document }], - { - enumType: 'native', - enumValues: { - UserRole: { - ADMIN: 0, - CUSTOMER: 'test', - }, - }, - }, - { outputFile: '' } - ), + await plugin(schema, [{ document }], { typesPrefix: 'I', enumPrefix: true }, { outputFile: '' }), ]); - expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - export enum UserRole { - Admin = 0, - Customer = 'test' - } + export type IUserRole = + | 'ADMIN' + | 'CUSTOMER'; - export type MeQueryVariables = Exact<{ - role: UserRole; + export type IMeQueryVariables = Exact<{ + role: IUserRole; }>; - export type MeQuery = { me: { id: string } | null }; + export type IMeQuery = { me: { id: string } | null }; " `); validateTs(result, undefined, undefined, undefined, undefined, true); }); - it('handles `enumValues` as file import', async () => { + it('does not add typesPrefix to enum when enumPrefix is false', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User @@ -516,39 +468,30 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const result = mergeOutputs([ - await plugin( - schema, - [{ document }], - { - enumValues: { - UserRole: './my-file#MyEnum', - }, - }, - { outputFile: '' } - ), + await plugin(schema, [{ document }], { typesPrefix: 'I', enumPrefix: false }, { outputFile: '' }), ]); - expect(result).toMatchInlineSnapshot(` - "import { MyEnum as UserRole } from './my-file'; - /** Internal type. DO NOT USE DIRECTLY. */ + "/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - export { UserRole }; + export type UserRole = + | 'ADMIN' + | 'CUSTOMER'; - export type MeQueryVariables = Exact<{ + export type IMeQueryVariables = Exact<{ role: UserRole; }>; - export type MeQuery = { me: { id: string } | null }; + export type IMeQuery = { me: { id: string } | null }; " `); validateTs(result, undefined, undefined, undefined, undefined, true); }); - it('does not import or export `enumValues` (as file import) if enum is not used', async () => { + it('adds typesSuffix to enum when enumSuffix is true', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User @@ -570,7 +513,7 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const document = parse(/* GraphQL */ ` - query { + query Me($role: UserRole!) { me { id } @@ -578,34 +521,30 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const result = mergeOutputs([ - await plugin( - schema, - [{ document }], - { - enumValues: { - UserRole: './my-file#MyEnum', - }, - }, - { outputFile: '' } - ), + await plugin(schema, [{ document }], { typesSuffix: 'Z', enumSuffix: true }, { outputFile: '' }), ]); - expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; + export type UserRoleZ = + | 'ADMIN' + | 'CUSTOMER'; + + export type MeQueryVariablesZ = Exact<{ + role: UserRoleZ; + }>; - export type Unnamed_1_Query = { me: { id: string } | null }; + export type MeQueryZ = { me: { id: string } | null }; " `); validateTs(result, undefined, undefined, undefined, undefined, true); }); - it('handles `enumValues` with custom imported enum from namespace with different name', async () => { + it('does not add typesSuffix to enum when enumSuffix is false', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User @@ -635,40 +574,30 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const result = mergeOutputs([ - await plugin( - schema, - [{ document }], - { - enumValues: { - UserRole: './my-file#NS.ETest', - }, - }, - { outputFile: '' } - ), + await plugin(schema, [{ document }], { typesSuffix: 'Z', enumSuffix: false }, { outputFile: '' }), ]); - expect(result).toMatchInlineSnapshot(` - "import { NS } from './my-file'; - import UserRole = NS.ETest; - /** Internal type. DO NOT USE DIRECTLY. */ + "/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - export { UserRole }; + export type UserRole = + | 'ADMIN' + | 'CUSTOMER'; - export type MeQueryVariables = Exact<{ + export type MeQueryVariablesZ = Exact<{ role: UserRole; }>; - export type MeQuery = { me: { id: string } | null }; + export type MeQueryZ = { me: { id: string } | null }; " `); validateTs(result, undefined, undefined, undefined, undefined, true); }); - it('handles `enumValues` with custom imported enum from namespace with the same name', async () => { + it('keeps enum value naming convention when namingConvention.enumValues is `keep`', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User @@ -681,6 +610,10 @@ describe('TypeScript Operations Plugin - Enum', () => { createdAt: DateTime! } + input UserRoleInput { + role: UserRole! + } + enum UserRole { ADMIN CUSTOMER @@ -690,9 +623,10 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const document = parse(/* GraphQL */ ` - query Me($role: UserRole!) { + query Me($input: UserRoleInput!, $role: UserRole!) { me { id + role } } `); @@ -702,36 +636,41 @@ describe('TypeScript Operations Plugin - Enum', () => { schema, [{ document }], { - enumValues: { - UserRole: './my-file#NS.UserRole', + namingConvention: { + typeNames: 'change-case-all#lowerCase', + enumValues: 'keep', }, }, { outputFile: '' } ), ]); - expect(result).toMatchInlineSnapshot(` - "import { NS } from './my-file'; - import UserRole = NS.UserRole; - /** Internal type. DO NOT USE DIRECTLY. */ + "/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - export { UserRole }; + export type userroleinput = { + role: userrole; + }; - export type MeQueryVariables = Exact<{ - role: UserRole; + export type userrole = + | 'ADMIN' + | 'CUSTOMER'; + + export type mequeryvariables = Exact<{ + input: userroleinput; + role: userrole; }>; - export type MeQuery = { me: { id: string } | null }; + export type mequery = { me: { id: string, role: userrole } | null }; " `); validateTs(result, undefined, undefined, undefined, undefined, true); }); - it('handles `enumValues` from a single file', async () => { + it('uses custom enum naming convention when namingConvention.enumValues is provided and enumType is native', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User @@ -744,23 +683,23 @@ describe('TypeScript Operations Plugin - Enum', () => { createdAt: DateTime! } + input UserRoleInput { + role: UserRole! + } + enum UserRole { ADMIN CUSTOMER } - enum UserStatus { - ACTIVE - PENDING - } - scalar DateTime `); const document = parse(/* GraphQL */ ` - query Me($role: UserRole!, $status: UserStatus!) { + query Me($input: UserRoleInput!, $role: UserRole!) { me { id + role } } `); @@ -771,37 +710,42 @@ describe('TypeScript Operations Plugin - Enum', () => { [{ document }], { enumType: 'native', - enumValues: './my-file', + namingConvention: { + typeNames: 'keep', + enumValues: 'change-case-all#lowerCase', + }, }, { outputFile: '' } ), ]); - expect(result).toMatchInlineSnapshot(` - "import { UserRole } from './my-file'; - import { UserStatus } from './my-file'; - /** Internal type. DO NOT USE DIRECTLY. */ + "/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - export { UserRole }; + export type UserRoleInput = { + role: UserRole; + }; - export { UserStatus }; + export enum UserRole { + admin = 'ADMIN', + customer = 'CUSTOMER' + } export type MeQueryVariables = Exact<{ + input: UserRoleInput; role: UserRole; - status: UserStatus; }>; - export type MeQuery = { me: { id: string } | null }; + export type MeQuery = { me: { id: string, role: UserRole } | null }; " `); validateTs(result, undefined, undefined, undefined, undefined, true); }); - it('handles `enumValues` from a single file when specified as string', async () => { + it('does not contain "export" when noExport is set to true', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User @@ -819,16 +763,11 @@ describe('TypeScript Operations Plugin - Enum', () => { CUSTOMER } - enum UserStatus { - ACTIVE - PENDING - } - scalar DateTime `); const document = parse(/* GraphQL */ ` - query Me($role: UserRole!, $status: UserStatus!) { + query Me($role: UserRole!) { me { id } @@ -840,43 +779,42 @@ describe('TypeScript Operations Plugin - Enum', () => { schema, [{ document }], { - enumType: 'native', - enumValues: { UserRole: './my-file#UserRole', UserStatus: './my-file#UserStatus2X' }, + noExport: true, }, { outputFile: '' } ), ]); - expect(result).toMatchInlineSnapshot(` - "import { UserRole } from './my-file'; - import { UserStatus2X as UserStatus } from './my-file'; - /** Internal type. DO NOT USE DIRECTLY. */ + "/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - export { UserRole }; - - export { UserStatus }; + type UserRole = + | 'ADMIN' + | 'CUSTOMER'; - export type MeQueryVariables = Exact<{ + type MeQueryVariables = Exact<{ role: UserRole; - status: UserStatus; }>; - export type MeQuery = { me: { id: string } | null }; + type MeQuery = { me: { id: string } | null }; " `); validateTs(result, undefined, undefined, undefined, undefined, true); }); - it('removes underscore from enum values', async () => { + it('handles enumValues and named default import', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User } + input UserRoleInput { + role: UserRole! + } + type User { id: ID! name: String! @@ -885,50 +823,63 @@ describe('TypeScript Operations Plugin - Enum', () => { } enum UserRole { - A_B_C - X_Y_Z - _TEST - My_Value + ADMIN + CUSTOMER } scalar DateTime `); const document = parse(/* GraphQL */ ` - query Me($role: UserRole!) { + query Me($input: UserRoleInput!, $role: UserRole!) { me { id + role } } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' }, { outputFile: '' })]); + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + typesPrefix: 'I', + namingConvention: { enumValues: 'change-case-all#constantCase' }, + enumValues: { + UserRole: './files#default as IUserRole', + }, + }, + { outputFile: '' } + ), + ]); expect(result).toMatchInlineSnapshot(` - "/** Internal type. DO NOT USE DIRECTLY. */ + "import IUserRole from './files'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - export enum UserRole { - ABC = 'A_B_C', - XYZ = 'X_Y_Z', - Test = '_TEST', - MyValue = 'My_Value' - } + export type IUserRoleInput = { + role: IUserRole; + }; - export type MeQueryVariables = Exact<{ - role: UserRole; + export { IUserRole }; + + export type IMeQueryVariables = Exact<{ + input: IUserRoleInput; + role: IUserRole; }>; - export type MeQuery = { me: { id: string } | null }; + export type IMeQuery = { me: { id: string, role: IUserRole } | null }; " `); validateTs(result, undefined, undefined, undefined, undefined, true); }); - it('keeps underscores in enum values when the value is only underscores', async () => { + it('enum members should be quoted if numeric when enumType is native', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User @@ -942,9 +893,9 @@ describe('TypeScript Operations Plugin - Enum', () => { } enum UserRole { - _ - __ - _TEST + AXB + _1X2 + _3X4 } scalar DateTime @@ -966,9 +917,9 @@ describe('TypeScript Operations Plugin - Enum', () => { /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; export enum UserRole { - _ = '_', - __ = '__', - Test = '_TEST' + Axb = 'AXB', + '1X2' = '_1X2', + '3X4' = '_3X4' } export type MeQueryVariables = Exact<{ @@ -979,11 +930,11 @@ describe('TypeScript Operations Plugin - Enum', () => { export type MeQuery = { me: { id: string } | null }; " `); - - validateTs(result, undefined, undefined, undefined, undefined, true); }); +}); - it('adds typesPrefix to enum when enumPrefix is true', async () => { +describe('TypeScript Operations Plugin - Enum `%future added value`', () => { + it('adds `%future added value` to the type when enumType is `string-literal` and futureProofEnums is true', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User @@ -1003,7 +954,6 @@ describe('TypeScript Operations Plugin - Enum', () => { scalar DateTime `); - const document = parse(/* GraphQL */ ` query Me($role: UserRole!) { me { @@ -1012,31 +962,33 @@ describe('TypeScript Operations Plugin - Enum', () => { } `); - const result = mergeOutputs([ - await plugin(schema, [{ document }], { typesPrefix: 'I', enumPrefix: true }, { outputFile: '' }), - ]); + const result = mergeOutputs([await plugin(schema, [{ document }], { futureProofEnums: true }, { outputFile: '' })]); + expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - export type IUserRole = + export type UserRole = | 'ADMIN' - | 'CUSTOMER'; + | 'CUSTOMER' + | '%future added value'; - export type IMeQueryVariables = Exact<{ - role: IUserRole; + export type MeQueryVariables = Exact<{ + role: UserRole; }>; - export type IMeQuery = { me: { id: string } | null }; + export type MeQuery = { me: { id: string } | null }; " `); validateTs(result, undefined, undefined, undefined, undefined, true); }); +}); - it('does not add typesPrefix to enum when enumPrefix is false', async () => { +describe('TypeScript Operations Plugin - Enum enumValues', () => { + it('handles `enumValues` with `string-literal` enum', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User @@ -1049,47 +1001,76 @@ describe('TypeScript Operations Plugin - Enum', () => { createdAt: DateTime! } + input UserRoleInput { + role: UserRole! + } + enum UserRole { - ADMIN - CUSTOMER + A_B_C + X_Y_Z + _TEST + My_Value } scalar DateTime `); - const document = parse(/* GraphQL */ ` - query Me($role: UserRole!) { + query Me($input: UserRoleInput!, $role: UserRole!) { me { id + role } } `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { typesPrefix: 'I', enumPrefix: false }, { outputFile: '' }), + await plugin( + schema, + [{ document }], + { + enumType: 'string-literal', + enumValues: { + UserRole: { + A_B_C: 0, + X_Y_Z: 'Foo', + _TEST: 'Bar', + My_Value: 1, + }, + }, + }, + { outputFile: '' } + ), ]); + expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserRoleInput = { + role: UserRole; + }; + export type UserRole = - | 'ADMIN' - | 'CUSTOMER'; + | 0 + | 'Foo' + | 'Bar' + | 1; - export type IMeQueryVariables = Exact<{ + export type MeQueryVariables = Exact<{ + input: UserRoleInput; role: UserRole; }>; - export type IMeQuery = { me: { id: string } | null }; + export type MeQuery = { me: { id: string, role: UserRole } | null }; " `); validateTs(result, undefined, undefined, undefined, undefined, true); }); - it('adds typesSuffix to enum when enumSuffix is true', async () => { + it('handles `enumValues` with `const` enum', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User @@ -1102,47 +1083,78 @@ describe('TypeScript Operations Plugin - Enum', () => { createdAt: DateTime! } + input UserRoleInput { + role: UserRole! + } + enum UserRole { - ADMIN - CUSTOMER + A_B_C + X_Y_Z + _TEST + My_Value } scalar DateTime `); - const document = parse(/* GraphQL */ ` - query Me($role: UserRole!) { + query Me($input: UserRoleInput!, $role: UserRole!) { me { id + role } } `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { typesSuffix: 'Z', enumSuffix: true }, { outputFile: '' }), + await plugin( + schema, + [{ document }], + { + enumType: 'const', + enumValues: { + UserRole: { + A_B_C: 0, + X_Y_Z: 'Foo', + _TEST: 'Bar', + My_Value: 1, + }, + }, + }, + { outputFile: '' } + ), ]); + expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - export type UserRoleZ = - | 'ADMIN' - | 'CUSTOMER'; + export type UserRoleInput = { + role: UserRole; + }; - export type MeQueryVariablesZ = Exact<{ - role: UserRoleZ; + export const UserRole = { + ABC: 0, + XYZ: 'Foo', + Test: 'Bar', + MyValue: 1 + } as const; + + export type UserRole = typeof UserRole[keyof typeof UserRole]; + export type MeQueryVariables = Exact<{ + input: UserRoleInput; + role: UserRole; }>; - export type MeQueryZ = { me: { id: string } | null }; + export type MeQuery = { me: { id: string, role: UserRole } | null }; " `); validateTs(result, undefined, undefined, undefined, undefined, true); }); - it('does not add typesSuffix to enum when enumSuffix is false', async () => { + it('handles `enumValues` with `native` enum', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User @@ -1155,6 +1167,10 @@ describe('TypeScript Operations Plugin - Enum', () => { createdAt: DateTime! } + input UserRoleInput { + role: UserRole! + } + enum UserRole { ADMIN CUSTOMER @@ -1162,40 +1178,60 @@ describe('TypeScript Operations Plugin - Enum', () => { scalar DateTime `); - const document = parse(/* GraphQL */ ` - query Me($role: UserRole!) { + query Me($input: UserRoleInput!, $role: UserRole!) { me { id + role } } `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { typesSuffix: 'Z', enumSuffix: false }, { outputFile: '' }), + await plugin( + schema, + [{ document }], + { + enumType: 'native', + enumValues: { + UserRole: { + ADMIN: 0, + CUSTOMER: 'test', + }, + }, + }, + { outputFile: '' } + ), ]); + expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - export type UserRole = - | 'ADMIN' - | 'CUSTOMER'; + export type UserRoleInput = { + role: UserRole; + }; - export type MeQueryVariablesZ = Exact<{ + export enum UserRole { + Admin = 0, + Customer = 'test' + } + + export type MeQueryVariables = Exact<{ + input: UserRoleInput; role: UserRole; }>; - export type MeQueryZ = { me: { id: string } | null }; + export type MeQuery = { me: { id: string, role: UserRole } | null }; " `); validateTs(result, undefined, undefined, undefined, undefined, true); }); - it('keeps enum value naming convention when namingConvention.enumValues is `keep`', async () => { + it('handles `enumValues` as file import', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User @@ -1208,6 +1244,10 @@ describe('TypeScript Operations Plugin - Enum', () => { createdAt: DateTime! } + input UserRoleInput { + role: UserRole! + } + enum UserRole { ADMIN CUSTOMER @@ -1217,9 +1257,10 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const document = parse(/* GraphQL */ ` - query Me($role: UserRole!) { + query Me($input: UserRoleInput!, $role: UserRole!) { me { id + role } } `); @@ -1229,36 +1270,40 @@ describe('TypeScript Operations Plugin - Enum', () => { schema, [{ document }], { - namingConvention: { - typeNames: 'change-case-all#lowerCase', - enumValues: 'keep', + enumValues: { + UserRole: './my-file#MyEnum', }, }, { outputFile: '' } ), ]); + expect(result).toMatchInlineSnapshot(` - "/** Internal type. DO NOT USE DIRECTLY. */ + "import { MyEnum as UserRole } from './my-file'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - export type userrole = - | 'ADMIN' - | 'CUSTOMER'; + export type UserRoleInput = { + role: UserRole; + }; - export type mequeryvariables = Exact<{ - role: userrole; + export { UserRole }; + + export type MeQueryVariables = Exact<{ + input: UserRoleInput; + role: UserRole; }>; - export type mequery = { me: { id: string } | null }; + export type MeQuery = { me: { id: string, role: UserRole } | null }; " `); validateTs(result, undefined, undefined, undefined, undefined, true); }); - it('uses custom enum naming convention when namingConvention.enumValues is provided and enumType is native', async () => { + it('does not import or export `enumValues` (as file import) if enum is not used', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User @@ -1280,7 +1325,7 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const document = parse(/* GraphQL */ ` - query Me($role: UserRole!) { + query { me { id } @@ -1292,38 +1337,30 @@ describe('TypeScript Operations Plugin - Enum', () => { schema, [{ document }], { - enumType: 'native', - namingConvention: { - typeNames: 'keep', - enumValues: 'change-case-all#lowerCase', + enumValues: { + UserRole: './my-file#MyEnum', }, }, { outputFile: '' } ), ]); + expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - export enum UserRole { - admin = 'ADMIN', - customer = 'CUSTOMER' - } - - export type MeQueryVariables = Exact<{ - role: UserRole; - }>; + export type Unnamed_1_QueryVariables = Exact<{ [key: string]: never; }>; - export type MeQuery = { me: { id: string } | null }; + export type Unnamed_1_Query = { me: { id: string } | null }; " `); validateTs(result, undefined, undefined, undefined, undefined, true); }); - it('does not contain "export" when noExport is set to true', async () => { + it('handles `enumValues` with custom imported enum from namespace with different name', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User @@ -1336,6 +1373,10 @@ describe('TypeScript Operations Plugin - Enum', () => { createdAt: DateTime! } + input UserRoleInput { + role: UserRole! + } + enum UserRole { ADMIN CUSTOMER @@ -1345,9 +1386,10 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const document = parse(/* GraphQL */ ` - query Me($role: UserRole!) { + query Me($input: UserRoleInput!, $role: UserRole!) { me { id + role } } `); @@ -1357,33 +1399,41 @@ describe('TypeScript Operations Plugin - Enum', () => { schema, [{ document }], { - noExport: true, + enumValues: { + UserRole: './my-file#NS.ETest', + }, }, { outputFile: '' } ), ]); + expect(result).toMatchInlineSnapshot(` - "/** Internal type. DO NOT USE DIRECTLY. */ + "import { NS } from './my-file'; + import UserRole = NS.ETest; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - type UserRole = - | 'ADMIN' - | 'CUSTOMER'; + export type UserRoleInput = { + role: UserRole; + }; - type MeQueryVariables = Exact<{ + export { UserRole }; + + export type MeQueryVariables = Exact<{ + input: UserRoleInput; role: UserRole; }>; - type MeQuery = { me: { id: string } | null }; + export type MeQuery = { me: { id: string, role: UserRole } | null }; " `); validateTs(result, undefined, undefined, undefined, undefined, true); }); - it('handles enumValues and named default import', async () => { + it('handles `enumValues` with custom imported enum from namespace with the same name', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User @@ -1396,6 +1446,10 @@ describe('TypeScript Operations Plugin - Enum', () => { createdAt: DateTime! } + input UserRoleInput { + role: UserRole! + } + enum UserRole { ADMIN CUSTOMER @@ -1405,9 +1459,10 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const document = parse(/* GraphQL */ ` - query Me($role: UserRole!) { + query Me($input: UserRoleInput!, $role: UserRole!) { me { id + role } } `); @@ -1417,10 +1472,8 @@ describe('TypeScript Operations Plugin - Enum', () => { schema, [{ document }], { - typesPrefix: 'I', - namingConvention: { enumValues: 'change-case-all#constantCase' }, enumValues: { - UserRole: './files#default as UserRole', + UserRole: './my-file#NS.UserRole', }, }, { outputFile: '' } @@ -1428,24 +1481,32 @@ describe('TypeScript Operations Plugin - Enum', () => { ]); expect(result).toMatchInlineSnapshot(` - "import UserRole from './files'; + "import { NS } from './my-file'; + import UserRole = NS.UserRole; /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserRoleInput = { + role: UserRole; + }; + export { UserRole }; - export type IMeQueryVariables = Exact<{ + export type MeQueryVariables = Exact<{ + input: UserRoleInput; role: UserRole; }>; - export type IMeQuery = { me: { id: string } | null }; + export type MeQuery = { me: { id: string, role: UserRole } | null }; " `); + + validateTs(result, undefined, undefined, undefined, undefined, true); }); - it('enum members should be quoted if numeric when enumType is native', async () => { + it('handles `enumValues` from a single file', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User @@ -1458,49 +1519,74 @@ describe('TypeScript Operations Plugin - Enum', () => { createdAt: DateTime! } + input UserRoleInput { + role: UserRole! + } + enum UserRole { - AXB - _1X2 - _3X4 + ADMIN + CUSTOMER + } + + enum UserStatus { + ACTIVE + PENDING } scalar DateTime `); const document = parse(/* GraphQL */ ` - query Me($role: UserRole!) { + query Me($input: UserRoleInput!, $role: UserRole!, $status: UserStatus!) { me { id + role } } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' }, { outputFile: '' })]); + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + enumType: 'native', + enumValues: './my-file', + }, + { outputFile: '' } + ), + ]); expect(result).toMatchInlineSnapshot(` - "/** Internal type. DO NOT USE DIRECTLY. */ + "import { UserRole } from './my-file'; + import { UserStatus } from './my-file'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - export enum UserRole { - Axb = 'AXB', - '1X2' = '_1X2', - '3X4' = '_3X4' - } + export type UserRoleInput = { + role: UserRole; + }; + + export { UserRole }; + + export { UserStatus }; export type MeQueryVariables = Exact<{ + input: UserRoleInput; role: UserRole; + status: UserStatus; }>; - export type MeQuery = { me: { id: string } | null }; + export type MeQuery = { me: { id: string, role: UserRole } | null }; " `); + + validateTs(result, undefined, undefined, undefined, undefined, true); }); -}); -describe('TypeScript Operations Plugin - Enum `%future added value`', () => { - it('adds `%future added value` to the type when enumType is `string-literal` and futureProofEnums is true', async () => { + it('handles `enumValues` from a single file when specified as string', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { me: User @@ -1513,39 +1599,123 @@ describe('TypeScript Operations Plugin - Enum `%future added value`', () => { createdAt: DateTime! } + input UserRoleInput { + role: UserRole! + } + enum UserRole { ADMIN CUSTOMER } + enum UserStatus { + ACTIVE + PENDING + } + scalar DateTime `); + const document = parse(/* GraphQL */ ` - query Me($role: UserRole!) { + query Me($input: UserRoleInput!, $role: UserRole!, $status: UserStatus!) { me { id + role } } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { futureProofEnums: true }, { outputFile: '' })]); + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + enumType: 'native', + enumValues: { UserRole: './my-file#UserRole', UserStatus: './my-file#UserStatus2X' }, + }, + { outputFile: '' } + ), + ]); expect(result).toMatchInlineSnapshot(` - "/** Internal type. DO NOT USE DIRECTLY. */ + "import { UserRole } from './my-file'; + import { UserStatus2X as UserStatus } from './my-file'; + /** Internal type. DO NOT USE DIRECTLY. */ type Exact = { [K in keyof T]: T[K] }; /** Internal type. DO NOT USE DIRECTLY. */ export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; - export type UserRole = - | 'ADMIN' - | 'CUSTOMER' - | '%future added value'; + export type UserRoleInput = { + role: UserRole; + }; + + export { UserRole }; + + export { UserStatus }; export type MeQueryVariables = Exact<{ + input: UserRoleInput; role: UserRole; + status: UserStatus; }>; - export type MeQuery = { me: { id: string } | null }; + export type MeQuery = { me: { id: string, role: UserRole } | null }; + " + `); + + validateTs(result, undefined, undefined, undefined, undefined, true); + }); + + it('#10471 - `enumValues` as named import from file must consider naming convention', async () => { + const schema = buildSchema(/* GraphQL */ ` + type Query { + license: License + } + + type License { + id: ID! + sku: LicenseSKU! + } + + enum LicenseSKU { + BASIC + ADVANCED + } + `); + + const document = parse(/* GraphQL */ ` + query License { + license { + sku + } + } + `); + + const result = mergeOutputs([ + await plugin( + schema, + [{ document }], + { + enumValues: { + LicenseSKU: './my-file#LicenseSku', + }, + }, + { outputFile: '' } + ), + ]); + + expect(result).toMatchInlineSnapshot(` + "import { LicenseSku } from './my-file'; + /** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export { LicenseSku }; + + export type LicenseQueryVariables = Exact<{ [key: string]: never; }>; + + + export type LicenseQuery = { license: { sku: LicenseSku } | null }; " `); diff --git a/packages/plugins/typescript/typescript/src/visitor.ts b/packages/plugins/typescript/typescript/src/visitor.ts index ca7a288bbfd..06b7e6fba7e 100644 --- a/packages/plugins/typescript/typescript/src/visitor.ts +++ b/packages/plugins/typescript/typescript/src/visitor.ts @@ -369,10 +369,12 @@ export class TsVisitor< outputType, naming: { convert: this.config.convert, - typesPrefix: this.config.typesPrefix, - typesSuffix: this.config.typesSuffix, - useTypesPrefix: this.config.enumPrefix, - useTypesSuffix: this.config.enumSuffix, + options: { + typesPrefix: this.config.typesPrefix, + typesSuffix: this.config.typesSuffix, + useTypesPrefix: this.config.enumPrefix, + useTypesSuffix: this.config.enumSuffix, + }, }, }); } From 7aed107788d15ef2a04c40291da32944fdae7888 Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Wed, 1 Apr 2026 00:08:53 +1100 Subject: [PATCH 66/69] [typescript][typescript-resolvers] Fix enumValues not considering namingConvention in certain scenarios (2) (#10657) * Ensure enumValues is consistent in typescript and typescript-resolvers * Add a note to default alias import not doing anything * Add changeset --- .changeset/tasty-waves-trade.md | 7 +++++++ .../src/base-resolvers-visitor.ts | 7 ++----- .../src/base-types-visitor.ts | 2 +- .../ts-documents.standalone.enum.spec.ts | 2 +- .../resolvers/tests/ts-resolvers.spec.ts | 7 +++++-- .../typescript/tests/typescript.spec.ts | 19 +++++++++++++------ 6 files changed, 29 insertions(+), 15 deletions(-) create mode 100644 .changeset/tasty-waves-trade.md diff --git a/.changeset/tasty-waves-trade.md b/.changeset/tasty-waves-trade.md new file mode 100644 index 00000000000..4a7facf07e3 --- /dev/null +++ b/.changeset/tasty-waves-trade.md @@ -0,0 +1,7 @@ +--- +'@graphql-codegen/visitor-plugin-common': patch +'@graphql-codegen/typescript': patch +'@graphql-codegen/typescript-resolvers': patch +--- + +Fix namingConvention not being applied consistently diff --git a/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts index 88836d2fe3e..f39d58b0e04 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-resolvers-visitor.ts @@ -975,10 +975,7 @@ export class BaseResolversVisitor< if (isEnumType(schemaType) && this.config.enumValues[typeName]) { const isExternalFile = !!this.config.enumValues[typeName].sourceFile; prev[typeName] = isExternalFile - ? this.convertName(this.config.enumValues[typeName].typeIdentifier, { - useTypesPrefix: false, - useTypesSuffix: false, - }) + ? this.config.enumValues[typeName].typeIdentifierConverted : this.config.enumValues[typeName].sourceIdentifier; } else if (hasDefaultMapper && !hasPlaceholder(this.config.defaultMapper.type)) { prev[typeName] = applyWrapper(this.config.defaultMapper.type); @@ -1436,7 +1433,7 @@ export class BaseResolversVisitor< : false; const existsFromEnums = !!Object.keys(this.config.enumValues) .map(key => this.config.enumValues[key]) - .find(o => o.sourceFile === source && o.typeIdentifier === identifier); + .find(o => o.sourceFile === source && o.typeIdentifierConverted === identifier); return exists || existsFromEnums; } diff --git a/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts b/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts index c09973a6721..69b7319ccec 100644 --- a/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts +++ b/packages/plugins/other/visitor-plugin-common/src/base-types-visitor.ts @@ -997,7 +997,7 @@ export class BaseTypesVisitor< return this._getScalar(typeAsString, isVisitingInputType ? 'input' : 'output'); } if (this.config.enumValues[typeAsString]) { - return this.config.enumValues[typeAsString].typeIdentifier; + return this.config.enumValues[typeAsString].typeIdentifierConverted; } const schemaType = this._schema.getType(typeAsString); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts index 36c469748f5..5a76ff8d199 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts @@ -847,7 +847,7 @@ describe('TypeScript Operations Plugin - Enum', () => { typesPrefix: 'I', namingConvention: { enumValues: 'change-case-all#constantCase' }, enumValues: { - UserRole: './files#default as IUserRole', + UserRole: './files#default as UserRole', // NOTE: `as UserRole` doesn't do anything here, this is here to demonstrate that it's the same as './files#default' }, }, { outputFile: '' } diff --git a/packages/plugins/typescript/resolvers/tests/ts-resolvers.spec.ts b/packages/plugins/typescript/resolvers/tests/ts-resolvers.spec.ts index f9e5898e10f..178aa9552f3 100644 --- a/packages/plugins/typescript/resolvers/tests/ts-resolvers.spec.ts +++ b/packages/plugins/typescript/resolvers/tests/ts-resolvers.spec.ts @@ -724,8 +724,8 @@ __isTypeOf?: IsTypeOfResolverFn; expect(mergedOutputs).not.toContain(`NotMapped: NotMapped;`); expect(mergedOutputs).toContain(`A: MyA;`); expect(mergedOutputs).toContain(`B: GQL_B;`); - expect(mergedOutputs).toContain(`C: C;`); - expect(mergedOutputs).toContain(`import { MyC as C } from '../enums.js';`); + expect(mergedOutputs).toContain(`C: GQL_C;`); + expect(mergedOutputs).toContain(`import { MyC as GQL_C } from '../enums.js';`); }); it('Should allow to generate optional __resolveType', async () => { @@ -2447,6 +2447,9 @@ export type ResolverFn = ( { outputFile: 'graphql.ts' }, )) as Types.ComplexPluginOutput; + expect(output.content).toContain( + `export type GqlAuthDirectiveArgs = {\n role?: Maybe;\n};`, + ); // Note: `GqlUserRole` will be imported from `@org/package` by `typescript` plugin expect(output.content).toContain( `export type GqlAuthDirectiveArgs = {\n role?: Maybe;\n};`, ); diff --git a/packages/plugins/typescript/typescript/tests/typescript.spec.ts b/packages/plugins/typescript/typescript/tests/typescript.spec.ts index a3e0d191a74..4417d547e46 100644 --- a/packages/plugins/typescript/typescript/tests/typescript.spec.ts +++ b/packages/plugins/typescript/typescript/tests/typescript.spec.ts @@ -905,13 +905,13 @@ describe('TypeScript', () => { typesPrefix: 'I', namingConvention: { enumValues: 'change-case-all#constantCase' }, enumValues: { - MyEnum: './files#default as MyEnum', + MyEnum: './files#default as MyEnum', // NOTE: `as MyEnum` doesn't do anything, this is here to demonstrate that it's the same as './files#default' }, }, { outputFile: '' }, )) as Types.ComplexPluginOutput; - expect(result.prepend[0]).toBe(`import MyEnum from './files';`); + expect(result.prepend[0]).toBe(`import IMyEnum from './files';`); }); it('#4834 - enum members should be quoted if numeric', async () => { @@ -958,14 +958,21 @@ describe('TypeScript', () => { { outputFile: '' }, )) as Types.ComplexPluginOutput; + expect(result.prepend).toMatchInlineSnapshot(` + [ + "import { MyEnum as IMyEnum } from './files';", + "export type Maybe = T | null;", + "export type InputMaybe = Maybe;", + ] + `); expect(result.content).toBeSimilarStringTo(`export type ITest = { __typename?: 'Test'; - t?: Maybe; + t?: Maybe; test?: Maybe; };`); expect(result.content).toBeSimilarStringTo(`export type ITestTestArgs = { - a?: InputMaybe; + a?: InputMaybe; };`); }); @@ -997,9 +1004,9 @@ describe('TypeScript', () => { }, { outputFile: '' }, )) as Types.ComplexPluginOutput; - expect(result.prepend).toContain(`import { MyEnum } from './files';`); + expect(result.prepend).toContain(`import { MyEnum as GQL_MyEnum } from './files';`); expect(result.content).toContain(`enum GQL_OtherEnum {`); - expect(result.content).toContain(`a?: Maybe;`); + expect(result.content).toContain(`a?: Maybe;`); expect(result.content).toContain(`b?: Maybe`); }); From 6a2738be8088fd6f3b493b2df4b34df15ec92f9e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 13 Apr 2026 13:12:52 +0000 Subject: [PATCH 67/69] chore(dependencies): updated changesets for modified dependencies --- .../@graphql-codegen_client-preset-10496-dependencies.md | 5 ----- ...graphql-codegen_typed-document-node-10496-dependencies.md | 2 +- .changeset/@graphql-codegen_typescript-10496-dependencies.md | 1 + ...aphql-codegen_typescript-operations-10496-dependencies.md | 2 +- 4 files changed, 3 insertions(+), 7 deletions(-) delete mode 100644 .changeset/@graphql-codegen_client-preset-10496-dependencies.md diff --git a/.changeset/@graphql-codegen_client-preset-10496-dependencies.md b/.changeset/@graphql-codegen_client-preset-10496-dependencies.md deleted file mode 100644 index bfcc839c224..00000000000 --- a/.changeset/@graphql-codegen_client-preset-10496-dependencies.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@graphql-codegen/client-preset": patch ---- -dependencies updates: - - Removed dependency [`@graphql-codegen/typescript@^5.0.9` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.9) (from `dependencies`) diff --git a/.changeset/@graphql-codegen_typed-document-node-10496-dependencies.md b/.changeset/@graphql-codegen_typed-document-node-10496-dependencies.md index 52788e4aeeb..03198289844 100644 --- a/.changeset/@graphql-codegen_typed-document-node-10496-dependencies.md +++ b/.changeset/@graphql-codegen_typed-document-node-10496-dependencies.md @@ -2,5 +2,5 @@ "@graphql-codegen/typed-document-node": patch --- dependencies updates: - - Updated dependency [`change-case-all@^2.1.0` ↗︎](https://www.npmjs.com/package/change-case-all/v/2.1.0) (from `1.0.15`, in `dependencies`) - Updated dependency [`auto-bind@^5.0.0` ↗︎](https://www.npmjs.com/package/auto-bind/v/5.0.0) (from `~4.0.0`, in `dependencies`) + - Updated dependency [`change-case-all@^2.1.0` ↗︎](https://www.npmjs.com/package/change-case-all/v/2.1.0) (from `1.0.15`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typescript-10496-dependencies.md b/.changeset/@graphql-codegen_typescript-10496-dependencies.md index e7efcd336f4..f0a25772c39 100644 --- a/.changeset/@graphql-codegen_typescript-10496-dependencies.md +++ b/.changeset/@graphql-codegen_typescript-10496-dependencies.md @@ -3,3 +3,4 @@ --- dependencies updates: - Updated dependency [`auto-bind@^5.0.0` ↗︎](https://www.npmjs.com/package/auto-bind/v/5.0.0) (from `~4.0.0`, in `dependencies`) + - Updated dependency [`tslib@~2.6.0` ↗︎](https://www.npmjs.com/package/tslib/v/2.6.0) (from `^2.8.0`, in `dependencies`) diff --git a/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md b/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md index 6ed72635910..fd8fb574d9b 100644 --- a/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md +++ b/.changeset/@graphql-codegen_typescript-operations-10496-dependencies.md @@ -4,4 +4,4 @@ dependencies updates: - Updated dependency [`auto-bind@^5.0.0` ↗︎](https://www.npmjs.com/package/auto-bind/v/5.0.0) (from `~4.0.0`, in `dependencies`) - Added dependency [`@graphql-codegen/schema-ast@^5.0.1` ↗︎](https://www.npmjs.com/package/@graphql-codegen/schema-ast/v/5.0.1) (to `dependencies`) - - Removed dependency [`@graphql-codegen/typescript@^5.0.9` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.9) (from `dependencies`) + - Removed dependency [`@graphql-codegen/typescript@^5.0.10` ↗︎](https://www.npmjs.com/package/@graphql-codegen/typescript/v/5.0.10) (from `dependencies`) From 61e21f4b1b8f8b029c7078874e088f7e34608c4d Mon Sep 17 00:00:00 2001 From: Eddy Nguyen Date: Mon, 13 Apr 2026 23:14:52 +1000 Subject: [PATCH 68/69] Cleanup after rebase --- .prettierignore | 4 + dev-test-apollo-tooling/README.md | 15 ++- dev-test-apollo-tooling/cli/index.ts | 6 +- dev-test-apollo-tooling/package.json | 26 ++--- dev-test-apollo-tooling/schema.graphql | 36 ++++-- dev-test-apollo-tooling/src/Component.ts | 2 +- .../tests/Component.test.ts | 4 +- .../tests/Duplicates.test.ts | 20 ++-- dev-test-apollo-tooling/vitest.config.ts | 2 +- dev-test/test-schema/flow-types.flow.js | 38 ++----- .../tests/generate-and-save.spec.ts | 10 +- ...schema-enum-to-declaration-block-string.ts | 38 ++++--- .../visitor-plugin-common/src/enum-values.ts | 2 +- .../src/graphql-type-utils.ts | 2 +- .../visitor-plugin-common/src/imports.ts | 14 ++- .../src/operation-avoid-optionals.ts | 2 +- .../src/operation-declaration-kinds.ts | 2 +- .../typescript/operations/src/config.ts | 2 +- ...tract-all-types-compact-duplicates.spec.ts | 18 ++- .../tests/extract-all-types.spec.ts | 36 ++++-- ...-documents.external-fragments-enum.spec.ts | 24 ++-- .../ts-documents.externalDocuments.spec.ts | 13 ++- .../tests/ts-documents.nullability.spec.ts | 4 +- ...-documents.skip-include-directives.spec.ts | 107 ++++++++++++++---- ...s.standalone.config.avoidOptionals.spec.ts | 28 +++-- ....standalone.config.declarationKind.spec.ts | 12 +- .../ts-documents.standalone.enum.spec.ts | 82 ++++++++++---- ...-documents.standalone.import-types.spec.ts | 27 +++-- .../ts-documents.standalone.input.spec.ts | 18 ++- .../ts-documents.standalone.scalars.spec.ts | 18 ++- .../tests/ts-documents.standalone.spec.ts | 24 +++- .../resolvers/tests/ts-resolvers.spec.ts | 3 - .../pages/plugins/presets/preset-client.mdx | 2 +- 33 files changed, 426 insertions(+), 215 deletions(-) diff --git a/.prettierignore b/.prettierignore index d58d3ea2879..33860628e5b 100644 --- a/.prettierignore +++ b/.prettierignore @@ -34,3 +34,7 @@ packages/presets/swc-plugin/tests/fixtures # Ignore intentional error files packages/graphql-codegen-cli/tests/test-files/schema-dir/error-schema.graphql packages/graphql-codegen-cli/tests/test-files/error-document.graphql + +# Ignore dev-tests with no prettier requirement +dev-test/test-schema/flow-types.flow.js +dev-test-apollo-tooling/src/__generated__/ diff --git a/dev-test-apollo-tooling/README.md b/dev-test-apollo-tooling/README.md index 69e815dce45..0e0fb858580 100644 --- a/dev-test-apollo-tooling/README.md +++ b/dev-test-apollo-tooling/README.md @@ -1,20 +1,23 @@ -The `dev-test-apollo-tooling` package is an example of migrating from Apollo tooling to GraphQL Codegen. It attempts to generate output as close as possible to Apollo tooling’s output. Note: **this package is a work in progress** and currently requires a patch to `near-operation-file`. We will fix this package soon. +The `dev-test-apollo-tooling` package is an example of migrating from Apollo tooling to GraphQL +Codegen. It attempts to generate output as close as possible to Apollo tooling’s output. Note: +**this package is a work in progress** and currently requires a patch to `near-operation-file`. We +will fix this package soon. How to run this package: -1. Make sure you have the correct Yarn version installed (check the root package.json, `packageManager` entry). Otherwise, you might run into unexplained bugs. +1. Make sure you have the correct Yarn version installed (check the root package.json, + `packageManager` entry). Otherwise, you might run into unexplained bugs. 2. In the monorepo root, run: yarn clean && yarn install && yarn build -3. Patch `near-operation-file` manually (the automatic patch doesn’t always work). In the monorepo root, run: +3. Patch `near-operation-file` manually (the automatic patch doesn’t always work). In the monorepo + root, run: yarn postinstall 4. Go to the `dev-test-apollo-tooling` directory and run: -cd dev-test-apollo-tooling -yarn install -yarn start +cd dev-test-apollo-tooling yarn install yarn start This will generate type files in `dev-test-apollo-tooling/src/__generated__/*`. diff --git a/dev-test-apollo-tooling/cli/index.ts b/dev-test-apollo-tooling/cli/index.ts index 50b6bd525da..a82483dcf50 100644 --- a/dev-test-apollo-tooling/cli/index.ts +++ b/dev-test-apollo-tooling/cli/index.ts @@ -1,5 +1,4 @@ #!/usr/bin/env ts-node - import { generate } from '@graphql-codegen/cli'; import type { Types } from '@graphql-codegen/plugin-helpers'; @@ -62,7 +61,10 @@ export const main = async () => { await generate({ schema: localSchemaFilePath, - documents: [...includes.map((include: any) => `${include}/**/*.{js,jsx,ts,tsx}`), `!**/${GENERATED}/**`], + documents: [ + ...includes.map((include: any) => `${include}/**/*.{js,jsx,ts,tsx}`), + `!**/${GENERATED}/**`, + ], config: GRAPHQL_CODEGEN_CONFIG, generates: generatePaths, silent: false, diff --git a/dev-test-apollo-tooling/package.json b/dev-test-apollo-tooling/package.json index e0a5e49feee..a38219fb00b 100644 --- a/dev-test-apollo-tooling/package.json +++ b/dev-test-apollo-tooling/package.json @@ -1,16 +1,25 @@ { "name": "dev-test-apollo-tooling", - "private": true, - "description": "A setup which mimics Apollo tooling generation as close as possible", "version": "0.0.1", "type": "module", + "description": "A setup which mimics Apollo tooling generation as close as possible", + "private": true, + "files": [ + "cli" + ], + "scripts": { + "start": "tsx cli/index.ts", + "start:debug": "NODE_OPTIONS='--trace-warnings' tsx cli/index.ts", + "start:verbose": "DEBUG='*' tsx cli/index.ts", + "test": "vitest --no-watch" + }, "dependencies": { "@apollo/client": "3.13.8", "@graphql-codegen/cli": "*", "@graphql-codegen/plugin-helpers": "*", + "@graphql-codegen/typed-document-node": "*", "@graphql-codegen/typescript-operations": "*", - "@graphql-codegen/visitor-plugin-common": "*", - "@graphql-codegen/typed-document-node": "*" + "@graphql-codegen/visitor-plugin-common": "*" }, "devDependencies": { "@types/node": "^25.0.3", @@ -18,14 +27,5 @@ "typescript": "^5.9.3", "vitest": "4.0.4" }, - "files": [ - "cli" - ], - "scripts": { - "start": "tsx cli/index.ts", - "start:debug": "NODE_OPTIONS='--trace-warnings' tsx cli/index.ts", - "start:verbose": "DEBUG='*' tsx cli/index.ts", - "test": "vitest --no-watch" - }, "sideEffects": false } diff --git a/dev-test-apollo-tooling/schema.graphql b/dev-test-apollo-tooling/schema.graphql index 68909ce7a6e..d5c1acd821f 100644 --- a/dev-test-apollo-tooling/schema.graphql +++ b/dev-test-apollo-tooling/schema.graphql @@ -20,7 +20,10 @@ directive @join__field( overrideLabel: String ) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION -directive @join__implements(graph: join__Graph!, interface: String!) repeatable on OBJECT | INTERFACE +directive @join__implements( + graph: join__Graph! + interface: String! +) repeatable on OBJECT | INTERFACE directive @join__type( graph: join__Graph! @@ -32,7 +35,12 @@ directive @join__type( directive @join__unionMember(graph: join__Graph!, member: String!) repeatable on UNION -directive @link(url: String, as: String, for: link__Purpose, import: [link__Import]) repeatable on SCHEMA +directive @link( + url: String + as: String + for: link__Purpose + import: [link__Import] +) repeatable on SCHEMA directive @tag( name: String! @@ -47,10 +55,15 @@ enum link__Purpose { } enum join__Graph { - SUPER_USER_MANAGER @join__graph(name: "super_user_management", url: "http://i.am.not.used.example.com") - GRAPHQL_MAIN__SHARD__BASE @join__graph(name: "graphql_main__shard__base", url: "http://i.am.not.used.example.com") + SUPER_USER_MANAGER + @join__graph(name: "super_user_management", url: "http://i.am.not.used.example.com") + GRAPHQL_MAIN__SHARD__BASE + @join__graph(name: "graphql_main__shard__base", url: "http://i.am.not.used.example.com") GRAPHQL_MAIN__SHARD__INTERNAL_TESTING - @join__graph(name: "graphql_main__shard__internal_testing", url: "http://i.am.not.used.example.com") + @join__graph( + name: "graphql_main__shard__internal_testing" + url: "http://i.am.not.used.example.com" + ) } type Query { @@ -203,8 +216,12 @@ enum ProcessableFeedbackSortBy enum ProcessableFeedbackSortOrder @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) @join__type(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) { - ASC @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) - DESC @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) + ASC + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) + DESC + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__BASE) + @join__enumValue(graph: GRAPHQL_MAIN__SHARD__INTERNAL_TESTING) } type FeedbackConnection @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { @@ -229,7 +246,8 @@ type Thread implements Node @join__implements(graph: GRAPHQL_MAIN__SHARD__BASE, interface: "Node") @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { id: ID! - posts(after: String, first: Int): ThreadPostConnection @join__field(graph: GRAPHQL_MAIN__SHARD__BASE) + posts(after: String, first: Int): ThreadPostConnection + @join__field(graph: GRAPHQL_MAIN__SHARD__BASE) } type ThreadPostConnection @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { @@ -253,7 +271,7 @@ union ThreadPostCreator @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) @join__unionMember(graph: GRAPHQL_MAIN__SHARD__BASE, member: "OrgMember") @join__unionMember(graph: GRAPHQL_MAIN__SHARD__BASE, member: "EndUser") = - OrgMember + | OrgMember | EndUser type OrgMember @join__type(graph: GRAPHQL_MAIN__SHARD__BASE) { diff --git a/dev-test-apollo-tooling/src/Component.ts b/dev-test-apollo-tooling/src/Component.ts index 5360cbd4218..af327d906f8 100644 --- a/dev-test-apollo-tooling/src/Component.ts +++ b/dev-test-apollo-tooling/src/Component.ts @@ -3,7 +3,7 @@ * Check that `UserManagerRoleType` enum is generated in `__generated__/Component.ts` */ -import { useQuery, gql } from '@apollo/client'; +import { gql, useQuery } from '@apollo/client'; import Helper from './Helper'; export const getFooQuery = gql` diff --git a/dev-test-apollo-tooling/tests/Component.test.ts b/dev-test-apollo-tooling/tests/Component.test.ts index 2ce5f6fa4c2..0de36414f05 100644 --- a/dev-test-apollo-tooling/tests/Component.test.ts +++ b/dev-test-apollo-tooling/tests/Component.test.ts @@ -1,7 +1,7 @@ -import { describe, it, expect } from 'vitest'; import { readFileSync } from 'node:fs'; -import { fileURLToPath } from 'node:url'; import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describe, expect, it } from 'vitest'; const __dirname = dirname(fileURLToPath(import.meta.url)); diff --git a/dev-test-apollo-tooling/tests/Duplicates.test.ts b/dev-test-apollo-tooling/tests/Duplicates.test.ts index 9a7843a2e64..e9d87b32318 100644 --- a/dev-test-apollo-tooling/tests/Duplicates.test.ts +++ b/dev-test-apollo-tooling/tests/Duplicates.test.ts @@ -1,13 +1,16 @@ -import { describe, it, expect } from 'vitest'; import { readFileSync } from 'node:fs'; -import { fileURLToPath } from 'node:url'; import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describe, expect, it } from 'vitest'; const __dirname = dirname(fileURLToPath(import.meta.url)); describe('Duplicates.ts', () => { it('ConfigTypeDefinitions types should be exported', () => { - const fileContent = readFileSync(join(__dirname, '../src/__generated__/Duplicates.ts'), 'utf-8'); + const fileContent = readFileSync( + join(__dirname, '../src/__generated__/Duplicates.ts'), + 'utf-8', + ); expect(fileContent).toMatch(/export type ConfigTypeDefinitions_ConfigActionId\s*=/); expect(fileContent).toMatch(/export type ConfigTypeDefinitions_ConfigEnum\s*=/); @@ -16,16 +19,19 @@ describe('Duplicates.ts', () => { }); it('GetFeedbackData creator union type exports should exist', () => { - const fileContent = readFileSync(join(__dirname, '../src/__generated__/Duplicates.ts'), 'utf-8'); + const fileContent = readFileSync( + join(__dirname, '../src/__generated__/Duplicates.ts'), + 'utf-8', + ); expect(fileContent).toMatch( - /export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator\s*=/ + /export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator\s*=/, ); expect(fileContent).toMatch( - /export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_EndUser\s*=/ + /export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_EndUser\s*=/, ); expect(fileContent).toMatch( - /export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_OrgMember\s*=/ + /export type GetFeedbackData_organization_internalOrgData_processableFeedback_edges_node_orgMemberThread_posts_edges_node_creator_OrgMember\s*=/, ); }); }); diff --git a/dev-test-apollo-tooling/vitest.config.ts b/dev-test-apollo-tooling/vitest.config.ts index b0ef9b2bc35..98426e79914 100644 --- a/dev-test-apollo-tooling/vitest.config.ts +++ b/dev-test-apollo-tooling/vitest.config.ts @@ -8,5 +8,5 @@ export default mergeConfig( name: 'dev-test-apollo-tooling', include: ['tests/**/*.spec.ts', 'tests/**/*.test.ts'], }, - }) + }), ); diff --git a/dev-test/test-schema/flow-types.flow.js b/dev-test/test-schema/flow-types.flow.js index f8ac067469a..4b3cd55f7e0 100644 --- a/dev-test/test-schema/flow-types.flow.js +++ b/dev-test/test-schema/flow-types.flow.js @@ -1,8 +1,7 @@ // @flow import { type GraphQLResolveInfo } from 'graphql'; -export type $RequireFields = $Diff & - $ObjMapi(k: Key) => $NonMaybeType<$ElementType>>; +export type $RequireFields = $Diff & $ObjMapi(k: Key) => $NonMaybeType<$ElementType>>; /** All built-in and custom scalars, mapped to their actual values */ export type Scalars = {| ID: string, @@ -18,6 +17,7 @@ export type Query = {| userById?: ?User, |}; + export type QueryUserByIdArgs = {| id: $ElementType, |}; @@ -33,21 +33,21 @@ export type Resolver = ( parent: Parent, args: Args, context: Context, - info: GraphQLResolveInfo, + info: GraphQLResolveInfo ) => Promise | Result; export type SubscriptionSubscribeFn = ( parent: Parent, args: Args, context: Context, - info: GraphQLResolveInfo, + info: GraphQLResolveInfo ) => AsyncIterator | Promise>; export type SubscriptionResolveFn = ( parent: Parent, args: Args, context: Context, - info: GraphQLResolveInfo, + info: GraphQLResolveInfo ) => Result | Promise; export interface SubscriptionSubscriberObject { @@ -71,14 +71,10 @@ export type SubscriptionResolver = ( parent: Parent, context: Context, - info: GraphQLResolveInfo, + info: GraphQLResolveInfo ) => ?Types | Promise; -export type IsTypeOfResolverFn = ( - obj: T, - context: Context, - info: GraphQLResolveInfo, -) => boolean | Promise; +export type IsTypeOfResolverFn = (obj: T, context: Context, info: GraphQLResolveInfo) => boolean | Promise; export type NextResolverFn = () => Promise; @@ -87,7 +83,7 @@ export type DirectiveResolverFn Result | Promise; export type ResolverTypeWrapper = Promise | T; @@ -110,23 +106,12 @@ export type ResolversParentTypes = { User: User, }; -export type QueryResolvers< - ContextType = any, - ParentType = $ElementType, -> = { +export type QueryResolvers> = { allUsers?: Resolver>, ParentType, ContextType>, - userById?: Resolver< - ?$ElementType, - ParentType, - ContextType, - $RequireFields, - >, + userById?: Resolver, ParentType, ContextType, $RequireFields>, }; -export type UserResolvers< - ContextType = any, - ParentType = $ElementType, -> = { +export type UserResolvers> = { email?: Resolver<$ElementType, ParentType, ContextType>, id?: Resolver<$ElementType, ParentType, ContextType>, name?: Resolver<$ElementType, ParentType, ContextType>, @@ -137,3 +122,4 @@ export type Resolvers = { Query?: QueryResolvers, User?: UserResolvers, }; + diff --git a/packages/graphql-codegen-cli/tests/generate-and-save.spec.ts b/packages/graphql-codegen-cli/tests/generate-and-save.spec.ts index 8e064912622..1c4154b2b2f 100644 --- a/packages/graphql-codegen-cli/tests/generate-and-save.spec.ts +++ b/packages/graphql-codegen-cli/tests/generate-and-save.spec.ts @@ -348,16 +348,18 @@ describe('generate-and-save', () => { }, }, }, - false + false, ); } catch { // Note: cannot use toMatchInlineSnapshot here because spacing in the snapshot gets formatted by prettier. expect(outputErrorSpy.mock.calls[0][0]).toContain( - '[FAILED] Failed to load documents from ./tests/test-files/error-document-error-keyword.graphql.*.ts,!src/gql/:' + '[FAILED] Failed to load documents from ./tests/test-files/error-document-error-keyword.graphql.*.ts,!src/gql/:', + ); + expect(outputErrorSpy.mock.calls[0][0]).toContain( + '[FAILED] Syntax Error: Unexpected Name "qu".', ); - expect(outputErrorSpy.mock.calls[0][0]).toContain('[FAILED] Syntax Error: Unexpected Name "qu".'); expect(outputErrorSpy.mock.calls[0][0]).toContain( - `[FAILED] ${process.cwd()}/tests/test-files/error-document-error-keyword.graphql.1.ts:2:3` + `[FAILED] ${process.cwd()}/tests/test-files/error-document-error-keyword.graphql.1.ts:2:3`, ); expect(outputErrorSpy.mock.calls[0][0]).toContain('[FAILED] 2 | qu ery Test {'); expect(outputErrorSpy.mock.calls[0][0]).toContain('[FAILED] | ^'); diff --git a/packages/plugins/other/visitor-plugin-common/src/convert-schema-enum-to-declaration-block-string.ts b/packages/plugins/other/visitor-plugin-common/src/convert-schema-enum-to-declaration-block-string.ts index 8c857142469..3b24a5e36e7 100644 --- a/packages/plugins/other/visitor-plugin-common/src/convert-schema-enum-to-declaration-block-string.ts +++ b/packages/plugins/other/visitor-plugin-common/src/convert-schema-enum-to-declaration-block-string.ts @@ -1,14 +1,19 @@ -import type { EnumTypeDefinitionNode, EnumValueDefinitionNode, GraphQLEnumType, GraphQLSchema } from 'graphql'; +import type { + EnumTypeDefinitionNode, + EnumValueDefinitionNode, + GraphQLEnumType, + GraphQLSchema, +} from 'graphql'; +import { convertName } from './naming.js'; import type { ConvertFn, ParsedEnumValuesMap } from './types.js'; import { DeclarationBlock, - type DeclarationBlockConfig, + getNodeComment, indent, transformComment, - getNodeComment, wrapWithSingleQuotes, + type DeclarationBlockConfig, } from './utils.js'; -import { convertName } from './naming.js'; export interface ConvertSchemaEnumToDeclarationBlockString { schema: GraphQLSchema; @@ -53,7 +58,9 @@ export const convertSchemaEnumToDeclarationBlockString = ({ return null; }; - const withFutureAddedValue = [futureProofEnums ? [indent('| ' + wrapWithSingleQuotes('%future added value'))] : []]; + const withFutureAddedValue = [ + futureProofEnums ? [indent('| ' + wrapWithSingleQuotes('%future added value'))] : [], + ]; const enumTypeName = convertName({ convert: () => naming.convert(node), @@ -77,7 +84,7 @@ export const convertSchemaEnumToDeclarationBlockString = ({ return comment + indent('| ' + wrapWithSingleQuotes(enumValue)); }) .concat(...withFutureAddedValue) - .join('\n') + .join('\n'), ).string; } @@ -101,12 +108,12 @@ export const convertSchemaEnumToDeclarationBlockString = ({ useTypesPrefix: false, }, convert: () => naming.convert(enumOption, { transformUnderscore: true }), - }) + }), ); return comment + indent(optionName) + ` = ${enumValue}`; }) .concat(...withFutureAddedValue) - .join(',\n') + .join(',\n'), ).string; } @@ -135,7 +142,7 @@ export const convertSchemaEnumToDeclarationBlockString = ({ naming.convert(enumOption, { transformUnderscore: true, }), - }) + }), ); const comment = transformComment(enumOption.description?.value, 1); const name = enumOption.name.value; @@ -143,7 +150,7 @@ export const convertSchemaEnumToDeclarationBlockString = ({ return comment + indent(`${optionName}: ${wrapWithSingleQuotes(enumValue)}`); }) - .join(',\n') + .join(',\n'), ).string; return [enumAsConst, typeName].join('\n'); @@ -163,7 +170,7 @@ export const convertSchemaEnumToDeclarationBlockString = ({ ignoreEnumValuesFromSchema, declarationBlockConfig, enumValues, - }) + }), ).string; }; @@ -202,14 +209,15 @@ export const buildEnumValuesBlock = ({ // characters. Otherwise we'll generate syntactically invalid code. transformUnderscore: !onlyUnderscoresPattern.test(enumOption.name.value), }), - }) + }), ); const comment = getNodeComment(enumOption); const schemaEnumValue = schemaEnumType && !ignoreEnumValuesFromSchema ? schemaEnumType.getValue(enumOption.name.value).value : undefined; - let enumValue: string | number = typeof schemaEnumValue === 'undefined' ? enumOption.name.value : schemaEnumValue; + let enumValue: string | number = + typeof schemaEnumValue === 'undefined' ? enumOption.name.value : schemaEnumValue; if (typeof enumValues[typeName]?.mappedValues?.[enumValue] !== 'undefined') { enumValue = enumValues[typeName].mappedValues[enumValue]; @@ -220,8 +228,8 @@ export const buildEnumValuesBlock = ({ indent( `${optionName}${declarationBlockConfig.enumNameValueSeparator} ${wrapWithSingleQuotes( enumValue, - typeof schemaEnumValue !== 'undefined' - )}` + typeof schemaEnumValue !== 'undefined', + )}`, ) ); }) diff --git a/packages/plugins/other/visitor-plugin-common/src/enum-values.ts b/packages/plugins/other/visitor-plugin-common/src/enum-values.ts index de56ab76658..6d87a956789 100644 --- a/packages/plugins/other/visitor-plugin-common/src/enum-values.ts +++ b/packages/plugins/other/visitor-plugin-common/src/enum-values.ts @@ -1,7 +1,7 @@ import { GraphQLEnumType, GraphQLSchema, isEnumType } from 'graphql'; import { parseMapper } from './mappers.js'; -import type { ConvertFn, EnumValuesMap, ParsedEnumValuesMap } from './types.js'; import { convertName } from './naming.js'; +import type { ConvertFn, EnumValuesMap, ParsedEnumValuesMap } from './types.js'; function escapeString(str: string) { return str.replace(/\\/g, '\\\\').replace(/\n/g, '\\n').replace(/'/g, "\\'"); diff --git a/packages/plugins/other/visitor-plugin-common/src/graphql-type-utils.ts b/packages/plugins/other/visitor-plugin-common/src/graphql-type-utils.ts index 9c2e2c175ea..52a43513c03 100644 --- a/packages/plugins/other/visitor-plugin-common/src/graphql-type-utils.ts +++ b/packages/plugins/other/visitor-plugin-common/src/graphql-type-utils.ts @@ -1,4 +1,4 @@ -import { type GraphQLNamedType, isIntrospectionType, isSpecifiedScalarType } from 'graphql'; +import { isIntrospectionType, isSpecifiedScalarType, type GraphQLNamedType } from 'graphql'; export const isNativeNamedType = (namedType: GraphQLNamedType): boolean => { // "Native" NamedType in this context means the following: diff --git a/packages/plugins/other/visitor-plugin-common/src/imports.ts b/packages/plugins/other/visitor-plugin-common/src/imports.ts index 2a291cc1998..8ac5fc27254 100644 --- a/packages/plugins/other/visitor-plugin-common/src/imports.ts +++ b/packages/plugins/other/visitor-plugin-common/src/imports.ts @@ -131,7 +131,11 @@ export function getEnumsImports({ // use namespace import to dereference nested enum // { enumValues: { MyEnum: './my-file#NS.NestedEnum' } } return [ - buildTypeImport({ identifier: importIdentifier || sourceIdentifier, source: sourceFile, useTypeImports }), + buildTypeImport({ + identifier: importIdentifier || sourceIdentifier, + source: sourceFile, + useTypeImports, + }), `import ${typeIdentifierConverted} = ${sourceIdentifier};`, ]; } @@ -144,7 +148,13 @@ export function getEnumsImports({ }), ]; } - return [buildTypeImport({ identifier: importIdentifier || sourceIdentifier, source: sourceFile, useTypeImports })]; + return [ + buildTypeImport({ + identifier: importIdentifier || sourceIdentifier, + source: sourceFile, + useTypeImports, + }), + ]; } return Object.keys(enumValues) diff --git a/packages/plugins/other/visitor-plugin-common/src/operation-avoid-optionals.ts b/packages/plugins/other/visitor-plugin-common/src/operation-avoid-optionals.ts index cf502c9b44f..6afbf647ce5 100644 --- a/packages/plugins/other/visitor-plugin-common/src/operation-avoid-optionals.ts +++ b/packages/plugins/other/visitor-plugin-common/src/operation-avoid-optionals.ts @@ -6,7 +6,7 @@ export interface OperationAvoidOptionalsConfig { export type NormalizedOperationAvoidOptionalsConfig = Required; export const normalizeOperationAvoidOptionals = ( - avoidOptionals: boolean | OperationAvoidOptionalsConfig + avoidOptionals: boolean | OperationAvoidOptionalsConfig, ): NormalizedOperationAvoidOptionalsConfig => { const defaultAvoidOptionals: NormalizedOperationAvoidOptionalsConfig = { variableValue: false, diff --git a/packages/plugins/other/visitor-plugin-common/src/operation-declaration-kinds.ts b/packages/plugins/other/visitor-plugin-common/src/operation-declaration-kinds.ts index a68a8dffee1..c5aed4ae3bf 100644 --- a/packages/plugins/other/visitor-plugin-common/src/operation-declaration-kinds.ts +++ b/packages/plugins/other/visitor-plugin-common/src/operation-declaration-kinds.ts @@ -13,7 +13,7 @@ const DEFAULT_OPERATION_DECLARATION_KINDS: NormalizedOperationDeclarationKindCon }; export function normalizeOperationDeclarationKind( - declarationKind: OperationDeclarationKind | OperationDeclarationKindConfig + declarationKind: OperationDeclarationKind | OperationDeclarationKindConfig, ): NormalizedOperationDeclarationKindConfig { if (typeof declarationKind === 'string') { return { diff --git a/packages/plugins/typescript/operations/src/config.ts b/packages/plugins/typescript/operations/src/config.ts index 934be5996e9..eb2db30ad27 100644 --- a/packages/plugins/typescript/operations/src/config.ts +++ b/packages/plugins/typescript/operations/src/config.ts @@ -1,7 +1,7 @@ import { + RawDocumentsConfig, type ConvertSchemaEnumToDeclarationBlockString, type EnumValuesMap, - RawDocumentsConfig, } from '@graphql-codegen/visitor-plugin-common'; /** diff --git a/packages/plugins/typescript/operations/tests/extract-all-types-compact-duplicates.spec.ts b/packages/plugins/typescript/operations/tests/extract-all-types-compact-duplicates.spec.ts index 03daec54d3d..f09cd9673a7 100644 --- a/packages/plugins/typescript/operations/tests/extract-all-types-compact-duplicates.spec.ts +++ b/packages/plugins/typescript/operations/tests/extract-all-types-compact-duplicates.spec.ts @@ -1,6 +1,6 @@ +import { buildSchema, parse } from 'graphql'; import { mergeOutputs, Types } from '@graphql-codegen/plugin-helpers'; import { validateTs } from '@graphql-codegen/testing'; -import { buildSchema, parse } from 'graphql'; import { plugin, type TypeScriptDocumentsPluginConfig } from '../src/index.js'; describe('extractAllFieldsToTypesCompact: duplicate type names', () => { @@ -69,7 +69,9 @@ describe('extractAllFieldsToTypesCompact: duplicate type names', () => { fragmentSuffix: '', }; - const { content } = await plugin(schema, [{ location: 'test-file.ts', document }], config, { outputFile: '' }); + const { content } = await plugin(schema, [{ location: 'test-file.ts', document }], config, { + outputFile: '', + }); await validate(content); @@ -146,7 +148,9 @@ describe('extractAllFieldsToTypesCompact: duplicate type names', () => { fragmentSuffix: '', }; - const { content } = await plugin(schema, [{ location: 'test-file.ts', document }], config, { outputFile: '' }); + const { content } = await plugin(schema, [{ location: 'test-file.ts', document }], config, { + outputFile: '', + }); await validate(content); @@ -202,7 +206,9 @@ describe('extractAllFieldsToTypesCompact: duplicate type names', () => { fragmentSuffix: '', }; - const { content } = await plugin(schema, [{ location: 'test-file.ts', document }], config, { outputFile: '' }); + const { content } = await plugin(schema, [{ location: 'test-file.ts', document }], config, { + outputFile: '', + }); await validate(content); @@ -306,7 +312,9 @@ describe('extractAllFieldsToTypesCompact: duplicate type names', () => { fragmentSuffix: '', }; - const { content } = await plugin(schema, [{ location: 'test-file.ts', document }], config, { outputFile: '' }); + const { content } = await plugin(schema, [{ location: 'test-file.ts', document }], config, { + outputFile: '', + }); await validate(content); diff --git a/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts b/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts index a4bebc6780f..c5a514ce8d6 100644 --- a/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/extract-all-types.spec.ts @@ -1652,9 +1652,14 @@ describe('extractAllFieldsToTypesCompact: true', () => { nonOptionalTypename: true, omitOperationSuffix: true, }; - const { content } = await plugin(companySchema, [{ location: 'test-file.ts', document: companyDoc }], config, { - outputFile: '', - }); + const { content } = await plugin( + companySchema, + [{ location: 'test-file.ts', document: companyDoc }], + config, + { + outputFile: '', + }, + ); expect(content).toMatchInlineSnapshot(` "export type GetCompanyInfo_company_office_location = { __typename: 'Location', formatted: string | null }; @@ -1721,7 +1726,12 @@ describe('extractAllFieldsToTypesCompact: true', () => { nonOptionalTypename: true, omitOperationSuffix: true, }; - const { content } = await plugin(schema, [{ location: 'test-file.ts', document: doc }], config, { outputFile: '' }); + const { content } = await plugin( + schema, + [{ location: 'test-file.ts', document: doc }], + config, + { outputFile: '' }, + ); // Verify the naming follows Apollo Tooling style (field names only, no intermediate type names) expect(content).toContain('GetAnimals_animals_owner_Trainer'); @@ -1744,9 +1754,14 @@ describe('extractAllFieldsToTypesCompact: true', () => { nonOptionalTypename: true, omitOperationSuffix: true, }; - const { content } = await plugin(companySchema, [{ location: 'test-file.ts', document: companyDoc }], config, { - outputFile: '', - }); + const { content } = await plugin( + companySchema, + [{ location: 'test-file.ts', document: companyDoc }], + config, + { + outputFile: '', + }, + ); // When extractAllFieldsToTypesCompact is true, extractAllFieldsToTypes should be automatically enabled // So types should be extracted, not inlined @@ -1810,7 +1825,12 @@ describe('extractAllFieldsToTypesCompact: true', () => { nonOptionalTypename: true, omitOperationSuffix: true, }; - const { content } = await plugin(schema, [{ location: 'test-file.ts', document: doc }], config, { outputFile: '' }); + const { content } = await plugin( + schema, + [{ location: 'test-file.ts', document: doc }], + config, + { outputFile: '' }, + ); // Fragment types should use compact naming (no intermediate type names) expect(content).toContain('UserProfile_profile_contact'); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.external-fragments-enum.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.external-fragments-enum.spec.ts index d1296b56719..625341a79eb 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.external-fragments-enum.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.external-fragments-enum.spec.ts @@ -1,6 +1,6 @@ +import { buildSchema, parse } from 'graphql'; import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; import { validateTs } from '@graphql-codegen/testing'; -import { buildSchema, parse } from 'graphql'; import { plugin } from '../src/index.js'; describe('TypeScript Operations Plugin - External Fragments with Enums', () => { @@ -68,7 +68,7 @@ describe('TypeScript Operations Plugin - External Fragments with Enums', () => { }, ], }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -150,7 +150,7 @@ describe('TypeScript Operations Plugin - External Fragments with Enums', () => { }, ], }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -211,7 +211,10 @@ describe('TypeScript Operations Plugin - External Fragments with Enums', () => { const roleFragmentDef = roleFragmentDocument.definitions[0]; const statusFragmentDef = statusFragmentDocument.definitions[0]; - if (roleFragmentDef.kind !== 'FragmentDefinition' || statusFragmentDef.kind !== 'FragmentDefinition') { + if ( + roleFragmentDef.kind !== 'FragmentDefinition' || + statusFragmentDef.kind !== 'FragmentDefinition' + ) { throw new Error('Expected fragment definitions'); } @@ -236,7 +239,7 @@ describe('TypeScript Operations Plugin - External Fragments with Enums', () => { }, ], }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -309,7 +312,7 @@ describe('TypeScript Operations Plugin - External Fragments with Enums', () => { }, ], }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -373,7 +376,10 @@ describe('TypeScript Operations Plugin - External Fragments with Enums', () => { const profileFragmentDef = profileFragmentDocument.definitions[0]; const userFragmentDef = userFragmentDocument.definitions[0]; - if (profileFragmentDef.kind !== 'FragmentDefinition' || userFragmentDef.kind !== 'FragmentDefinition') { + if ( + profileFragmentDef.kind !== 'FragmentDefinition' || + userFragmentDef.kind !== 'FragmentDefinition' + ) { throw new Error('Expected fragment definitions'); } @@ -398,7 +404,7 @@ describe('TypeScript Operations Plugin - External Fragments with Enums', () => { }, ], }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -463,7 +469,7 @@ describe('TypeScript Operations Plugin - External Fragments with Enums', () => { }, ], }, - { outputFile: '' } + { outputFile: '' }, ), ]); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.externalDocuments.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.externalDocuments.spec.ts index 3c2139335fb..f474eb86b3f 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.externalDocuments.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.externalDocuments.spec.ts @@ -1,5 +1,6 @@ import { buildSchema, parse } from 'graphql'; import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; +import { validateTs } from '@graphql-codegen/testing'; import { plugin } from '../src/index.js'; describe('TypeScript Operations Plugin - externalDocuments', () => { @@ -49,15 +50,17 @@ describe('TypeScript Operations Plugin - externalDocuments', () => { ]); expect(result).toMatchInlineSnapshot(` - "export type UserQueryVariables = Exact<{ [key: string]: never; }>; + "/** Internal type. DO NOT USE DIRECTLY. */ + type Exact = { [K in keyof T]: T[K] }; + /** Internal type. DO NOT USE DIRECTLY. */ + export type Incremental = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never }; + export type UserQueryVariables = Exact<{ [key: string]: never; }>; - export type UserQuery = { __typename?: 'Query', user?: { __typename?: 'User', id: string, name: string } | null }; + export type UserQuery = { user: { id: string, name: string } | null }; " `); - // FIXME: cannot call `validateTs` until next major version - // https://github.com/dotansimha/graphql-code-generator/pull/10496/changes - // validateTs(result, undefined, undefined, undefined, undefined, true); + validateTs(result, undefined, undefined, undefined, undefined, true); }); }); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.nullability.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.nullability.spec.ts index 43364d22955..6b89ff30494 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.nullability.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.nullability.spec.ts @@ -70,7 +70,7 @@ describe('TypeScript Operations Plugin - nullability', () => { errorHandlingClient: true, }, }, - { outputFile: '' } + { outputFile: '' }, ); const formattedContent = await prettier.format(result.content, { @@ -116,7 +116,7 @@ describe('TypeScript Operations Plugin - nullability', () => { errorHandlingClient: false, }, }, - { outputFile: '' } + { outputFile: '' }, ); const formattedContent = await prettier.format(result.content, { diff --git a/packages/plugins/typescript/operations/tests/ts-documents.skip-include-directives.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.skip-include-directives.spec.ts index 7167019694d..605758badf6 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.skip-include-directives.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.skip-include-directives.spec.ts @@ -34,7 +34,7 @@ describe('TypeScript Operations Plugin - @include directives', () => { schema, [{ location: '', document: fragment }], { maybeValue: "T | 'specialType'" }, - { outputFile: 'graphql.ts' } + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` "export type UserQueryVariables = Exact<{ @@ -78,7 +78,7 @@ describe('TypeScript Operations Plugin - @include directives', () => { schema, [{ location: '', document: fragment }], { allowUndefinedQueryVariables: true }, - { outputFile: 'graphql.ts' } + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` @@ -113,7 +113,12 @@ describe('TypeScript Operations Plugin - @include directives', () => { } `); - const { content } = await plugin(schema, [{ location: '', document: fragment }], {}, { outputFile: 'graphql.ts' }); + const { content } = await plugin( + schema, + [{ location: '', document: fragment }], + {}, + { outputFile: 'graphql.ts' }, + ); expect(content).toMatchInlineSnapshot(` "export type UserQueryVariables = Exact<{ @@ -155,7 +160,7 @@ describe('TypeScript Operations Plugin - @include directives', () => { schema, [{ location: '', document }], { inlineFragmentTypes: 'combine' }, - { outputFile: '' } + { outputFile: '' }, ); expect(content).toMatchInlineSnapshot(` @@ -199,7 +204,12 @@ describe('TypeScript Operations Plugin - @include directives', () => { } `); - const { content } = await plugin(schema, [{ location: '', document: fragment }], {}, { outputFile: 'graphql.ts' }); + const { content } = await plugin( + schema, + [{ location: '', document: fragment }], + {}, + { outputFile: 'graphql.ts' }, + ); expect(content).toMatchInlineSnapshot(` "export type UserQueryVariables = Exact<{ @@ -246,7 +256,12 @@ describe('TypeScript Operations Plugin - @include directives', () => { } `); - const { content } = await plugin(schema, [{ location: '', document: fragment }], {}, { outputFile: 'graphql.ts' }); + const { content } = await plugin( + schema, + [{ location: '', document: fragment }], + {}, + { outputFile: 'graphql.ts' }, + ); expect(content).toMatchInlineSnapshot(` "export type UserQueryVariables = Exact<{ @@ -289,7 +304,7 @@ describe('TypeScript Operations Plugin - @include directives', () => { schema, [{ location: '', document: fragment }], { nonOptionalTypename: true }, - { outputFile: 'graphql.ts' } + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` @@ -332,7 +347,12 @@ describe('TypeScript Operations Plugin - @include directives', () => { } `); - const { content } = await plugin(schema, [{ location: '', document: fragment }], {}, { outputFile: 'graphql.ts' }); + const { content } = await plugin( + schema, + [{ location: '', document: fragment }], + {}, + { outputFile: 'graphql.ts' }, + ); expect(content).toMatchInlineSnapshot(` "export type UserQueryVariables = Exact<{ @@ -379,7 +399,7 @@ describe('TypeScript Operations Plugin - @include directives', () => { schema, [{ location: '', document: fragment }], { maybeValue: "T | 'specialType'" }, - { outputFile: 'graphql.ts' } + { outputFile: 'graphql.ts' }, ); expect(content).toMatchInlineSnapshot(` "export type UserQueryVariables = Exact<{ @@ -417,7 +437,12 @@ describe('TypeScript Operations Plugin - @include directives', () => { } `); - const { content } = await plugin(schema, [{ location: '', document }], {}, { outputFile: 'graphql.ts' }); + const { content } = await plugin( + schema, + [{ location: '', document }], + {}, + { outputFile: 'graphql.ts' }, + ); expect(content).toMatchInlineSnapshot(` "export type GetUsersQueryVariables = Exact<{ @@ -476,7 +501,12 @@ describe('TypeScript Operations Plugin - @include directives', () => { } `); - const { content } = await plugin(schema, [{ location: '', document }], {}, { outputFile: 'graphql.ts' }); + const { content } = await plugin( + schema, + [{ location: '', document }], + {}, + { outputFile: 'graphql.ts' }, + ); expect(content).toMatchInlineSnapshot(` "export type UserQueryVariables = Exact<{ @@ -544,7 +574,12 @@ describe('TypeScript Operations Plugin - @include directives', () => { } `); - const { content } = await plugin(schema, [{ location: '', document }], {}, { outputFile: 'graphql.ts' }); + const { content } = await plugin( + schema, + [{ location: '', document }], + {}, + { outputFile: 'graphql.ts' }, + ); expect(content).toMatchInlineSnapshot(` "export type UserQueryVariables = Exact<{ @@ -601,7 +636,12 @@ describe('TypeScript Operations Plugin - @skip directive', () => { } `); - const { content } = await plugin(testSchema, [{ location: '', document: query }], {}, { outputFile: 'graphql.ts' }); + const { content } = await plugin( + testSchema, + [{ location: '', document: query }], + {}, + { outputFile: 'graphql.ts' }, + ); expect(content).toMatchInlineSnapshot(` "export type UserQueryQueryVariables = Exact<{ @@ -623,12 +663,17 @@ describe('TypeScript Operations Plugin - @skip directive', () => { } `, // < v15 compatibility - { experimentalFragmentVariables: true, allowLegacyFragmentVariables: true } as any + { experimentalFragmentVariables: true, allowLegacyFragmentVariables: true } as any, ); const config = { experimentalFragmentVariables: true }; - const { content } = await plugin(schema, [{ location: 'test-file.ts', document: ast }], config, { - outputFile: '', - }); + const { content } = await plugin( + schema, + [{ location: 'test-file.ts', document: ast }], + config, + { + outputFile: '', + }, + ); expect(content).toMatchInlineSnapshot(` "export type TextNotificationFragmentFragment = { text?: string }; @@ -661,7 +706,12 @@ describe('TypeScript Operations Plugin - @skip directive', () => { } `); - const { content } = await plugin(schema, [{ location: '', document }], {}, { outputFile: 'graphql.ts' }); + const { content } = await plugin( + schema, + [{ location: '', document }], + {}, + { outputFile: 'graphql.ts' }, + ); expect(content).toMatchInlineSnapshot(` "export type GetUsersQueryVariables = Exact<{ @@ -720,7 +770,12 @@ describe('TypeScript Operations Plugin - @skip directive', () => { } `); - const { content } = await plugin(schema, [{ location: '', document }], {}, { outputFile: 'graphql.ts' }); + const { content } = await plugin( + schema, + [{ location: '', document }], + {}, + { outputFile: 'graphql.ts' }, + ); expect(content).toMatchInlineSnapshot(` "export type UserQueryVariables = Exact<{ @@ -788,7 +843,12 @@ describe('TypeScript Operations Plugin - @skip directive', () => { } `); - const { content } = await plugin(schema, [{ location: '', document }], {}, { outputFile: 'graphql.ts' }); + const { content } = await plugin( + schema, + [{ location: '', document }], + {}, + { outputFile: 'graphql.ts' }, + ); expect(content).toMatchInlineSnapshot(` "export type UserQueryVariables = Exact<{ @@ -860,7 +920,12 @@ describe('TypeScript Operations Plugin - @include and @skip with @defer', () => } `); - const { content } = await plugin(schema, [{ location: '', document }], {}, { outputFile: 'graphql.ts' }); + const { content } = await plugin( + schema, + [{ location: '', document }], + {}, + { outputFile: 'graphql.ts' }, + ); expect(content).toMatchInlineSnapshot(` "export type UserSkipQueryVariables = Exact<{ [key: string]: never; }>; diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.avoidOptionals.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.avoidOptionals.spec.ts index 025f1890f67..781d5636975 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.avoidOptionals.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.avoidOptionals.spec.ts @@ -1,6 +1,6 @@ +import { buildSchema, parse } from 'graphql'; import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; import { validateTs } from '@graphql-codegen/testing'; -import { buildSchema, parse } from 'graphql'; import { plugin } from '../src/index.js'; describe('TypeScript Operations Plugin - config.avoidOptionals', () => { @@ -36,7 +36,12 @@ describe('TypeScript Operations Plugin - config.avoidOptionals', () => { scalar DateTime `); const document = parse(/* GraphQL */ ` - query User($testNullable: ID, $testNonNullable: ID!, $inputNullable: UserInput, $inputNonNullable: UserInput!) { + query User( + $testNullable: ID + $testNonNullable: ID! + $inputNullable: UserInput + $inputNonNullable: UserInput! + ) { user(input: $input) { id name @@ -106,7 +111,12 @@ describe('TypeScript Operations Plugin - config.avoidOptionals', () => { scalar DateTime `); const document = parse(/* GraphQL */ ` - query User($testNullable: ID, $testNonNullable: ID!, $inputNullable: UserInput, $inputNonNullable: UserInput!) { + query User( + $testNullable: ID + $testNonNullable: ID! + $inputNullable: UserInput + $inputNonNullable: UserInput! + ) { user(input: $input) { id name @@ -115,7 +125,9 @@ describe('TypeScript Operations Plugin - config.avoidOptionals', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { avoidOptionals: true }, { outputFile: '' })]); + const result = mergeOutputs([ + await plugin(schema, [{ document }], { avoidOptionals: true }, { outputFile: '' }), + ]); expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ @@ -194,7 +206,7 @@ describe('TypeScript Operations Plugin - config.avoidOptionals', () => { inputValue: true, }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -273,7 +285,7 @@ describe('TypeScript Operations Plugin - config.avoidOptionals', () => { defaultValue: true, }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -352,7 +364,7 @@ describe('TypeScript Operations Plugin - config.avoidOptionals', () => { variableValue: true, }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -437,7 +449,7 @@ describe('TypeScript Operations Plugin - config.avoidOptionals', () => { defaultValue: false, }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.declarationKind.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.declarationKind.spec.ts index fdac7d01680..ffe5cce9f93 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.declarationKind.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.config.declarationKind.spec.ts @@ -1,6 +1,6 @@ +import { buildSchema, parse } from 'graphql'; import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; import { validateTs } from '@graphql-codegen/testing'; -import { buildSchema, parse } from 'graphql'; import { plugin } from '../src/index.js'; const warnSpy = vi.spyOn(console, 'warn'); @@ -165,7 +165,7 @@ describe('TypeScript Operations Plugin - config.declarationKind', () => { result: 'interface', // `result` value is `interface`, and `input` value is `type` (default) }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -267,14 +267,14 @@ describe('TypeScript Operations Plugin - config.declarationKind', () => { extractAllFieldsToTypes: true, declarationKind: 'interface', }, - { outputFile: '' } + { outputFile: '' }, ), ]); expect(warnSpy).toHaveBeenCalledTimes(1); expect(warnSpy).toHaveBeenNthCalledWith( 1, - "`declarationKind.result` has been set to `'type'` because `extractAllFieldsToTypes` or `extractAllFieldsToTypesCompact` is true" + "`declarationKind.result` has been set to `'type'` because `extractAllFieldsToTypes` or `extractAllFieldsToTypesCompact` is true", ); expect(result).toMatchInlineSnapshot(` @@ -389,14 +389,14 @@ describe('TypeScript Operations Plugin - config.declarationKind', () => { extractAllFieldsToTypesCompact: true, declarationKind: 'interface', }, - { outputFile: '' } + { outputFile: '' }, ), ]); expect(warnSpy).toHaveBeenCalledTimes(1); expect(warnSpy).toHaveBeenNthCalledWith( 1, - "`declarationKind.result` has been set to `'type'` because `extractAllFieldsToTypes` or `extractAllFieldsToTypesCompact` is true" + "`declarationKind.result` has been set to `'type'` because `extractAllFieldsToTypes` or `extractAllFieldsToTypesCompact` is true", ); expect(result).toMatchInlineSnapshot(` diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts index 5a76ff8d199..921f451f72d 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.enum.spec.ts @@ -1,6 +1,6 @@ +import { buildSchema, parse } from 'graphql'; import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; import { validateTs } from '@graphql-codegen/testing'; -import { buildSchema, parse } from 'graphql'; import { plugin } from '../src/index.js'; describe('TypeScript Operations Plugin - Enum', () => { @@ -134,7 +134,9 @@ describe('TypeScript Operations Plugin - Enum', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'const' }, { outputFile: '' })]); + const result = mergeOutputs([ + await plugin(schema, [{ document }], { enumType: 'const' }, { outputFile: '' }), + ]); expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ @@ -249,7 +251,9 @@ describe('TypeScript Operations Plugin - Enum', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' }, { outputFile: '' })]); + const result = mergeOutputs([ + await plugin(schema, [{ document }], { enumType: 'native' }, { outputFile: '' }), + ]); expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ @@ -304,7 +308,9 @@ describe('TypeScript Operations Plugin - Enum', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' }, { outputFile: '' })]); + const result = mergeOutputs([ + await plugin(schema, [{ document }], { enumType: 'native' }, { outputFile: '' }), + ]); expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ @@ -360,7 +366,9 @@ describe('TypeScript Operations Plugin - Enum', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' }, { outputFile: '' })]); + const result = mergeOutputs([ + await plugin(schema, [{ document }], { enumType: 'native' }, { outputFile: '' }), + ]); expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ @@ -415,7 +423,12 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { typesPrefix: 'I', enumPrefix: true }, { outputFile: '' }), + await plugin( + schema, + [{ document }], + { typesPrefix: 'I', enumPrefix: true }, + { outputFile: '' }, + ), ]); expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ @@ -468,7 +481,12 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { typesPrefix: 'I', enumPrefix: false }, { outputFile: '' }), + await plugin( + schema, + [{ document }], + { typesPrefix: 'I', enumPrefix: false }, + { outputFile: '' }, + ), ]); expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ @@ -521,7 +539,12 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { typesSuffix: 'Z', enumSuffix: true }, { outputFile: '' }), + await plugin( + schema, + [{ document }], + { typesSuffix: 'Z', enumSuffix: true }, + { outputFile: '' }, + ), ]); expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ @@ -574,7 +597,12 @@ describe('TypeScript Operations Plugin - Enum', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { typesSuffix: 'Z', enumSuffix: false }, { outputFile: '' }), + await plugin( + schema, + [{ document }], + { typesSuffix: 'Z', enumSuffix: false }, + { outputFile: '' }, + ), ]); expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ @@ -641,7 +669,7 @@ describe('TypeScript Operations Plugin - Enum', () => { enumValues: 'keep', }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); expect(result).toMatchInlineSnapshot(` @@ -715,7 +743,7 @@ describe('TypeScript Operations Plugin - Enum', () => { enumValues: 'change-case-all#lowerCase', }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); expect(result).toMatchInlineSnapshot(` @@ -781,7 +809,7 @@ describe('TypeScript Operations Plugin - Enum', () => { { noExport: true, }, - { outputFile: '' } + { outputFile: '' }, ), ]); expect(result).toMatchInlineSnapshot(` @@ -850,7 +878,7 @@ describe('TypeScript Operations Plugin - Enum', () => { UserRole: './files#default as UserRole', // NOTE: `as UserRole` doesn't do anything here, this is here to demonstrate that it's the same as './files#default' }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -909,7 +937,9 @@ describe('TypeScript Operations Plugin - Enum', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { enumType: 'native' }, { outputFile: '' })]); + const result = mergeOutputs([ + await plugin(schema, [{ document }], { enumType: 'native' }, { outputFile: '' }), + ]); expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ @@ -962,7 +992,9 @@ describe('TypeScript Operations Plugin - Enum `%future added value`', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { futureProofEnums: true }, { outputFile: '' })]); + const result = mergeOutputs([ + await plugin(schema, [{ document }], { futureProofEnums: true }, { outputFile: '' }), + ]); expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ @@ -1038,7 +1070,7 @@ describe('TypeScript Operations Plugin - Enum enumValues', () => { }, }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -1120,7 +1152,7 @@ describe('TypeScript Operations Plugin - Enum enumValues', () => { }, }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -1200,7 +1232,7 @@ describe('TypeScript Operations Plugin - Enum enumValues', () => { }, }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -1274,7 +1306,7 @@ describe('TypeScript Operations Plugin - Enum enumValues', () => { UserRole: './my-file#MyEnum', }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -1341,7 +1373,7 @@ describe('TypeScript Operations Plugin - Enum enumValues', () => { UserRole: './my-file#MyEnum', }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -1403,7 +1435,7 @@ describe('TypeScript Operations Plugin - Enum enumValues', () => { UserRole: './my-file#NS.ETest', }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -1476,7 +1508,7 @@ describe('TypeScript Operations Plugin - Enum enumValues', () => { UserRole: './my-file#NS.UserRole', }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -1553,7 +1585,7 @@ describe('TypeScript Operations Plugin - Enum enumValues', () => { enumType: 'native', enumValues: './my-file', }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -1633,7 +1665,7 @@ describe('TypeScript Operations Plugin - Enum enumValues', () => { enumType: 'native', enumValues: { UserRole: './my-file#UserRole', UserStatus: './my-file#UserStatus2X' }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -1700,7 +1732,7 @@ describe('TypeScript Operations Plugin - Enum enumValues', () => { LicenseSKU: './my-file#LicenseSku', }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts index 1519b50e31f..2e9f28d483a 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.import-types.spec.ts @@ -1,6 +1,6 @@ import { buildSchema, parse } from 'graphql'; -import { validateTs } from '@graphql-codegen/testing'; import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; +import { validateTs } from '@graphql-codegen/testing'; import { plugin } from '../src/index.js'; describe('TypeScript Operations Plugin - Import Types', () => { @@ -95,7 +95,7 @@ describe('TypeScript Operations Plugin - Import Types', () => { schema, [{ document }], { importSchemaTypesFrom: './base-dir/path-to-other-file.generated.ts' }, - { outputFile: './base-dir/this-file.ts' } + { outputFile: './base-dir/this-file.ts' }, ), ]); @@ -229,7 +229,7 @@ describe('TypeScript Operations Plugin - Import Types', () => { schema, [{ document }], { importSchemaTypesFrom: '~@my-company/package/types' }, - { outputFile: './base-dir/this-file.ts' } + { outputFile: './base-dir/this-file.ts' }, ), ]); @@ -340,7 +340,12 @@ describe('TypeScript Operations Plugin - Import Types', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { importSchemaTypesFrom: './path-to-other-file' }, { outputFile: '' }), + await plugin( + schema, + [{ document }], + { importSchemaTypesFrom: './path-to-other-file' }, + { outputFile: '' }, + ), ]); expect(result).toMatchInlineSnapshot(` @@ -401,7 +406,7 @@ describe('TypeScript Operations Plugin - Import Types with external custom Scala Scalar1: '@org/scalars#Scalar1', }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); expect(sharedTypeFileResult).toMatchInlineSnapshot(` @@ -426,7 +431,7 @@ describe('TypeScript Operations Plugin - Import Types with external custom Scala Scalar1: '@org/scalars#Scalar1', }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); expect(operationFileResult).toMatchInlineSnapshot(` @@ -478,7 +483,7 @@ describe('TypeScript Operations Plugin - Import Types with external custom Scala Scalar1: '@org/scalars#Scalar1', }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); expect(sharedTypeFileResult).toMatchInlineSnapshot(` @@ -498,7 +503,7 @@ describe('TypeScript Operations Plugin - Import Types with external custom Scala Scalar1: '@org/scalars#Scalar1', }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); expect(operationFileResult).toMatchInlineSnapshot(` @@ -550,7 +555,7 @@ describe('TypeScript Operations Plugin - Import Types with external custom Scala Scalar1: '@org/scalars#Scalar1', }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); expect(sharedTypeFileResult).toMatchInlineSnapshot(` @@ -570,7 +575,7 @@ describe('TypeScript Operations Plugin - Import Types with external custom Scala Scalar1: '@org/scalars#Scalar1', }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); expect(operationFileResult).toMatchInlineSnapshot(` @@ -627,7 +632,7 @@ describe('TypeScript Operations Plugin - Import Types with external custom Scala importSchemaTypesFrom: './base-dir/path-to-other-file.generated.ts', namespacedImportName: 'TypeImport', }, - { outputFile: './base-dir/this-file.ts' } + { outputFile: './base-dir/this-file.ts' }, ), ]); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts index b47e3af2527..9654ad5955f 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.input.spec.ts @@ -1,13 +1,19 @@ +import { buildSchema, parse } from 'graphql'; import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; import { validateTs } from '@graphql-codegen/testing'; -import { buildSchema, parse } from 'graphql'; import { plugin } from '../src/index.js'; describe('TypeScript Operations Plugin - Input', () => { it('generates nested input correctly', async () => { const schema = buildSchema(/* GraphQL */ ` type Query { - users(input: UsersInput!, ageRange1: [Int], ageRange2: [Int]!, ageRange3: [Int!], ageRange4: [Int!]!): [User!]! + users( + input: UsersInput! + ageRange1: [Int] + ageRange2: [Int]! + ageRange3: [Int!] + ageRange4: [Int!]! + ): [User!]! } type User { @@ -88,7 +94,7 @@ describe('TypeScript Operations Plugin - Input', () => { DateTime: 'Date', }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -211,7 +217,7 @@ describe('TypeScript Operations Plugin - Input', () => { }, immutableTypes: true, }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -322,7 +328,7 @@ describe('TypeScript Operations Plugin - Input', () => { DateTime: 'Date', }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -423,7 +429,7 @@ describe('TypeScript Operations Plugin - Input', () => { DateTime: 'Date', }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.scalars.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.scalars.spec.ts index ea8726487aa..bd9caeecf20 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.scalars.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.scalars.spec.ts @@ -1,6 +1,6 @@ +import { buildSchema, parse } from 'graphql'; import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; import { validateTs } from '@graphql-codegen/testing'; -import { buildSchema, parse } from 'graphql'; import { plugin } from '../src/index.js'; describe('TypeScript Operations Plugin - Default Scalar types', () => { @@ -350,7 +350,7 @@ describe('TypeScript Operations Plugin - Custom Scalars', () => { UnusedScalar: 'scalars#UnusedScalar', }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -400,7 +400,13 @@ describe('TypeScript Operations Plugin - Custom Scalars', () => { scalar UnusedScalar `); const document = parse(/* GraphQL */ ` - query User($userInput: UserInput, $scalar4: Scalar4, $scalar5: Scalar5, $scalar6: Scalar6, $scalar7: Scalar7) { + query User( + $userInput: UserInput + $scalar4: Scalar4 + $scalar5: Scalar5 + $scalar6: Scalar6 + $scalar7: Scalar7 + ) { user { id } @@ -426,7 +432,7 @@ describe('TypeScript Operations Plugin - Custom Scalars', () => { UnusedScalar: 'scalars#UnusedScalar', }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -541,7 +547,7 @@ describe('TypeScript Operations Plugin - Custom Scalars', () => { UnusedScalar: 'scalars#UnusedScalar', }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -664,7 +670,7 @@ describe('TypeScript Operations Plugin - Custom Scalars', () => { UnusedScalar: 'scalars#UnusedScalar', }, }, - { outputFile: '' } + { outputFile: '' }, ), ]); diff --git a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts index 5c7a5db8a65..f0b004a2517 100644 --- a/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts +++ b/packages/plugins/typescript/operations/tests/ts-documents.standalone.spec.ts @@ -1,6 +1,6 @@ +import { buildSchema, parse } from 'graphql'; import { mergeOutputs } from '@graphql-codegen/plugin-helpers'; import { validateTs } from '@graphql-codegen/testing'; -import { buildSchema, parse } from 'graphql'; import { plugin } from '../src/index.js'; describe('TypeScript Operations Plugin - Standalone', () => { @@ -327,7 +327,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { }, { outputFile: '', - } + }, ), ]); @@ -394,7 +394,12 @@ describe('TypeScript Operations Plugin - Standalone', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document }], { scalars: { ID: 'string | number | boolean' } }, { outputFile: '' }), + await plugin( + schema, + [{ document }], + { scalars: { ID: 'string | number | boolean' } }, + { outputFile: '' }, + ), ]); expect(result).toMatchInlineSnapshot(` @@ -509,7 +514,12 @@ describe('TypeScript Operations Plugin - Standalone', () => { `); const result = mergeOutputs([ - await plugin(schema, [{ document: documentMain }, { document: documentWithFragment }], {}, { outputFile: '' }), + await plugin( + schema, + [{ document: documentMain }, { document: documentWithFragment }], + {}, + { outputFile: '' }, + ), ]); expect(result).toMatchInlineSnapshot(` @@ -801,7 +811,7 @@ describe('TypeScript Operations Plugin - Standalone', () => { skipTypeNameForRoot: true, nonOptionalTypename: true, }, - { outputFile: '' } + { outputFile: '' }, ), ]); @@ -897,7 +907,9 @@ describe('TypeScript Operations Plugin - Standalone', () => { } `); - const result = mergeOutputs([await plugin(schema, [{ document }], { globalNamespace: true }, { outputFile: '' })]); + const result = mergeOutputs([ + await plugin(schema, [{ document }], { globalNamespace: true }, { outputFile: '' }), + ]); expect(result).toMatchInlineSnapshot(` "/** Internal type. DO NOT USE DIRECTLY. */ diff --git a/packages/plugins/typescript/resolvers/tests/ts-resolvers.spec.ts b/packages/plugins/typescript/resolvers/tests/ts-resolvers.spec.ts index 178aa9552f3..42ba8100198 100644 --- a/packages/plugins/typescript/resolvers/tests/ts-resolvers.spec.ts +++ b/packages/plugins/typescript/resolvers/tests/ts-resolvers.spec.ts @@ -2450,9 +2450,6 @@ export type ResolverFn = ( expect(output.content).toContain( `export type GqlAuthDirectiveArgs = {\n role?: Maybe;\n};`, ); // Note: `GqlUserRole` will be imported from `@org/package` by `typescript` plugin - expect(output.content).toContain( - `export type GqlAuthDirectiveArgs = {\n role?: Maybe;\n};`, - ); expect(output.content).toContain( `export type GqlAuthDirectiveResolver = DirectiveResolverFn;`, ); diff --git a/website/src/pages/plugins/presets/preset-client.mdx b/website/src/pages/plugins/presets/preset-client.mdx index 4997e3cb63f..9c3f4ba5dc8 100644 --- a/website/src/pages/plugins/presets/preset-client.mdx +++ b/website/src/pages/plugins/presets/preset-client.mdx @@ -51,7 +51,7 @@ The `client` preset allows the following `config` options: - [`scalars`](/plugins/typescript/typescript-operations#scalars): Extends or overrides the built-in scalars and custom GraphQL scalars to a custom type. - [`defaultScalarType`](/plugins/typescript/typescript-operations#defaultscalartype): Allows you to - override the type that unknown `scalars` will have. Defaults to `any`. + override the type that unknown `scalars` will have. Defaults to `unknown`. - [`strictScalars`](/plugins/typescript/typescript-operations#strictscalars): If `scalars` are found in the schema that are not defined in scalars an error will be thrown during codegen. - [`namingConvention`](/plugins/typescript/typescript-operations#namingconvention): Available case From eb41159d047f15f84648ca3282322ef660a92d63 Mon Sep 17 00:00:00 2001 From: Arda TANRIKULU Date: Mon, 13 Apr 2026 09:52:26 -0400 Subject: [PATCH 69/69] feat(cli): use `ESM` by default (#10705) * feat(cli): use `ESM` by default * Update graphql-codegen-esm to use esm/bin.js --- .changeset/wacky-books-post.md | 14 ++++++++++++++ packages/graphql-codegen-cli/package.json | 9 +++++---- 2 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 .changeset/wacky-books-post.md diff --git a/.changeset/wacky-books-post.md b/.changeset/wacky-books-post.md new file mode 100644 index 00000000000..47fca5fee43 --- /dev/null +++ b/.changeset/wacky-books-post.md @@ -0,0 +1,14 @@ +--- +'@graphql-codegen/cli': patch +--- + +Use ESM for CLI instead of CJS; + +For backwards compatibility; `graphql-codegen-esm` is reserved, and also `graphql-codegen-cjs` is added for users who want to use CJS. + +So the commands are; +- `graphql-codegen` - ESM version, default +- `graphql-codegen-esm` - ESM version, same as above, but reserved for backwards compatibility +- `graphql-codegen-cjs` - CJS version, for users who want to use CJS, but not recommended for new users. Will be removed in the future. +- `gql-gen` - ESM version, same as `graphql-codegen` +- `graphql-code-generator` - ESM version, same as `graphql-codegen` and `gql-gen` diff --git a/packages/graphql-codegen-cli/package.json b/packages/graphql-codegen-cli/package.json index c732d160bef..60b1261577e 100644 --- a/packages/graphql-codegen-cli/package.json +++ b/packages/graphql-codegen-cli/package.json @@ -17,10 +17,11 @@ "node": ">=16" }, "bin": { - "gql-gen": "dist/cjs/bin.js", - "graphql-codegen": "dist/cjs/bin.js", - "graphql-code-generator": "dist/cjs/bin.js", - "graphql-codegen-esm": "dist/esm/bin.js" + "gql-gen": "dist/esm/bin.js", + "graphql-codegen": "dist/esm/bin.js", + "graphql-code-generator": "dist/esm/bin.js", + "graphql-codegen-esm": "dist/esm/bin.js", + "graphql-codegen-cjs": "dist/cjs/bin.js" }, "main": "dist/cjs/index.js", "module": "dist/esm/index.js",