Skip to content

Commit

Permalink
Fix double imports (#6548)
Browse files Browse the repository at this point in the history
* Deduplicate generated imports

* Generate changeset

* Add comments; remove unnecessary imports
  • Loading branch information
nbudin authored Aug 24, 2021
1 parent 35199de commit 263570e
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/shiny-eels-smell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphql-codegen/visitor-plugin-common': patch
---

Don't generate duplicate imports for the same identifier
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,35 @@ export class ClientSideBaseVisitor<
documentMode === DocumentMode.string ||
documentMode === DocumentMode.documentNodeImportFragments
) {
fragmentImports.forEach(fragmentImport => {
// keep track of what imports we've already generated so we don't try
// to import the same identifier twice
const alreadyImported = new Map<string, Set<string>>();

const deduplicatedImports = fragmentImports
.map(fragmentImport => {
const { path, identifiers } = fragmentImport.importSource;
if (!alreadyImported.has(path)) {
alreadyImported.set(path, new Set<string>());
}

const alreadyImportedForPath = alreadyImported.get(path);
const newIdentifiers = identifiers.filter(identifier => !alreadyImportedForPath.has(identifier.name));
newIdentifiers.forEach(newIdentifier => alreadyImportedForPath.add(newIdentifier.name));

// filter the set of identifiers in this fragment import to only
// the ones we haven't already imported from this path
return {
...fragmentImport,
importSource: {
...fragmentImport.importSource,
identifiers: newIdentifiers,
},
};
})
// remove any imports that now have no identifiers in them
.filter(fragmentImport => fragmentImport.importSource.identifiers.length > 0);

deduplicatedImports.forEach(fragmentImport => {
if (fragmentImport.outputPath !== fragmentImport.importSource.path) {
this._imports.add(generateFragmentImportStatement(fragmentImport, 'document'));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import gql from 'graphql-tag';

export const usernameFragment = gql`
fragment usernameFragment on User {
username
}
`;

export const userFields = gql`
fragment userFields on User {
...usernameFragment
email
}
${usernameFragment}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import gql from 'graphql-tag';
import { userFields, usernameFragment } from './issue-6546-fragments';

export const limitedUserFieldsQuery = gql`
query user {
user(id: "1") {
...usernameFragment
}
}
${usernameFragment}
`;

export const userAndFriendQuery = gql`
query allUserFields {
user(id: "1") {
...userFields
}
friend: user(id: "2") {
...usernameFragment
}
}
${userFields}
${usernameFragment}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,41 @@ export type CQuery = { __typename?: 'Query', a?: Types.Maybe<string> };

expect(result[0].content).not.toMatch(`import { UserFieldsFragmentDoc }`);
});

it('#6546 - duplicate fragment imports', async () => {
const result = await executeCodegen({
schema: [
/* GraphQL */ `
type Query {
user(id: String!): User!
}
type User {
id: String!
email: String
username: String
}
`,
],
documents: [
path.join(__dirname, 'fixtures/issue-6546-queries.ts'),
path.join(__dirname, 'fixtures/issue-6546-fragments.ts'),
],
generates: {
'out1.ts': {
preset: preset,
presetConfig: {
baseTypesPath: 'types.ts',
},
plugins: ['typescript-operations', 'typescript-react-apollo'],
},
},
});

const queriesContent = result.find(generatedDoc => generatedDoc.filename.match(/issue-6546-queries/)).content;
const imports = queriesContent.match(/import.*UsernameFragmentFragmentDoc/g);
expect(imports).toHaveLength(1);
});
});

it('Should build the correct operation files paths', async () => {
Expand Down

0 comments on commit 263570e

Please sign in to comment.