Skip to content

Commit fa96556

Browse files
committed
Handle errors instead of swallowing them when ignoreNoDocuments=true
1 parent c5efba3 commit fa96556

File tree

8 files changed

+4439
-2974
lines changed

8 files changed

+4439
-2974
lines changed

.changeset/lazy-snails-fold.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@graphql-codegen/cli': patch
3+
---
4+
5+
Fix ignoreNoDocuments=true swallowing all errors

packages/graphql-codegen-cli/src/codegen.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
normalizeOutputParam,
1212
Types,
1313
} from '@graphql-codegen/plugin-helpers';
14+
import { NoTypeDefinitionsFound } from '@graphql-tools/load';
1415
import { DocumentNode, GraphQLError, GraphQLSchema } from 'graphql';
1516
import { Listr, ListrTask } from 'listr2';
1617
import { CodegenContext, ensureContext, shouldEmitLegacyCommonJSImports } from './config.js';
@@ -279,7 +280,7 @@ export async function executeCodegen(input: CodegenContext | Types.Config): Prom
279280
documents,
280281
};
281282
} catch (error) {
282-
if (config.ignoreNoDocuments) {
283+
if (error instanceof NoTypeDefinitionsFound && config.ignoreNoDocuments) {
283284
return {
284285
documents: [],
285286
};

packages/graphql-codegen-cli/src/load.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { JsonFileLoader } from '@graphql-tools/json-file-loader';
99
import {
1010
loadDocuments as loadDocumentsToolkit,
1111
loadSchema as loadSchemaToolkit,
12+
NoTypeDefinitionsFound,
1213
UnnormalizedTypeDefPointer,
1314
} from '@graphql-tools/load';
1415
import { PrismaLoader } from '@graphql-tools/prisma-loader';
@@ -101,7 +102,12 @@ export async function loadDocuments(
101102
});
102103
return loadedFromToolkit;
103104
} catch (error) {
104-
if (config.ignoreNoDocuments) return [];
105+
// NoTypeDefinitionsFound from `@graphql-tools/load` already has a message with pointer, so we can just rethrow the error
106+
if (error instanceof NoTypeDefinitionsFound) {
107+
throw error;
108+
}
109+
110+
// For other errors, we need to add an error message with documentPointers, so it's better for DevX
105111
throw new Error(
106112
[`Failed to load documents from ${Object.keys(documentPointers).join(',')}:`, printError(error)].join('\n')
107113
);

packages/graphql-codegen-cli/tests/generate-and-save.spec.ts

+90-19
Original file line numberDiff line numberDiff line change
@@ -77,22 +77,6 @@ describe('generate-and-save', () => {
7777
expect(writeSpy).not.toHaveBeenCalled();
7878
});
7979

80-
test('should not error when ignoreNoDocuments config option is present', async () => {
81-
jest.spyOn(fs, 'writeFile').mockImplementation();
82-
const config = await createContext({
83-
config: './tests/test-files/graphql.config.json',
84-
project: undefined,
85-
errorsOnly: true,
86-
overwrite: true,
87-
profile: true,
88-
require: [],
89-
silent: false,
90-
watch: false,
91-
});
92-
93-
await generate(config, false);
94-
});
95-
9680
test('should use global overwrite option and write a file', async () => {
9781
const filename = 'overwrite.ts';
9882
const writeSpy = jest.spyOn(fs, 'writeFile').mockImplementation();
@@ -255,11 +239,11 @@ describe('generate-and-save', () => {
255239
expect(writeSpy).toHaveBeenCalled();
256240
});
257241

258-
describe('Syntax errors when loading pointers', () => {
242+
describe('Errors when loading pointers', () => {
259243
const originalConsole = { ...console };
260244
const originalNodeEnv = process.env.NODE_ENV;
261245

262-
let consoleErrorMock;
246+
let consoleErrorMock: jest.Mock;
263247

264248
beforeEach(() => {
265249
// Mock common console functions to avoid noise in the terminal
@@ -279,7 +263,8 @@ describe('generate-and-save', () => {
279263
process.env.NODE_ENV = originalNodeEnv;
280264
});
281265

282-
test('Schema syntax error - should print native GraphQLError for', async () => {
266+
test('Schema syntax error - should print native GraphQLError', async () => {
267+
expect.assertions(4);
283268
try {
284269
await generate(
285270
{
@@ -324,6 +309,7 @@ describe('generate-and-save', () => {
324309
});
325310

326311
test('Document syntax error - should print native GraphQLError', async () => {
312+
expect.assertions(4);
327313
try {
328314
await generate(
329315
{
@@ -352,5 +338,90 @@ describe('generate-and-save', () => {
352338
`);
353339
}
354340
});
341+
342+
test('No documents found - should throw error by default', async () => {
343+
expect.assertions(1);
344+
try {
345+
await generate(
346+
{
347+
verbose: true,
348+
schema: './tests/test-files/schema-dir/schema.ts',
349+
documents: './tests/test-files/document-file-does-not-exist.graphql',
350+
generates: {
351+
'src/test.ts': {
352+
plugins: ['typescript'],
353+
},
354+
},
355+
},
356+
false
357+
);
358+
} catch {
359+
expect(consoleErrorMock.mock.calls[0][0]).toBeSimilarStringTo(`
360+
[FAILED] Unable to find any GraphQL type definitions for the following pointers:
361+
[FAILED]
362+
[FAILED] - ./tests/test-files/document-file-does-not-exist.graphql
363+
`);
364+
}
365+
});
366+
367+
test('No documents found - should not fail if ignoreNoDocuments=true', async () => {
368+
await generate(
369+
{
370+
verbose: true,
371+
ignoreNoDocuments: true,
372+
schema: './tests/test-files/schema-dir/schema.ts',
373+
documents: './tests/test-files/document-file-does-not-exist.graphql',
374+
generates: {
375+
'src/test.ts': {
376+
plugins: ['typescript'],
377+
},
378+
},
379+
},
380+
false
381+
);
382+
expect(consoleErrorMock).not.toHaveBeenCalled();
383+
});
384+
385+
test('No documents found - GraphQL Config - should throw error by default', async () => {
386+
expect.assertions(1);
387+
try {
388+
const config = await createContext({
389+
config: './tests/test-files/graphql.config.no-doc.js',
390+
project: undefined,
391+
errorsOnly: true,
392+
overwrite: true,
393+
profile: true,
394+
require: [],
395+
silent: false,
396+
watch: false,
397+
});
398+
399+
await generate(config, false);
400+
} catch {
401+
expect(consoleErrorMock.mock.calls[0][0]).toBeSimilarStringTo(`
402+
[FAILED]
403+
[FAILED] Unable to find any GraphQL type definitions for the following pointers:
404+
[FAILED]
405+
[FAILED] - ../test-documents/empty.graphql
406+
`);
407+
}
408+
});
409+
test('No documents found - GraphQL Config - should not fail if ignoreNoDocuments=true', async () => {
410+
jest.spyOn(fs, 'writeFile').mockImplementation();
411+
const config = await createContext({
412+
config: './tests/test-files/graphql.config.no-doc-ignored.js',
413+
project: undefined,
414+
errorsOnly: true,
415+
overwrite: true,
416+
profile: true,
417+
require: [],
418+
silent: false,
419+
watch: false,
420+
});
421+
422+
await generate(config, false);
423+
424+
expect(consoleErrorMock).not.toHaveBeenCalled();
425+
});
355426
});
356427
});

packages/graphql-codegen-cli/tests/test-files/graphql.config.json

-14
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/** @type {import('graphql-config').IGraphQLConfig } */
2+
module.exports = {
3+
schema: ['../test-documents/schema.graphql'],
4+
documents: ['../test-documents/empty.graphql'],
5+
extensions: {
6+
codegen: {
7+
verbose: true,
8+
ignoreNoDocuments: true,
9+
generates: {
10+
'./gql/': {
11+
preset: 'client',
12+
},
13+
},
14+
},
15+
},
16+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/** @type {import('graphql-config').IGraphQLConfig } */
2+
module.exports = {
3+
schema: ['../test-documents/schema.graphql'],
4+
documents: ['../test-documents/empty.graphql'],
5+
extensions: {
6+
codegen: {
7+
verbose: true,
8+
generates: {
9+
'./gql/': {
10+
preset: 'client',
11+
},
12+
},
13+
},
14+
},
15+
};

0 commit comments

Comments
 (0)