Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/local-fragment-over-external.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphql-codegen/visitor-plugin-common': patch
---

Keep the local definition of a fragment when the same fragment is also passed as an external fragment, so its `*FragmentDoc` is generated again. This fixes `near-operation-file` output for a fragment declared in one `gql` tag and spread by an operation in another `gql` tag of the same file.
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,18 @@ export class ClientSideBaseVisitor<
this._documents = documents;
this._onExecutableDocumentNode = (rawConfig as any).unstable_onExecutableDocumentNode;
this._omitDefinitions = (rawConfig as any).unstable_omitDefinitions;
this._fragments = new Map(fragments.map(fragment => [fragment.name, fragment]));
const fragmentsByName = new Map<string, LoadedFragment>();
for (const fragment of fragments) {
// A fragment can be passed both as a local definition and as an external one, e.g. when
// near-operation-file reports a fragment generated into the same file as external.
// Keep the local definition so its document is still generated.
const existing = fragmentsByName.get(fragment.name);
if (existing && !existing.isExternal && fragment.isExternal) {
continue;
}
fragmentsByName.set(fragment.name, fragment);
}
this._fragments = fragmentsByName;
this.fragmentsGraph = this._getFragmentsGraph();
autoBind(this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -470,3 +470,46 @@ describe('includeExternalFragments', () => {
expect(visitor.fragments).toContain('ExternalAFragment');
});
});

describe('fragments declared locally and passed as external', () => {
const schema = buildSchema(/* GraphQL */ `
type Query {
user: User
}

type User {
id: ID!
name: String
}
`);

const toLoadedFragments = (source: string, isExternal: boolean) =>
parse(source)
.definitions.filter(d => d.kind === Kind.FRAGMENT_DEFINITION)
.map(fragmentDef => ({
node: fragmentDef,
name: fragmentDef.name.value,
onType: fragmentDef.typeCondition.name.value,
isExternal,
}));

const userFields = /* GraphQL */ `
fragment UserFields on User {
id
name
}
`;

// near-operation-file also reports fragments generated into the same file as external,
// so the same fragment reaches the visitor once as local and once as external.
it('should generate the FragmentDoc of the local definition', () => {
const visitor = new ClientSideBaseVisitor(
schema,
[...toLoadedFragments(userFields, false), ...toLoadedFragments(userFields, true)],
{},
{},
);

expect(visitor.fragments).toContain('export const UserFieldsFragmentDoc');
});
});