Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(hasura-allow-list):add config to change fragments definition order #452

Merged
merged 2 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/long-zebras-perform.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@graphql-codegen/hasura-allow-list": minor
---

add config to change fragments definition order
5 changes: 5 additions & 0 deletions packages/plugins/other/hasura-allow-list/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,9 @@ export interface HasuraAllowListPluginConfig {
* @description Whether to source fragments per-document, or globally. If set, will enforce fragment name uniqueness
*/
globalFragments?: boolean;
/**
* @default definition
* @description Whether to order fragments by global definition order, or by definition order in the document
*/
fragmentsOrder?: 'global' | 'document';
}
15 changes: 13 additions & 2 deletions packages/plugins/other/hasura-allow-list/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,23 @@ function getOperationFragmentsRecursively(
operationDefinition: OperationDefinitionNode,
fragmentDefinitions: FragmentDefinitionNode[],
documentLocation: string,
config: HasuraAllowListPluginConfig,
): FragmentDefinitionNode[] {
const requiredFragmentNames = new Set<string>();

getRequiredFragments(operationDefinition);

// note: we first get a list of required fragments names, then filter the original list.
// this means order of fragments is preserved.
// note: we should choose fragmentsOrder config that is compatible with other graphql-codegen plugins we use.
const order = config.fragmentsOrder ?? 'global';

// order of fragments is determined by the order they are defined in the document.
if (order === 'document') {
return Array.from(requiredFragmentNames).map(name =>
fragmentDefinitions.find(definition => definition.name.value === name),
);
}

// order is determined by the global fragments definition order.
return fragmentDefinitions.filter(definition => requiredFragmentNames.has(definition.name.value));

/**
Expand Down Expand Up @@ -147,6 +157,7 @@ export const plugin: PluginFunction<HasuraAllowListPluginConfig> = async (
operation,
fragments,
document.location,
config,
);

// insert the operation and any fragments to our queries definition.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,50 @@ describe('Hasura allow list', () => {

expect(content).toBe(expectedContent);
});
it('with globalFragments enabled and fragmentsOrder set to document, should define fragment by the order they are defined in the document.', async () => {
const expectedContent = `- name: allowed-queries
definition:
queries:
- name: MyQuery1
query: |-
query MyQuery1 {
field
...MyOtherFragment
...MyFragment
}
fragment MyOtherFragment on Query {
field
}
fragment MyFragment on Query {
field
}
`;
const document1 = parse(/* GraphQL */ `
query MyQuery1 {
field
...MyOtherFragment
...MyFragment
}
fragment MyFragment on Query {
field
}
`);
const document2 = parse(/* GraphQL */ `
fragment MyOtherFragment on Query {
field
}
`);
const content = await plugin(
null,
[
{ document: document1, location: '/dummy/location1' },
{ document: document2, location: '/dummy/location2' },
],
{ globalFragments: true, fragmentsOrder: 'document' },
);

expect(content).toBe(expectedContent);
});
it('with globalFragments enabled, should error on missing fragments', async () => {
const document1 = parse(/* GraphQL */ `
query MyQuery1 {
Expand Down