dotansimha / graphql-code-generator

A tool for generating code based on a GraphQL schema and GraphQL operations (query/mutation/subscription), with flexible support for custom plugins.
https://the-guild.dev/graphql/codegen/
MIT License
10.87k stars 1.34k forks source link

Watch generates different files from no watch (graphql-modules) #6851

Open abrenneke opened 3 years ago

abrenneke commented 3 years ago

Describe the bug

Thank you for keeping this important project going! So for some reason, if `--watch 'some/file/glob'` is specified for our monorepo, then the server schema generated from the `graphql-modules` preset can potentially generate using more files than it should be using. In our monorepo, we have an older `schemas` folder with many `.graphql` files defining our schema, and a newer implementation using [graphql-modules](https://www.graphql-code-generator.com/docs/presets/graphql-modules). We generate two schemas, one _only_ from the graphql modules files, and one combining the older schema and the modules schema. If `--watch` specifies all possible files (including the older schema), then the merging happens even in the output file that shouldn't contain the full schema. My guess is that graphql-codegen or the modules preset is adding all possible files into an internal list, and reusing that list during generation instead of re-calculating for each `generates` key in the codegen file. So `--watch` basically augments `schema`, instead of _only_ watching the specified files for changes and keeping `schema` the same. For a workaround I'm going to try watching the glob manually with chokidar or watchman, and re-running `graphql-codegen` from scratch each time. **To Reproduce** Don't have time for a full reproduction project right now, sorry :( (Abbreviated) `codegen.yml`: ```yaml schema: - ./modules/**/*.module.ts: noRequire: true config: onlyResolveTypeForInterfaces: true useTypeImports: true maybeValue: 'T | null | undefined' omitOperationSuffix: true preResolveTypes: false skipTypeNameForRoot: true namingConvention: enumValues: keep scalars: # many scalar definitions mappers: # many mapper definitions generates: # Generate server types and resolver types - modules ../src/modules/: preset: graphql-modules presetConfig: baseTypesPath: ../generated/server.ts filename: generated/module-types.ts encapsulateModuleTypes: none plugins: - typescript - typescript-resolvers # Generate server and resolver types - modules + legacy ../src/generated/server-legacy.ts: schema: ./schema/**/*.graphql # added to "schema" at root plugins: - typescript - typescript-resolvers ``` **Expected behavior** `--watch` should watch the specified files, but the actual files used in each `generates` should not change. **Environment:** - OS: Mac OS ```json { "@graphql-codegen/cli": "^2.2.0", "@graphql-codegen/graphql-modules-preset": "^2.1.4", "@graphql-codegen/schema-ast": "^2.2.0", "@graphql-codegen/typed-document-node": "^2.1.6", "@graphql-codegen/typescript": "^2.2.2", "@graphql-codegen/typescript-operations": "^2.1.8", "@graphql-codegen/typescript-resolvers": "^2.3.0" } ``` - NodeJS: 14.15.1
filenwind commented 2 years ago

I'm facing this problem and create a mini repo to reproduce.

https://github.com/filenwind/graphql-code-generator-watch-bug

The codegen.yml:

schema:
  - "./src/base/**/*.ts"
generates:
  ./src/serviceA/types.ts:
    schema:
      - "./src/serviceA/**/*.ts"
    plugins:
      - typescript
  ./src/serviceB/types.ts:
    schema:
      - "./src/serviceB/**/*.ts"
    plugins:
      - typescript

Reproduce Flow: npm run gql:codegen

./src/serviceA/types.ts

export type Foo = {
  __typename?: 'Foo';
  bar?: Maybe<Scalars['Int']>;
};

export type User = {
  __typename?: 'User';
  email?: Maybe<Scalars['String']>;
  name?: Maybe<Scalars['String']>;
};

npm run gql:codegen:watch

./src/serviceA/types.ts

export type Foo = {
  __typename?: 'Foo';
  bar?: Maybe<Scalars['Int']>;
};

export type Post = {
  __typename?: 'Post';
  context?: Maybe<Scalars['String']>;
  title?: Maybe<Scalars['String']>;
};

export type User = {
  __typename?: 'User';
  email?: Maybe<Scalars['String']>;
  name?: Maybe<Scalars['String']>;
};

You can see the type Post shouldn't emit for ./src/serviceA/types.ts

If I remove the root schema, it will working fine, is the root schema can't using with separate generate schema?

thanks for help!

node -v
v16.13.0