Skip to content

Commit

Permalink
Fix/multi project (#7968)
Browse files Browse the repository at this point in the history
* ✅ NEW: failing test

* 🐛 FIX: duplicated documents (#6282)

* 💡 DOC: add a bit of doc around project flag

* 👌 FIX: prettier

* doc: wording fix

* Create fifty-jars-end.md

Co-authored-by: Charly POLY <1252066+charlypoly@users.noreply.github.com>
  • Loading branch information
jycouet and charlypoly committed Jul 1, 2022
1 parent 9e735ea commit dfd9f07
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 21 deletions.
5 changes: 5 additions & 0 deletions .changeset/fifty-jars-end.md
@@ -0,0 +1,5 @@
---
"@graphql-codegen/cli": patch
---

Fix/multi project
37 changes: 18 additions & 19 deletions packages/graphql-codegen-cli/src/codegen.ts
Expand Up @@ -218,7 +218,7 @@ export async function executeCodegen(input: CodegenContext | Types.Config): Prom
let outputSchemaAst: GraphQLSchema;
let outputSchema: DocumentNode;
const outputFileTemplateConfig = outputConfig.config || {};
const outputDocuments: Types.DocumentFile[] = [];
let outputDocuments: Types.DocumentFile[] = [];
const outputSpecificSchemas = normalizeInstanceOrArray<Types.Schema>(outputConfig.schema);
const outputSpecificDocuments = normalizeInstanceOrArray<Types.OperationDocument>(outputConfig.documents);

Expand Down Expand Up @@ -264,25 +264,25 @@ export async function executeCodegen(input: CodegenContext | Types.Config): Prom
debugLog(`[CLI] Loading Documents`);

// get different cache for shared docs and output specific docs
const results = await Promise.all(
[rootDocuments, outputSpecificDocuments].map(docs => {
const hash = JSON.stringify(docs);
return cache('documents', hash, async () => {
const documents = await context.loadDocuments(docs);
return {
documents,
};
});
})
);

const documents: Types.DocumentFile[] = [];
const documentPointerMap: any = {};
const allDocumentsUnnormalizedPointers = [...rootDocuments, ...outputSpecificDocuments];
for (const unnormalizedPtr of allDocumentsUnnormalizedPointers) {
if (typeof unnormalizedPtr === 'string') {
documentPointerMap[unnormalizedPtr] = {};
} else if (typeof unnormalizedPtr === 'object') {
Object.assign(documentPointerMap, unnormalizedPtr);
}
}

results.forEach(source => documents.push(...source.documents));
const hash = JSON.stringify(documentPointerMap);
const result = await cache('documents', hash, async () => {
const documents = await context.loadDocuments(documentPointerMap);
return {
documents,
};
});

if (documents.length > 0) {
outputDocuments.push(...documents);
}
outputDocuments = await result.documents;
},
filename,
`Load GraphQL documents: ${filename}`
Expand Down Expand Up @@ -321,7 +321,6 @@ export async function executeCodegen(input: CodegenContext | Types.Config): Prom
};

let outputs: Types.GenerateOptions[] = [];

