Skip to content

Commit e406153

Browse files
FezVrastaevenchange4
authored andcommitted
fix: remove deduplicate fragments (fix #90) (#94)
* fix: dedupe fragments (fix #90) * fix coverage error
1 parent 87c5b9b commit e406153

File tree

5 files changed

+203
-4
lines changed

5 files changed

+203
-4
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@
1515
"test": "NODE_ENV='test' jest --coverage",
1616
"test:watch": "npm run test -- --watch",
1717
"flow": "flow",
18-
"flow-coverage": "hsu-scripts flow --threshold 71",
18+
"flow-coverage": "hsu-scripts flow --threshold 70",
1919
"eslint": "eslint ./",
2020
"format": "prettier --write '**/*.{js,json,md,css,yaml,yml}' '*.{js,json,md,css,yaml,yml}'",
2121
"changelog": "conventional-changelog --infile ./CHANGELOG.md --same-file --release-count 0 --output-unreleased"
2222
},
2323
"dependencies": {
24+
"@babel/template": "^7.4.4",
2425
"babel-literal-to-ast": "^2.1.0",
2526
"babel-plugin-macros": "^2.5.0",
2627
"graphql-tag": "^2.10.1"

src/__tests__/__snapshots__/macro.test.js.snap

Lines changed: 149 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,153 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3+
exports[`macros [gql] should handle duplicated fragments (issue#90): [gql] should handle duplicated fragments (issue#90) 1`] = `
4+
5+
import { gql } from 'graphql.macro';
6+
const frag1 = gql\`fragment TestDuplicate on Bar { field }\`;
7+
const frag2 = gql\`fragment TestDuplicate on Bar { field }\`;
8+
const query = gql\`{ bar { fieldOne ...TestDuplicate } } \${frag1} \${frag2}\`;
9+
10+
↓ ↓ ↓ ↓ ↓ ↓
11+
12+
const frag1 = {
13+
"kind": "Document",
14+
"definitions": [{
15+
"kind": "FragmentDefinition",
16+
"name": {
17+
"kind": "Name",
18+
"value": "TestDuplicate"
19+
},
20+
"typeCondition": {
21+
"kind": "NamedType",
22+
"name": {
23+
"kind": "Name",
24+
"value": "Bar"
25+
}
26+
},
27+
"directives": [],
28+
"selectionSet": {
29+
"kind": "SelectionSet",
30+
"selections": [{
31+
"kind": "Field",
32+
"name": {
33+
"kind": "Name",
34+
"value": "field"
35+
},
36+
"arguments": [],
37+
"directives": []
38+
}]
39+
}
40+
}],
41+
"loc": {
42+
"start": 0,
43+
"end": 39,
44+
"source": {
45+
"body": "fragment TestDuplicate on Bar { field }",
46+
"name": "GraphQL request",
47+
"locationOffset": {
48+
"line": 1,
49+
"column": 1
50+
}
51+
}
52+
}
53+
};
54+
const frag2 = {
55+
"kind": "Document",
56+
"definitions": [{
57+
"kind": "FragmentDefinition",
58+
"name": {
59+
"kind": "Name",
60+
"value": "TestDuplicate"
61+
},
62+
"typeCondition": {
63+
"kind": "NamedType",
64+
"name": {
65+
"kind": "Name",
66+
"value": "Bar"
67+
}
68+
},
69+
"directives": [],
70+
"selectionSet": {
71+
"kind": "SelectionSet",
72+
"selections": [{
73+
"kind": "Field",
74+
"name": {
75+
"kind": "Name",
76+
"value": "field"
77+
},
78+
"arguments": [],
79+
"directives": []
80+
}]
81+
}
82+
}],
83+
"loc": {
84+
"start": 0,
85+
"end": 39,
86+
"source": {
87+
"body": "fragment TestDuplicate on Bar { field }",
88+
"name": "GraphQL request",
89+
"locationOffset": {
90+
"line": 1,
91+
"column": 1
92+
}
93+
}
94+
}
95+
};
96+
const query = {
97+
"kind": "Document",
98+
"definitions": [{
99+
"kind": "OperationDefinition",
100+
"operation": "query",
101+
"variableDefinitions": [],
102+
"directives": [],
103+
"selectionSet": {
104+
"kind": "SelectionSet",
105+
"selections": [{
106+
"kind": "Field",
107+
"name": {
108+
"kind": "Name",
109+
"value": "bar"
110+
},
111+
"arguments": [],
112+
"directives": [],
113+
"selectionSet": {
114+
"kind": "SelectionSet",
115+
"selections": [{
116+
"kind": "Field",
117+
"name": {
118+
"kind": "Name",
119+
"value": "fieldOne"
120+
},
121+
"arguments": [],
122+
"directives": []
123+
}, {
124+
"kind": "FragmentSpread",
125+
"name": {
126+
"kind": "Name",
127+
"value": "TestDuplicate"
128+
},
129+
"directives": []
130+
}]
131+
}
132+
}]
133+
}
134+
}].concat(frag1.definitions, frag2.definitions).reduce((acc, definition) => definition.kind !== "FragmentDefinition" || acc.find(curDef => curDef.name.value === definition.name.value) ? acc : acc.concat(definition), []),
135+
"loc": {
136+
"start": 0,
137+
"end": 39,
138+
"source": {
139+
"body": "{ bar { fieldOne ...TestDuplicate } } ",
140+
"name": "GraphQL request",
141+
"locationOffset": {
142+
"line": 1,
143+
"column": 1
144+
}
145+
}
146+
}
147+
};
148+
149+
`;
150+
3151
exports[`macros [gql] with fragment: [gql] with fragment 1`] = `
4152
5153
import { gql } from 'graphql.macro';
@@ -114,7 +262,7 @@ const query = {
114262
}
115263
}]
116264
}
117-
}].concat(userFragment.definitions),
265+
}].concat(userFragment.definitions).reduce((acc, definition) => definition.kind !== "FragmentDefinition" || acc.find(curDef => curDef.name.value === definition.name.value) ? acc : acc.concat(definition), []),
118266
"loc": {
119267
"start": 0,
120268
"end": 82,

src/__tests__/macro.test.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ pluginTester({
5555
\`;
5656
`,
5757
},
58+
'[gql] should handle duplicated fragments (issue#90)': {
59+
error: false,
60+
code: `
61+
import { gql } from '../macro';
62+
const frag1 = gql\`fragment TestDuplicate on Bar { field }\`;
63+
const frag2 = gql\`fragment TestDuplicate on Bar { field }\`;
64+
const query = gql\`{ bar { fieldOne ...TestDuplicate } } $\{frag1} $\{frag2}\`;
65+
`,
66+
},
5867
'[loader] without fragment': {
5968
error: false,
6069
code: `

src/utils/compileWithFragment.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
// @flow
22
import gqlTag from 'graphql-tag';
33
import serialize from 'babel-literal-to-ast';
4+
import template from '@babel/template';
5+
6+
/**
7+
* ref: https://github.com/gajus/babel-plugin-graphql-tag/blob/35edbae44990bf20be2de7139dc0ce5843f70bff/src/index.js#L25
8+
*/
9+
const uniqueFn = template.ast(`
10+
(acc, definition) =>
11+
definition.kind !== "FragmentDefinition" ||
12+
acc.find(curDef => curDef.name.value === definition.name.value)
13+
? acc
14+
: acc.concat(definition)
15+
`);
416

517
/**
618
* ref: https://github.com/leoasis/graphql-tag.macro
@@ -23,8 +35,14 @@ export default function compileWithFragment(
2335
t.memberExpression(expression.node, t.identifier('definitions')),
2436
);
2537
definitionsProperty.value = t.callExpression(
26-
t.memberExpression(definitionsArray, t.identifier('concat')),
27-
concatDefinitions,
38+
t.memberExpression(
39+
t.callExpression(
40+
t.memberExpression(definitionsArray, t.identifier('concat')),
41+
concatDefinitions,
42+
),
43+
t.identifier('reduce'),
44+
),
45+
[t.toExpression(uniqueFn), t.arrayExpression([])],
2846
);
2947
}
3048

yarn.lock

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,11 @@
290290
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.3.tgz#092d450db02bdb6ccb1ca8ffd47d8774a91aef87"
291291
integrity sha512-xsH1CJoln2r74hR+y7cg2B5JCPaTh+Hd+EbBRk9nWGSNspuo6krjhX0Om6RnRQuIvFq8wVXCLKH3kwKDYhanSg==
292292

293+
"@babel/parser@^7.4.4":
294+
version "7.4.4"
295+
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.4.4.tgz#5977129431b8fe33471730d255ce8654ae1250b6"
296+
integrity sha512-5pCS4mOsL+ANsFZGdvNLybx4wtqAZJ0MJjMHxvzI3bvIsz6sQvzW8XX92EYIkiPtIvcfG3Aj+Ir5VNyjnZhP7w==
297+
293298
"@babel/plugin-proposal-async-generator-functions@^7.2.0":
294299
version "7.2.0"
295300
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e"
@@ -745,6 +750,15 @@
745750
"@babel/parser" "^7.2.2"
746751
"@babel/types" "^7.2.2"
747752

753+
"@babel/template@^7.4.4":
754+
version "7.4.4"
755+
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237"
756+
integrity sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==
757+
dependencies:
758+
"@babel/code-frame" "^7.0.0"
759+
"@babel/parser" "^7.4.4"
760+
"@babel/types" "^7.4.4"
761+
748762
"@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.5", "@babel/traverse@^7.1.6", "@babel/traverse@^7.2.2", "@babel/traverse@^7.2.3":
749763
version "7.2.3"
750764
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.2.3.tgz#7ff50cefa9c7c0bd2d81231fdac122f3957748d8"
@@ -778,6 +792,15 @@
778792
lodash "^4.17.11"
779793
to-fast-properties "^2.0.0"
780794

795+
"@babel/types@^7.4.4":
796+
version "7.4.4"
797+
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.4.4.tgz#8db9e9a629bb7c29370009b4b779ed93fe57d5f0"
798+
integrity sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==
799+
dependencies:
800+
esutils "^2.0.2"
801+
lodash "^4.17.11"
802+
to-fast-properties "^2.0.0"
803+
781804
"@iamstarkov/listr-update-renderer@0.4.1":
782805
version "0.4.1"
783806
resolved "https://registry.yarnpkg.com/@iamstarkov/listr-update-renderer/-/listr-update-renderer-0.4.1.tgz#d7c48092a2dcf90fd672b6c8b458649cb350c77e"

0 commit comments

Comments
 (0)