From 3422ae74fc8741461388a5dfba8889786583686f Mon Sep 17 00:00:00 2001 From: Nicola Marcacci Rossi Date: Mon, 22 Jun 2026 08:29:59 +0000 Subject: [PATCH 1/2] fix: prevent duplicate client type declarations with graphql-codegen v7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since graphql-codegen v7 the `typescript-operations` plugin re-emits every enum and input-object type used by an operation into its own output, which collided with the `typescript` plugin when both wrote to a single `client/index.ts` — declaring every used `*Where`/`Create*`/`Update*` input and every used enum twice (TS2300) and clashing enums as `enum` vs string-literal `type` alias (TS2567) in consumers' generated client types. Split the client output into `client/schema.ts` (full schema types via the `typescript` plugin) and `client/index.ts` (operation types via `typescript-operations`), wiring the latter to the former with `importSchemaTypesFrom` and re-exporting via `export * from './schema'` so the public import surface is unchanged. See dotansimha/graphql-code-generator#10782. Add a regression test asserting the generated client output has no duplicate declarations, and regenerate the test fixtures. Co-Authored-By: Claude Opus 4.8 --- src/bin/gqm/codegen.ts | 20 +- tests/generated/api/index.ts | 7 +- tests/generated/client/index.ts | 1044 +--------------------- tests/generated/client/schema.ts | 968 ++++++++++++++++++++ tests/unit/generate-client-types.spec.ts | 43 + 5 files changed, 1070 insertions(+), 1012 deletions(-) create mode 100644 tests/generated/client/schema.ts create mode 100644 tests/unit/generate-client-types.spec.ts diff --git a/src/bin/gqm/codegen.ts b/src/bin/gqm/codegen.ts index 41d4032e..5bce5a86 100644 --- a/src/bin/gqm/codegen.ts +++ b/src/bin/gqm/codegen.ts @@ -35,12 +35,30 @@ export const generateGraphqlClientTypes = async () => { schema: `${generatedFolderPath}/schema.graphql`, documents: [graphqlQueriesPath, `${generatedFolderPath}/client/mutations.ts`], generates: { + // The schema types and the operation types are emitted into two separate files on purpose. + // Since `@graphql-codegen/typescript-operations` v6 the operations plugin re-emits every enum + // and input-object type that an operation uses directly into its own output, unless + // `importSchemaTypesFrom` is set. Running it together with the `typescript` plugin in a single + // file therefore declares every used `*Where`/`Create*`/`Update*` input and every used enum + // twice (`TS2300: Duplicate identifier`), and `ReactionType`-style enums additionally clash as + // an `enum` (typescript) vs a string-literal `type` alias (typescript-operations) (`TS2567`). + // Splitting schema types into their own file and pointing the operations plugin at them via + // `importSchemaTypesFrom` is the upstream-recommended fix, see + // dotansimha/graphql-code-generator#10782. + [`${generatedFolderPath}/client/schema.ts`]: { + plugins: ['typescript', { add: { content: `import type { Time } from '@smartive/graphql-magic';` } }], + }, + // `export * from './schema'` keeps the public surface unchanged: consumers can still import + // both the schema types and the operation types from the single `client` entrypoint. [`${generatedFolderPath}/client/index.ts`]: { plugins: [ - 'typescript', 'typescript-operations', + { add: { content: `export * from './schema';` } }, { add: { content: `import type { Time } from '@smartive/graphql-magic';` } }, ], + config: { + importSchemaTypesFrom: `${generatedFolderPath}/client/schema`, + }, }, }, config: { diff --git a/tests/generated/api/index.ts b/tests/generated/api/index.ts index 0bf9d45f..c792a947 100644 --- a/tests/generated/api/index.ts +++ b/tests/generated/api/index.ts @@ -3,11 +3,6 @@ import { DateTime } from 'luxon'; import type { Time } from '@smartive/graphql-magic'; 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 }; -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 */ @@ -19,7 +14,7 @@ export type Scalars = { Float: { input: number; output: number; } DateTime: { input: DateTime; output: DateTime; } Time: { input: Time; output: Time; } - Upload: { input: any; output: any; } + Upload: { input: unknown; output: unknown; } }; export type AnotherObject = { diff --git a/tests/generated/client/index.ts b/tests/generated/client/index.ts index 5a728eda..702ff295 100644 --- a/tests/generated/client/index.ts +++ b/tests/generated/client/index.ts @@ -1,977 +1,11 @@ -import type { Time } from '@smartive/graphql-magic'; -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 }; +/** 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 }; -/** 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; } - DateTime: { input: string; output: string; } - Time: { input: Time; output: Time; } - Upload: { input: any; output: any; } -}; - -export type AnotherObject = { - deleteRootId: Maybe; - deleteRootType: Maybe; - deleted: Scalars['Boolean']['output']; - deletedAt: Maybe; - deletedBy: Maybe; - id: Scalars['ID']['output']; - manyObjects: Array; - myself: Maybe; - name: Maybe; - self: Maybe; -}; - - -export type AnotherObjectmanyObjectsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - search?: InputMaybe; - where?: InputMaybe; -}; - - -export type AnotherObjectselfArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - -export type AnotherObjectOrderBy = { - deletedAt?: InputMaybe; - name?: InputMaybe; -}; - -export type AnotherObjectSubWhere = { - AND?: InputMaybe>; - NOT?: InputMaybe; - OR?: InputMaybe>; - id?: InputMaybe>; - manyObjects_NONE?: InputMaybe; - manyObjects_SOME?: InputMaybe; -}; - -export type AnotherObjectWhere = { - AND?: InputMaybe>; - NOT?: InputMaybe; - OR?: InputMaybe>; - id?: InputMaybe>; - manyObjects_NONE?: InputMaybe; - manyObjects_SOME?: InputMaybe; -}; - -export type AnotherObjectWhereLookup = { - id?: InputMaybe; -}; - -export type AnotherObjectWhereUnique = { - id?: InputMaybe; -}; - -export type Answer = Reaction & { - childAnswers: Array; - childQuestions: Array; - childReactions: Array; - childReviews: Array; - content: Maybe; - createdAt: Scalars['DateTime']['output']; - createdBy: User; - deleteRootId: Maybe; - deleteRootType: Maybe; - deleted: Scalars['Boolean']['output']; - deletedAt: Maybe; - deletedBy: Maybe; - id: Scalars['ID']['output']; - parent: Maybe; - type: ReactionType; - updatedAt: Scalars['DateTime']['output']; - updatedBy: User; -}; - - -export type AnswerchildAnswersArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type AnswerchildQuestionsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type AnswerchildReactionsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type AnswerchildReviewsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - -export type AnswerOrderBy = { - createdAt?: InputMaybe; - deletedAt?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type AnswerSubWhere = { - AND?: InputMaybe>; - NOT?: InputMaybe; - OR?: InputMaybe>; - id?: InputMaybe>; -}; - -export type AnswerWhere = { - AND?: InputMaybe>; - NOT?: InputMaybe; - OR?: InputMaybe>; - id?: InputMaybe>; -}; - -export type AnswerWhereLookup = { - id?: InputMaybe; -}; - -export type AnswerWhereUnique = { - id?: InputMaybe; -}; - -export type Bird = Duck | Eagle; - -export type CreateAnswer = { - content?: InputMaybe; -}; - -export type CreateQuestion = { - content?: InputMaybe; -}; - -export type CreateReview = { - content?: InputMaybe; - rating?: InputMaybe; -}; - -export type CreateSomeObject = { - time?: InputMaybe; - xyz: Scalars['Int']['input']; -}; - -export type Duck = { - name: Maybe; -}; - -export type Eagle = { - name: Maybe; -}; - -export type Mutation = { - createAnswer: Answer; - createQuestion: Question; - createReview: Review; - createSomeObject: SomeObject; - deleteAnotherObject: Scalars['ID']['output']; - deleteAnswer: Scalars['ID']['output']; - deleteQuestion: Scalars['ID']['output']; - deleteReview: Scalars['ID']['output']; - deleteSomeObject: Scalars['ID']['output']; - restoreAnotherObject: Scalars['ID']['output']; - restoreAnswer: Scalars['ID']['output']; - restoreQuestion: Scalars['ID']['output']; - restoreReview: Scalars['ID']['output']; - restoreSomeObject: Scalars['ID']['output']; - updateAnswer: Answer; - updateQuestion: Question; - updateReview: Review; - updateSomeObject: SomeObject; -}; - - -export type MutationcreateAnswerArgs = { - data: CreateAnswer; -}; - - -export type MutationcreateQuestionArgs = { - data: CreateQuestion; -}; - - -export type MutationcreateReviewArgs = { - data: CreateReview; -}; - - -export type MutationcreateSomeObjectArgs = { - data: CreateSomeObject; -}; - - -export type MutationdeleteAnotherObjectArgs = { - dryRun?: InputMaybe; - where: AnotherObjectWhereUnique; -}; - - -export type MutationdeleteAnswerArgs = { - dryRun?: InputMaybe; - where: AnswerWhereUnique; -}; - - -export type MutationdeleteQuestionArgs = { - dryRun?: InputMaybe; - where: QuestionWhereUnique; -}; - - -export type MutationdeleteReviewArgs = { - dryRun?: InputMaybe; - where: ReviewWhereUnique; -}; - - -export type MutationdeleteSomeObjectArgs = { - dryRun?: InputMaybe; - where: SomeObjectWhereUnique; -}; - - -export type MutationrestoreAnotherObjectArgs = { - where: AnotherObjectWhereUnique; -}; - - -export type MutationrestoreAnswerArgs = { - where: AnswerWhereUnique; -}; - - -export type MutationrestoreQuestionArgs = { - where: QuestionWhereUnique; -}; - - -export type MutationrestoreReviewArgs = { - where: ReviewWhereUnique; -}; - - -export type MutationrestoreSomeObjectArgs = { - where: SomeObjectWhereUnique; -}; - - -export type MutationupdateAnswerArgs = { - data: UpdateAnswer; - where: AnswerWhereUnique; -}; - - -export type MutationupdateQuestionArgs = { - data: UpdateQuestion; - where: QuestionWhereUnique; -}; - - -export type MutationupdateReviewArgs = { - data: UpdateReview; - where: ReviewWhereUnique; -}; - - -export type MutationupdateSomeObjectArgs = { - data: UpdateSomeObject; - where: SomeObjectWhereUnique; -}; - -export enum Order { - ASC = 'ASC', - DESC = 'DESC' -} - -export type Query = { - anotherObjects: Array; - answer: Answer; - answers: Array; - birds: Array; - manyObjects: Array; - me: Maybe; - question: Question; - questions: Array; - reaction: Reaction; - reactions: Array; - review: Review; - reviews: Array; - someObject: SomeObject; -}; - - -export type QueryanotherObjectsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type QueryanswerArgs = { - deleted?: InputMaybe; - where: AnswerWhereLookup; -}; - - -export type QueryanswersArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type QuerymanyObjectsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - search?: InputMaybe; - where?: InputMaybe; -}; - - -export type QueryquestionArgs = { - deleted?: InputMaybe; - where: QuestionWhereLookup; -}; - - -export type QueryquestionsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type QueryreactionArgs = { - deleted?: InputMaybe; - where: ReactionWhereLookup; -}; - - -export type QueryreactionsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type QueryreviewArgs = { - deleted?: InputMaybe; - where: ReviewWhereLookup; -}; - - -export type QueryreviewsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type QuerysomeObjectArgs = { - deleted?: InputMaybe; - where: SomeObjectWhereLookup; -}; - -export type Question = Reaction & { - childAnswers: Array; - childQuestions: Array; - childReactions: Array; - childReviews: Array; - content: Maybe; - createdAt: Scalars['DateTime']['output']; - createdBy: User; - deleteRootId: Maybe; - deleteRootType: Maybe; - deleted: Scalars['Boolean']['output']; - deletedAt: Maybe; - deletedBy: Maybe; - id: Scalars['ID']['output']; - parent: Maybe; - type: ReactionType; - updatedAt: Scalars['DateTime']['output']; - updatedBy: User; -}; - - -export type QuestionchildAnswersArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type QuestionchildQuestionsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type QuestionchildReactionsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type QuestionchildReviewsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - -export type QuestionOrderBy = { - createdAt?: InputMaybe; - deletedAt?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type QuestionSubWhere = { - AND?: InputMaybe>; - NOT?: InputMaybe; - OR?: InputMaybe>; - id?: InputMaybe>; -}; - -export type QuestionWhere = { - AND?: InputMaybe>; - NOT?: InputMaybe; - OR?: InputMaybe>; - id?: InputMaybe>; -}; - -export type QuestionWhereLookup = { - id?: InputMaybe; -}; - -export type QuestionWhereUnique = { - id?: InputMaybe; -}; - -export type Reaction = { - childAnswers: Array; - childQuestions: Array; - childReactions: Array; - childReviews: Array; - content: Maybe; - createdAt: Scalars['DateTime']['output']; - createdBy: User; - deleteRootId: Maybe; - deleteRootType: Maybe; - deleted: Scalars['Boolean']['output']; - deletedAt: Maybe; - deletedBy: Maybe; - id: Scalars['ID']['output']; - parent: Maybe; - type: ReactionType; - updatedAt: Scalars['DateTime']['output']; - updatedBy: User; -}; - - -export type ReactionchildAnswersArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type ReactionchildQuestionsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type ReactionchildReactionsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type ReactionchildReviewsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - -export type ReactionOrderBy = { - createdAt?: InputMaybe; - deletedAt?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type ReactionSubWhere = { - AND?: InputMaybe>; - NOT?: InputMaybe; - OR?: InputMaybe>; - id?: InputMaybe>; -}; - -export enum ReactionType { - Answer = 'Answer', - Question = 'Question', - Review = 'Review' -} - -export type ReactionWhere = { - AND?: InputMaybe>; - NOT?: InputMaybe; - OR?: InputMaybe>; - id?: InputMaybe>; -}; - -export type ReactionWhereLookup = { - id?: InputMaybe; -}; - -export type ReactionWhereUnique = { - id?: InputMaybe; -}; - -export type Review = Reaction & { - childAnswers: Array; - childQuestions: Array; - childReactions: Array; - childReviews: Array; - content: Maybe; - createdAt: Scalars['DateTime']['output']; - createdBy: User; - deleteRootId: Maybe; - deleteRootType: Maybe; - deleted: Scalars['Boolean']['output']; - deletedAt: Maybe; - deletedBy: Maybe; - id: Scalars['ID']['output']; - parent: Maybe; - rating: Maybe; - type: ReactionType; - updatedAt: Scalars['DateTime']['output']; - updatedBy: User; -}; - - -export type ReviewchildAnswersArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type ReviewchildQuestionsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type ReviewchildReactionsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type ReviewchildReviewsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - -export type ReviewOrderBy = { - createdAt?: InputMaybe; - deletedAt?: InputMaybe; - updatedAt?: InputMaybe; -}; - -export type ReviewSubWhere = { - AND?: InputMaybe>; - NOT?: InputMaybe; - OR?: InputMaybe>; - id?: InputMaybe>; - rating_GT?: InputMaybe; - rating_GTE?: InputMaybe; - rating_LT?: InputMaybe; - rating_LTE?: InputMaybe; -}; - -export type ReviewWhere = { - AND?: InputMaybe>; - NOT?: InputMaybe; - OR?: InputMaybe>; - id?: InputMaybe>; - rating_GT?: InputMaybe; - rating_GTE?: InputMaybe; - rating_LT?: InputMaybe; - rating_LTE?: InputMaybe; -}; - -export type ReviewWhereLookup = { - id?: InputMaybe; -}; - -export type ReviewWhereUnique = { - id?: InputMaybe; -}; - -export enum Role { - ADMIN = 'ADMIN', - USER = 'USER' -} - -export enum SomeEnum { - A = 'A', - B = 'B', - C = 'C' -} - -export type SomeObject = { - another: Maybe; - createdAt: Scalars['DateTime']['output']; - createdBy: User; - deleteRootId: Maybe; - deleteRootType: Maybe; - deleted: Scalars['Boolean']['output']; - deletedAt: Maybe; - deletedBy: Maybe; - field: Maybe; - float: Scalars['Float']['output']; - id: Scalars['ID']['output']; - list: Array; - time: Maybe; - updatedAt: Scalars['DateTime']['output']; - updatedBy: User; - xyz: Scalars['Int']['output']; -}; - - -export type SomeObjectlistArgs = { - magic?: InputMaybe; -}; - -export type SomeObjectOrderBy = { - createdAt?: InputMaybe; - deletedAt?: InputMaybe; - updatedAt?: InputMaybe; - xyz?: InputMaybe; -}; - -export type SomeObjectSubWhere = { - AND?: InputMaybe>; - NOT?: InputMaybe; - OR?: InputMaybe>; - another?: InputMaybe; - field?: InputMaybe>; - float?: InputMaybe>; - id?: InputMaybe>; - xyz?: InputMaybe>; -}; - -export type SomeObjectWhere = { - AND?: InputMaybe>; - NOT?: InputMaybe; - OR?: InputMaybe>; - another?: InputMaybe; - field?: InputMaybe>; - float?: InputMaybe>; - id?: InputMaybe>; - xyz?: InputMaybe>; -}; - -export type SomeObjectWhereLookup = { - id?: InputMaybe; -}; - -export type SomeObjectWhereUnique = { - id?: InputMaybe; -}; - -export type SomeRawObject = { - field: Maybe; -}; - -export type UpdateAnswer = { - content?: InputMaybe; -}; - -export type UpdateQuestion = { - content?: InputMaybe; -}; - -export type UpdateReview = { - content?: InputMaybe; - rating?: InputMaybe; -}; - -export type UpdateSomeObject = { - anotherId?: InputMaybe; - time?: InputMaybe; - xyz?: InputMaybe; -}; - -export type User = { - createdAnswers: Array; - createdManyObjects: Array; - createdQuestions: Array; - createdReactions: Array; - createdReviews: Array; - deletedAnotherObjects: Array; - deletedAnswers: Array; - deletedManyObjects: Array; - deletedQuestions: Array; - deletedReactions: Array; - deletedReviews: Array; - id: Scalars['ID']['output']; - role: Role; - updatedAnswers: Array; - updatedManyObjects: Array; - updatedQuestions: Array; - updatedReactions: Array; - updatedReviews: Array; - username: Maybe; -}; - - -export type UsercreatedAnswersArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type UsercreatedManyObjectsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - search?: InputMaybe; - where?: InputMaybe; -}; - - -export type UsercreatedQuestionsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type UsercreatedReactionsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type UsercreatedReviewsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type UserdeletedAnotherObjectsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type UserdeletedAnswersArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type UserdeletedManyObjectsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - search?: InputMaybe; - where?: InputMaybe; -}; - - -export type UserdeletedQuestionsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type UserdeletedReactionsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type UserdeletedReviewsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type UserupdatedAnswersArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type UserupdatedManyObjectsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - search?: InputMaybe; - where?: InputMaybe; -}; - - -export type UserupdatedQuestionsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type UserupdatedReactionsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - - -export type UserupdatedReviewsArgs = { - deleted?: InputMaybe; - limit?: InputMaybe; - offset?: InputMaybe; - orderBy?: InputMaybe>; - where?: InputMaybe; -}; - -export type UserSubWhere = { - AND?: InputMaybe>; - NOT?: InputMaybe; - OR?: InputMaybe>; - id?: InputMaybe>; -}; - -export type UserWhere = { - AND?: InputMaybe>; - NOT?: InputMaybe; - OR?: InputMaybe>; - id?: InputMaybe>; -}; - -export type UserWhereLookup = { - id?: InputMaybe; -}; - -export type UserWhereUnique = { - id?: InputMaybe; -}; +import type * as Types from './schema'; +import type { Time } from '@smartive/graphql-magic'; +export * from './schema'; export type DeleteAnotherObjectMutationVariables = Exact<{ [key: string]: never; }>; @@ -986,40 +20,40 @@ export type GetReactionsQueryVariables = Exact<{ [key: string]: never; }>; export type GetReactionsQuery = { reactions: Array< - | { type: ReactionType, content: string | null } - | { type: ReactionType, content: string | null } - | { rating: number | null, type: ReactionType, content: string | null } + | { type: Types.ReactionType, content: string | null } + | { type: Types.ReactionType, content: string | null } + | { rating: number | null, type: Types.ReactionType, content: string | null } > }; export type GetReactionQueryVariables = Exact<{ [key: string]: never; }>; export type GetReactionQuery = { reaction: - | { type: ReactionType, content: string | null } - | { type: ReactionType, content: string | null } - | { rating: number | null, type: ReactionType, content: string | null } + | { type: Types.ReactionType, content: string | null } + | { type: Types.ReactionType, content: string | null } + | { rating: number | null, type: Types.ReactionType, content: string | null } }; export type GetReviewsQueryVariables = Exact<{ [key: string]: never; }>; -export type GetReviewsQuery = { reviews: Array<{ type: ReactionType, content: string | null, rating: number | null }> }; +export type GetReviewsQuery = { reviews: Array<{ type: Types.ReactionType, content: string | null, rating: number | null }> }; export type GetReviewQueryVariables = Exact<{ [key: string]: never; }>; -export type GetReviewQuery = { review: { type: ReactionType, content: string | null, rating: number | null } }; +export type GetReviewQuery = { review: { type: Types.ReactionType, content: string | null, rating: number | null } }; export type CreateReviewMutationVariables = Exact<{ - data: CreateReview; + data: Types.CreateReview; }>; export type CreateReviewMutation = { createReview: { content: string | null, rating: number | null } }; export type UpdateReviewMutationVariables = Exact<{ - id: Scalars['ID']['input']; - data: UpdateReview; + id: string | number; + data: Types.UpdateReview; }>; @@ -1066,130 +100,130 @@ export type NullRelationFilterQueryQueryVariables = Exact<{ [key: string]: never export type NullRelationFilterQueryQuery = { all: Array<{ id: string, another: { id: string } | null }>, withNullAnother: Array<{ id: string, another: { id: string } | null }>, withNotNullAnother: Array<{ id: string, another: { id: string } | null }> }; export type DeleteAnotherObjectMutationMutationVariables = Exact<{ - id: Scalars['ID']['input']; + id: string | number; }>; export type DeleteAnotherObjectMutationMutation = { deleteAnotherObject: string }; export type RestoreAnotherObjectMutationMutationVariables = Exact<{ - id: Scalars['ID']['input']; + id: string | number; }>; export type RestoreAnotherObjectMutationMutation = { restoreAnotherObject: string }; export type CreateSomeObjectMutationMutationVariables = Exact<{ - data: CreateSomeObject; + data: Types.CreateSomeObject; }>; export type CreateSomeObjectMutationMutation = { createSomeObject: { id: string } }; export type UpdateSomeObjectMutationMutationVariables = Exact<{ - id: Scalars['ID']['input']; - data: UpdateSomeObject; + id: string | number; + data: Types.UpdateSomeObject; }>; export type UpdateSomeObjectMutationMutation = { updateSomeObject: { id: string } }; export type DeleteSomeObjectMutationMutationVariables = Exact<{ - id: Scalars['ID']['input']; + id: string | number; }>; export type DeleteSomeObjectMutationMutation = { deleteSomeObject: string }; export type RestoreSomeObjectMutationMutationVariables = Exact<{ - id: Scalars['ID']['input']; + id: string | number; }>; export type RestoreSomeObjectMutationMutation = { restoreSomeObject: string }; export type CreateReviewMutationMutationVariables = Exact<{ - data: CreateReview; + data: Types.CreateReview; }>; export type CreateReviewMutationMutation = { createReview: { id: string } }; export type UpdateReviewMutationMutationVariables = Exact<{ - id: Scalars['ID']['input']; - data: UpdateReview; + id: string | number; + data: Types.UpdateReview; }>; export type UpdateReviewMutationMutation = { updateReview: { id: string } }; export type DeleteReviewMutationMutationVariables = Exact<{ - id: Scalars['ID']['input']; + id: string | number; }>; export type DeleteReviewMutationMutation = { deleteReview: string }; export type RestoreReviewMutationMutationVariables = Exact<{ - id: Scalars['ID']['input']; + id: string | number; }>; export type RestoreReviewMutationMutation = { restoreReview: string }; export type CreateQuestionMutationMutationVariables = Exact<{ - data: CreateQuestion; + data: Types.CreateQuestion; }>; export type CreateQuestionMutationMutation = { createQuestion: { id: string } }; export type UpdateQuestionMutationMutationVariables = Exact<{ - id: Scalars['ID']['input']; - data: UpdateQuestion; + id: string | number; + data: Types.UpdateQuestion; }>; export type UpdateQuestionMutationMutation = { updateQuestion: { id: string } }; export type DeleteQuestionMutationMutationVariables = Exact<{ - id: Scalars['ID']['input']; + id: string | number; }>; export type DeleteQuestionMutationMutation = { deleteQuestion: string }; export type RestoreQuestionMutationMutationVariables = Exact<{ - id: Scalars['ID']['input']; + id: string | number; }>; export type RestoreQuestionMutationMutation = { restoreQuestion: string }; export type CreateAnswerMutationMutationVariables = Exact<{ - data: CreateAnswer; + data: Types.CreateAnswer; }>; export type CreateAnswerMutationMutation = { createAnswer: { id: string } }; export type UpdateAnswerMutationMutationVariables = Exact<{ - id: Scalars['ID']['input']; - data: UpdateAnswer; + id: string | number; + data: Types.UpdateAnswer; }>; export type UpdateAnswerMutationMutation = { updateAnswer: { id: string } }; export type DeleteAnswerMutationMutationVariables = Exact<{ - id: Scalars['ID']['input']; + id: string | number; }>; export type DeleteAnswerMutationMutation = { deleteAnswer: string }; export type RestoreAnswerMutationMutationVariables = Exact<{ - id: Scalars['ID']['input']; + id: string | number; }>; diff --git a/tests/generated/client/schema.ts b/tests/generated/client/schema.ts new file mode 100644 index 00000000..1006c9a8 --- /dev/null +++ b/tests/generated/client/schema.ts @@ -0,0 +1,968 @@ +import type { Time } from '@smartive/graphql-magic'; +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; } + DateTime: { input: string; output: string; } + Time: { input: Time; output: Time; } + Upload: { input: unknown; output: unknown; } +}; + +export type AnotherObject = { + deleteRootId: Maybe; + deleteRootType: Maybe; + deleted: Scalars['Boolean']['output']; + deletedAt: Maybe; + deletedBy: Maybe; + id: Scalars['ID']['output']; + manyObjects: Array; + myself: Maybe; + name: Maybe; + self: Maybe; +}; + + +export type AnotherObjectmanyObjectsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + search?: InputMaybe; + where?: InputMaybe; +}; + + +export type AnotherObjectselfArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + +export type AnotherObjectOrderBy = { + deletedAt?: InputMaybe; + name?: InputMaybe; +}; + +export type AnotherObjectSubWhere = { + AND?: InputMaybe>; + NOT?: InputMaybe; + OR?: InputMaybe>; + id?: InputMaybe>; + manyObjects_NONE?: InputMaybe; + manyObjects_SOME?: InputMaybe; +}; + +export type AnotherObjectWhere = { + AND?: InputMaybe>; + NOT?: InputMaybe; + OR?: InputMaybe>; + id?: InputMaybe>; + manyObjects_NONE?: InputMaybe; + manyObjects_SOME?: InputMaybe; +}; + +export type AnotherObjectWhereLookup = { + id?: InputMaybe; +}; + +export type AnotherObjectWhereUnique = { + id?: InputMaybe; +}; + +export type Answer = Reaction & { + childAnswers: Array; + childQuestions: Array; + childReactions: Array; + childReviews: Array; + content: Maybe; + createdAt: Scalars['DateTime']['output']; + createdBy: User; + deleteRootId: Maybe; + deleteRootType: Maybe; + deleted: Scalars['Boolean']['output']; + deletedAt: Maybe; + deletedBy: Maybe; + id: Scalars['ID']['output']; + parent: Maybe; + type: ReactionType; + updatedAt: Scalars['DateTime']['output']; + updatedBy: User; +}; + + +export type AnswerchildAnswersArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type AnswerchildQuestionsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type AnswerchildReactionsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type AnswerchildReviewsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + +export type AnswerOrderBy = { + createdAt?: InputMaybe; + deletedAt?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type AnswerSubWhere = { + AND?: InputMaybe>; + NOT?: InputMaybe; + OR?: InputMaybe>; + id?: InputMaybe>; +}; + +export type AnswerWhere = { + AND?: InputMaybe>; + NOT?: InputMaybe; + OR?: InputMaybe>; + id?: InputMaybe>; +}; + +export type AnswerWhereLookup = { + id?: InputMaybe; +}; + +export type AnswerWhereUnique = { + id?: InputMaybe; +}; + +export type Bird = Duck | Eagle; + +export type CreateAnswer = { + content?: InputMaybe; +}; + +export type CreateQuestion = { + content?: InputMaybe; +}; + +export type CreateReview = { + content?: InputMaybe; + rating?: InputMaybe; +}; + +export type CreateSomeObject = { + time?: InputMaybe; + xyz: Scalars['Int']['input']; +}; + +export type Duck = { + name: Maybe; +}; + +export type Eagle = { + name: Maybe; +}; + +export type Mutation = { + createAnswer: Answer; + createQuestion: Question; + createReview: Review; + createSomeObject: SomeObject; + deleteAnotherObject: Scalars['ID']['output']; + deleteAnswer: Scalars['ID']['output']; + deleteQuestion: Scalars['ID']['output']; + deleteReview: Scalars['ID']['output']; + deleteSomeObject: Scalars['ID']['output']; + restoreAnotherObject: Scalars['ID']['output']; + restoreAnswer: Scalars['ID']['output']; + restoreQuestion: Scalars['ID']['output']; + restoreReview: Scalars['ID']['output']; + restoreSomeObject: Scalars['ID']['output']; + updateAnswer: Answer; + updateQuestion: Question; + updateReview: Review; + updateSomeObject: SomeObject; +}; + + +export type MutationcreateAnswerArgs = { + data: CreateAnswer; +}; + + +export type MutationcreateQuestionArgs = { + data: CreateQuestion; +}; + + +export type MutationcreateReviewArgs = { + data: CreateReview; +}; + + +export type MutationcreateSomeObjectArgs = { + data: CreateSomeObject; +}; + + +export type MutationdeleteAnotherObjectArgs = { + dryRun?: InputMaybe; + where: AnotherObjectWhereUnique; +}; + + +export type MutationdeleteAnswerArgs = { + dryRun?: InputMaybe; + where: AnswerWhereUnique; +}; + + +export type MutationdeleteQuestionArgs = { + dryRun?: InputMaybe; + where: QuestionWhereUnique; +}; + + +export type MutationdeleteReviewArgs = { + dryRun?: InputMaybe; + where: ReviewWhereUnique; +}; + + +export type MutationdeleteSomeObjectArgs = { + dryRun?: InputMaybe; + where: SomeObjectWhereUnique; +}; + + +export type MutationrestoreAnotherObjectArgs = { + where: AnotherObjectWhereUnique; +}; + + +export type MutationrestoreAnswerArgs = { + where: AnswerWhereUnique; +}; + + +export type MutationrestoreQuestionArgs = { + where: QuestionWhereUnique; +}; + + +export type MutationrestoreReviewArgs = { + where: ReviewWhereUnique; +}; + + +export type MutationrestoreSomeObjectArgs = { + where: SomeObjectWhereUnique; +}; + + +export type MutationupdateAnswerArgs = { + data: UpdateAnswer; + where: AnswerWhereUnique; +}; + + +export type MutationupdateQuestionArgs = { + data: UpdateQuestion; + where: QuestionWhereUnique; +}; + + +export type MutationupdateReviewArgs = { + data: UpdateReview; + where: ReviewWhereUnique; +}; + + +export type MutationupdateSomeObjectArgs = { + data: UpdateSomeObject; + where: SomeObjectWhereUnique; +}; + +export enum Order { + ASC = 'ASC', + DESC = 'DESC' +} + +export type Query = { + anotherObjects: Array; + answer: Answer; + answers: Array; + birds: Array; + manyObjects: Array; + me: Maybe; + question: Question; + questions: Array; + reaction: Reaction; + reactions: Array; + review: Review; + reviews: Array; + someObject: SomeObject; +}; + + +export type QueryanotherObjectsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type QueryanswerArgs = { + deleted?: InputMaybe; + where: AnswerWhereLookup; +}; + + +export type QueryanswersArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type QuerymanyObjectsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + search?: InputMaybe; + where?: InputMaybe; +}; + + +export type QueryquestionArgs = { + deleted?: InputMaybe; + where: QuestionWhereLookup; +}; + + +export type QueryquestionsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type QueryreactionArgs = { + deleted?: InputMaybe; + where: ReactionWhereLookup; +}; + + +export type QueryreactionsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type QueryreviewArgs = { + deleted?: InputMaybe; + where: ReviewWhereLookup; +}; + + +export type QueryreviewsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type QuerysomeObjectArgs = { + deleted?: InputMaybe; + where: SomeObjectWhereLookup; +}; + +export type Question = Reaction & { + childAnswers: Array; + childQuestions: Array; + childReactions: Array; + childReviews: Array; + content: Maybe; + createdAt: Scalars['DateTime']['output']; + createdBy: User; + deleteRootId: Maybe; + deleteRootType: Maybe; + deleted: Scalars['Boolean']['output']; + deletedAt: Maybe; + deletedBy: Maybe; + id: Scalars['ID']['output']; + parent: Maybe; + type: ReactionType; + updatedAt: Scalars['DateTime']['output']; + updatedBy: User; +}; + + +export type QuestionchildAnswersArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type QuestionchildQuestionsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type QuestionchildReactionsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type QuestionchildReviewsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + +export type QuestionOrderBy = { + createdAt?: InputMaybe; + deletedAt?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type QuestionSubWhere = { + AND?: InputMaybe>; + NOT?: InputMaybe; + OR?: InputMaybe>; + id?: InputMaybe>; +}; + +export type QuestionWhere = { + AND?: InputMaybe>; + NOT?: InputMaybe; + OR?: InputMaybe>; + id?: InputMaybe>; +}; + +export type QuestionWhereLookup = { + id?: InputMaybe; +}; + +export type QuestionWhereUnique = { + id?: InputMaybe; +}; + +export type Reaction = { + childAnswers: Array; + childQuestions: Array; + childReactions: Array; + childReviews: Array; + content: Maybe; + createdAt: Scalars['DateTime']['output']; + createdBy: User; + deleteRootId: Maybe; + deleteRootType: Maybe; + deleted: Scalars['Boolean']['output']; + deletedAt: Maybe; + deletedBy: Maybe; + id: Scalars['ID']['output']; + parent: Maybe; + type: ReactionType; + updatedAt: Scalars['DateTime']['output']; + updatedBy: User; +}; + + +export type ReactionchildAnswersArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type ReactionchildQuestionsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type ReactionchildReactionsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type ReactionchildReviewsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + +export type ReactionOrderBy = { + createdAt?: InputMaybe; + deletedAt?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type ReactionSubWhere = { + AND?: InputMaybe>; + NOT?: InputMaybe; + OR?: InputMaybe>; + id?: InputMaybe>; +}; + +export enum ReactionType { + Answer = 'Answer', + Question = 'Question', + Review = 'Review' +} + +export type ReactionWhere = { + AND?: InputMaybe>; + NOT?: InputMaybe; + OR?: InputMaybe>; + id?: InputMaybe>; +}; + +export type ReactionWhereLookup = { + id?: InputMaybe; +}; + +export type ReactionWhereUnique = { + id?: InputMaybe; +}; + +export type Review = Reaction & { + childAnswers: Array; + childQuestions: Array; + childReactions: Array; + childReviews: Array; + content: Maybe; + createdAt: Scalars['DateTime']['output']; + createdBy: User; + deleteRootId: Maybe; + deleteRootType: Maybe; + deleted: Scalars['Boolean']['output']; + deletedAt: Maybe; + deletedBy: Maybe; + id: Scalars['ID']['output']; + parent: Maybe; + rating: Maybe; + type: ReactionType; + updatedAt: Scalars['DateTime']['output']; + updatedBy: User; +}; + + +export type ReviewchildAnswersArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type ReviewchildQuestionsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type ReviewchildReactionsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type ReviewchildReviewsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + +export type ReviewOrderBy = { + createdAt?: InputMaybe; + deletedAt?: InputMaybe; + updatedAt?: InputMaybe; +}; + +export type ReviewSubWhere = { + AND?: InputMaybe>; + NOT?: InputMaybe; + OR?: InputMaybe>; + id?: InputMaybe>; + rating_GT?: InputMaybe; + rating_GTE?: InputMaybe; + rating_LT?: InputMaybe; + rating_LTE?: InputMaybe; +}; + +export type ReviewWhere = { + AND?: InputMaybe>; + NOT?: InputMaybe; + OR?: InputMaybe>; + id?: InputMaybe>; + rating_GT?: InputMaybe; + rating_GTE?: InputMaybe; + rating_LT?: InputMaybe; + rating_LTE?: InputMaybe; +}; + +export type ReviewWhereLookup = { + id?: InputMaybe; +}; + +export type ReviewWhereUnique = { + id?: InputMaybe; +}; + +export enum Role { + ADMIN = 'ADMIN', + USER = 'USER' +} + +export enum SomeEnum { + A = 'A', + B = 'B', + C = 'C' +} + +export type SomeObject = { + another: Maybe; + createdAt: Scalars['DateTime']['output']; + createdBy: User; + deleteRootId: Maybe; + deleteRootType: Maybe; + deleted: Scalars['Boolean']['output']; + deletedAt: Maybe; + deletedBy: Maybe; + field: Maybe; + float: Scalars['Float']['output']; + id: Scalars['ID']['output']; + list: Array; + time: Maybe; + updatedAt: Scalars['DateTime']['output']; + updatedBy: User; + xyz: Scalars['Int']['output']; +}; + + +export type SomeObjectlistArgs = { + magic?: InputMaybe; +}; + +export type SomeObjectOrderBy = { + createdAt?: InputMaybe; + deletedAt?: InputMaybe; + updatedAt?: InputMaybe; + xyz?: InputMaybe; +}; + +export type SomeObjectSubWhere = { + AND?: InputMaybe>; + NOT?: InputMaybe; + OR?: InputMaybe>; + another?: InputMaybe; + field?: InputMaybe>; + float?: InputMaybe>; + id?: InputMaybe>; + xyz?: InputMaybe>; +}; + +export type SomeObjectWhere = { + AND?: InputMaybe>; + NOT?: InputMaybe; + OR?: InputMaybe>; + another?: InputMaybe; + field?: InputMaybe>; + float?: InputMaybe>; + id?: InputMaybe>; + xyz?: InputMaybe>; +}; + +export type SomeObjectWhereLookup = { + id?: InputMaybe; +}; + +export type SomeObjectWhereUnique = { + id?: InputMaybe; +}; + +export type SomeRawObject = { + field: Maybe; +}; + +export type UpdateAnswer = { + content?: InputMaybe; +}; + +export type UpdateQuestion = { + content?: InputMaybe; +}; + +export type UpdateReview = { + content?: InputMaybe; + rating?: InputMaybe; +}; + +export type UpdateSomeObject = { + anotherId?: InputMaybe; + time?: InputMaybe; + xyz?: InputMaybe; +}; + +export type User = { + createdAnswers: Array; + createdManyObjects: Array; + createdQuestions: Array; + createdReactions: Array; + createdReviews: Array; + deletedAnotherObjects: Array; + deletedAnswers: Array; + deletedManyObjects: Array; + deletedQuestions: Array; + deletedReactions: Array; + deletedReviews: Array; + id: Scalars['ID']['output']; + role: Role; + updatedAnswers: Array; + updatedManyObjects: Array; + updatedQuestions: Array; + updatedReactions: Array; + updatedReviews: Array; + username: Maybe; +}; + + +export type UsercreatedAnswersArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type UsercreatedManyObjectsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + search?: InputMaybe; + where?: InputMaybe; +}; + + +export type UsercreatedQuestionsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type UsercreatedReactionsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type UsercreatedReviewsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type UserdeletedAnotherObjectsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type UserdeletedAnswersArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type UserdeletedManyObjectsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + search?: InputMaybe; + where?: InputMaybe; +}; + + +export type UserdeletedQuestionsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type UserdeletedReactionsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type UserdeletedReviewsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type UserupdatedAnswersArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type UserupdatedManyObjectsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + search?: InputMaybe; + where?: InputMaybe; +}; + + +export type UserupdatedQuestionsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type UserupdatedReactionsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + + +export type UserupdatedReviewsArgs = { + deleted?: InputMaybe; + limit?: InputMaybe; + offset?: InputMaybe; + orderBy?: InputMaybe>; + where?: InputMaybe; +}; + +export type UserSubWhere = { + AND?: InputMaybe>; + NOT?: InputMaybe; + OR?: InputMaybe>; + id?: InputMaybe>; +}; + +export type UserWhere = { + AND?: InputMaybe>; + NOT?: InputMaybe; + OR?: InputMaybe>; + id?: InputMaybe>; +}; + +export type UserWhereLookup = { + id?: InputMaybe; +}; + +export type UserWhereUnique = { + id?: InputMaybe; +}; diff --git a/tests/unit/generate-client-types.spec.ts b/tests/unit/generate-client-types.spec.ts new file mode 100644 index 00000000..20a6bd70 --- /dev/null +++ b/tests/unit/generate-client-types.spec.ts @@ -0,0 +1,43 @@ +import { readFileSync } from 'fs'; +import { join } from 'path'; + +/** + * Regression test for the duplicate-identifier breakage that the graphql-codegen v7 upgrade (#490) + * surfaced in the generated client types. + * + * Since `@graphql-codegen/typescript-operations` v6, the operations plugin re-emits every enum and + * input-object type used by an operation into its own output unless `importSchemaTypesFrom` is set. + * Running it together with the `typescript` plugin in a single file therefore declared every used + * `*Where`/`Create*`/`Update*` input and every used enum twice (`TS2300`), and enums additionally + * clashed as an `enum` vs a string-literal `type` alias (`TS2567`). The fix (see `codegen.ts`) + * emits schema types and operation types into separate files and wires the operations plugin to the + * shared schema types via `importSchemaTypesFrom`. + * + * This asserts the generated client output (regenerated and committed via `gqm generate`) is free of + * duplicate declarations — the exact check that would have caught #490. + */ +describe('generated client types', () => { + const clientDir = join(__dirname, '..', 'generated', 'client'); + const files = ['schema.ts', 'index.ts']; + + const declarationsOf = (content: string) => + [...content.matchAll(/^(?:export )?(?:type|enum|interface) (\w+)\b/gm)].map((match) => match[1]); + + it.each(files)('does not declare any identifier twice in %s', (file) => { + const declarations = declarationsOf(readFileSync(join(clientDir, file), 'utf8')); + const duplicates = [...new Set(declarations.filter((name, index) => declarations.indexOf(name) !== index))]; + expect(duplicates).toEqual([]); + }); + + it('declares each schema type exactly once across the client output', () => { + const declarations = files.flatMap((file) => declarationsOf(readFileSync(join(clientDir, file), 'utf8'))); + + // These were each emitted twice before the fix (once by `typescript`, once by `typescript-operations`). + for (const name of ['CreateReview', 'UpdateReview', 'ReactionType', 'ReviewWhere', 'UserWhere']) { + expect({ name, count: declarations.filter((declaration) => declaration === name).length }).toEqual({ + name, + count: 1, + }); + } + }); +}); From a707ac78c43d3a8c78257c028814a60441836d36 Mon Sep 17 00:00:00 2001 From: Nicola Marcacci Rossi Date: Mon, 22 Jun 2026 08:44:42 +0000 Subject: [PATCH 2/2] fix: import the Time scalar conditionally in generated client types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Map the `Time` scalar via its module (`@smartive/graphql-magic#Time`) and enable `useTypeImports`, instead of injecting the import with a hard-coded `add` plugin. The `add` import landed in the operations file (`client/index.ts`) unconditionally; a consumer with `noUnusedLocals` whose client operations never select a `Time` field would have hit `TS6133: 'Time' is declared but its value is never read` — a failure mode the previous single-file layout didn't have. graphql-codegen now emits the `Time` import only in the files that actually use it. The committed test fixtures are unchanged (their operations do use `Time`). Co-Authored-By: Claude Opus 4.8 --- src/bin/gqm/codegen.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/bin/gqm/codegen.ts b/src/bin/gqm/codegen.ts index 5bce5a86..127c23ae 100644 --- a/src/bin/gqm/codegen.ts +++ b/src/bin/gqm/codegen.ts @@ -46,16 +46,12 @@ export const generateGraphqlClientTypes = async () => { // `importSchemaTypesFrom` is the upstream-recommended fix, see // dotansimha/graphql-code-generator#10782. [`${generatedFolderPath}/client/schema.ts`]: { - plugins: ['typescript', { add: { content: `import type { Time } from '@smartive/graphql-magic';` } }], + plugins: ['typescript'], }, // `export * from './schema'` keeps the public surface unchanged: consumers can still import // both the schema types and the operation types from the single `client` entrypoint. [`${generatedFolderPath}/client/index.ts`]: { - plugins: [ - 'typescript-operations', - { add: { content: `export * from './schema';` } }, - { add: { content: `import type { Time } from '@smartive/graphql-magic';` } }, - ], + plugins: ['typescript-operations', { add: { content: `export * from './schema';` } }], config: { importSchemaTypesFrom: `${generatedFolderPath}/client/schema`, }, @@ -71,8 +67,12 @@ export const generateGraphqlClientTypes = async () => { }, scalars: { DateTime: 'string', - Time: 'Time', + // Reference the `Time` type via its module so codegen imports it only in the files that + // actually use it. A hard-coded `add` import would land in the operations file too and trip + // `noUnusedLocals` for consumers whose operations never select a `Time` field. + Time: '@smartive/graphql-magic#Time', }, + useTypeImports: true, // Emit `import type` for the scalar (and any other type) imports ignoreNoDocuments: true, }, });