Skip to content

Commit

Permalink
fix: ensure operations with GraphQL magic comment are only parsed onc…
Browse files Browse the repository at this point in the history
…e. (#3143)
  • Loading branch information
n1ru4l authored Jul 6, 2021
1 parent f6115d3 commit f1d7b3c
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/ninety-spies-care.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphql-tools/graphql-tag-pluck': patch
---

ensure operations with GraphQL magic comment are only parsed once.
17 changes: 13 additions & 4 deletions packages/graphql-tag-pluck/src/visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ export default (code: string, out: any, options: GraphQLTagPluckOptions = {}) =>
// Will result with ['gql', 'graphql']
const definedIdentifierNames: string[] = [];

const alreadyProcessedOperationsCache = new Set<string>();
// Will accumulate all template literals
const gqlTemplateLiterals: PluckedContent[] = [];

Expand Down Expand Up @@ -194,6 +195,15 @@ export default (code: string, out: any, options: GraphQLTagPluckOptions = {}) =>
);
};

const addTemplateLiteralToResult = (content: PluckedContent) => {
const cacheKey = `end/${content.end}/start/${content.start}/${content.content}`;
if (alreadyProcessedOperationsCache.has(cacheKey)) {
return;
}
alreadyProcessedOperationsCache.add(cacheKey);
gqlTemplateLiterals.push(content);
};

// Push all template literals leaded by graphql magic comment
// e.g. /* GraphQL */ `query myQuery {}` -> query myQuery {}
const pluckMagicTemplateLiteral = (node: any, takeExpression = false) => {
Expand All @@ -215,9 +225,8 @@ export default (code: string, out: any, options: GraphQLTagPluckOptions = {}) =>

const nodeToUse = takeExpression ? node.expression : node;
const gqlTemplateLiteral = pluckStringFromFile(nodeToUse);

if (gqlTemplateLiteral) {
gqlTemplateLiterals.push({
addTemplateLiteralToResult({
content: gqlTemplateLiteral,
loc: node.loc,
end: node.end,
Expand Down Expand Up @@ -262,7 +271,7 @@ export default (code: string, out: any, options: GraphQLTagPluckOptions = {}) =>
// If the entire template was made out of interpolations it should be an empty
// string by now and thus should be ignored
if (gqlTemplateLiteral) {
gqlTemplateLiterals.push({
addTemplateLiteralToResult({
content: gqlTemplateLiteral,
loc,
end,
Expand Down Expand Up @@ -344,7 +353,7 @@ export default (code: string, out: any, options: GraphQLTagPluckOptions = {}) =>
const gqlTemplateLiteral = pluckStringFromFile(path.node.quasi);

if (gqlTemplateLiteral) {
gqlTemplateLiterals.push({
addTemplateLiteralToResult({
content: gqlTemplateLiteral,
end: path.node.quasi.end,
start: path.node.quasi.start,
Expand Down
22 changes: 22 additions & 0 deletions packages/graphql-tag-pluck/tests/graphql-tag-pluck.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1207,6 +1207,28 @@ describe('graphql-tag-pluck', () => {
`));
});

it('should pluck graphql-tag template literals from code string with /* GraphQL */ comment', async () => {
const sources = await pluck('test.js', freeText(`
import gql from 'graphql-tag'
const doc = gql(/* GraphQL */ \`
query foo {
foo {
foo
}
}
\`)
`));

expect(sources.map(source => source.body).join('\n\n')).toEqual(freeText(`
query foo {
foo {
foo
}
}
`));
})

it('should pluck graphql-tag template literals from a .js file', async () => {
const sources = await pluck('tmp-XXXXXX.js', freeText(`
import gql from 'graphql-tag'
Expand Down

0 comments on commit f1d7b3c

Please sign in to comment.