if (hasPreset) {
outputs = await context.profiler.run(
async () =>
Expand Down
21 changes: 19 additions & 2 deletions packages/graphql-codegen-cli/tests/codegen.spec.ts
@@ -1,8 +1,8 @@
import { useMonorepo } from '@graphql-codegen/testing';
import { GraphQLObjectType, buildSchema, buildASTSchema, parse, print } from 'graphql';
import { mergeTypeDefs } from '@graphql-tools/merge';
import { executeCodegen } from '../src';
import { buildASTSchema, buildSchema, GraphQLObjectType, parse, print } from 'graphql';
import { join } from 'path';
import { createContext, executeCodegen } from '../src';

const SHOULD_NOT_THROW_STRING = 'SHOULD_NOT_THROW';
const SIMPLE_TEST_SCHEMA = `type MyType { f: String } type Query { f: String }`;
Expand Down Expand Up @@ -961,6 +961,7 @@ describe('Codegen Executor', () => {
throw new Error('This should not throw as the invalid file is excluded via glob.');
}
});

it('Should allow plugins to extend schema with custom root', async () => {
try {
const output = await executeCodegen({
Expand Down Expand Up @@ -1067,4 +1068,20 @@ describe('Codegen Executor', () => {
expect(error.message).toContain('Failed to load schema for "out1.graphql"');
}
});

it('Should generate documents output even if prj1/documents and prj1/extensions/codegen/generate/xxx/documents are both definded with the same glob files', async () => {
const prj1 = await createContext({
config: './tests/test-files/graphql.config.js',
project: 'prj1',
errorsOnly: true,
overwrite: true,
profile: true,
require: [],
silent: false,
watch: false,
});
const config = prj1.getConfig();
const output = await executeCodegen(config);
expect(output[0].content).toContain('DocumentNode<MyQueryQuery, MyQueryQueryVariables>');
});
});
21 changes: 21 additions & 0 deletions packages/graphql-codegen-cli/tests/test-files/graphql.config.js
@@ -0,0 +1,21 @@
/** @type {import('graphql-config').IGraphQLConfig } */
module.exports = {
generates: {},
projects: {
prj1: {
schema: ['**/test-documents/schema.graphql'],
documents: ['**/test-documents/valid.graphql'],
extensions: {
codegen: {
generates: {
'graphqlTypes.ts': {
schema: ['**/test-documents/schema.graphql'],
documents: ['**/test-documents/valid.graphql'],
plugins: ['typed-document-node'],
},
},
},
},
},
},
};
2 changes: 2 additions & 0 deletions website/docs/config-reference/codegen-config.mdx
Expand Up @@ -151,6 +151,8 @@ The Codegen also supports several CLI flags that allow you to override the defau

- **`--profile`** - Use the profiler to measure performance. _(see "Profiler" in "Advanced Usage")_

- **`--project` (`-p`)** - To generate only one project out of a [Multi Project](multiproject-config) config file.

<p>&nbsp;</p>

---
Expand Down
62 changes: 62 additions & 0 deletions website/docs/config-reference/multiproject-config.mdx
@@ -0,0 +1,62 @@
---
id: multiproject-config
title: 'Multi Project'
---

In some cases, it's useful to have multiple projects in the same config file.

For example, in a monorepo, the VSCode GraphQL plugin will automatically pick up the right config for the right folder.

<p>&nbsp;</p>

---

<p>&nbsp;</p>

## Configuration file format

Here's an example for a possible config file `graphql.config.js`:

```js
/** @type {import('graphql-config').IGraphQLConfig } */
module.exports = {
projects: {
prj1: {
schema: ['prj1/**/*.graphql'],
documents: ['prj1/**/*.gql'],
extensions: {
codegen: {
generates: {
'graphqlTypes.ts': {
plugins: ['typescript', 'typed-document-node']
}
}
}
}
},
prj2: {
schema: ['prj2/**/*.graphql'],
documents: ['prj2/**/*.gql'],
extensions: {
codegen: {
generates: {
'graphqlTypes.ts': {
plugins: ['typescript', 'typed-document-node']
}
}
}
}
}
}
}
```

<p>&nbsp;</p>

## Command to generate files

With the previous config, you can generate files with the following command:

```bash
graphql-codegen --config graphql.config.js -project prj1
```
1 change: 1 addition & 0 deletions website/routes.ts
Expand Up @@ -35,6 +35,7 @@ export function getRoutes(): IRoutes {
['require-field', 'require field'],
['naming-convention', 'Naming Convention'],
['lifecycle-hooks', 'Lifecycle Hooks'],
['multiproject-config', 'Multi Project'],
],
},
'docs/advanced': {
Expand Down

1 comment on commit dfd9f07

@vercel
Copy link

@vercel vercel bot commented on dfd9f07 Jul 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.