houdini 0.15.1 → 0.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# houdini
|
|
2
2
|
|
|
3
|
+
## 0.15.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#370](https://github.com/HoudiniGraphql/houdini/pull/370) [`1ce03ec`](https://github.com/HoudiniGraphql/houdini/commit/1ce03ece112bf2688dcc066bdd844fa8b431fe4a) Thanks [@AlecAivazis](https://github.com/AlecAivazis)! - fixed bug when generating type definitions for interfaces mixed on interfaces
|
|
8
|
+
|
|
3
9
|
## 0.15.1
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
|
@@ -60,16 +60,64 @@ function inlineType({ config, filepath, rootType, selections, root, allowReadonl
|
|
|
60
60
|
// if we are looking at something with a selection set
|
|
61
61
|
else if (selections) {
|
|
62
62
|
const rootObj = type;
|
|
63
|
+
// a selection can contain 1 of 3 things:
|
|
64
|
+
// - a field
|
|
65
|
+
// - an inline fragment
|
|
66
|
+
// - a fragment spread
|
|
67
|
+
// an inline fragment can refer to an interface that's not refered in another
|
|
68
|
+
// fragment so we need to break down all fragments into their concrete versions
|
|
69
|
+
// discriminated by __typename
|
|
63
70
|
// before we can begin, we need to sort the selection set for this field for
|
|
64
71
|
// fields defined on the interface as well as subtypes of the interface
|
|
65
|
-
const inlineFragments =
|
|
72
|
+
const inlineFragments = {};
|
|
66
73
|
// the rest of the selection can be a single type in the union
|
|
67
74
|
const selectedFields = [];
|
|
68
75
|
for (const selection of selections) {
|
|
69
76
|
// if we found an inline fragment then we have a sub-condition on the fragment
|
|
70
|
-
if (selection.kind === 'InlineFragment') {
|
|
71
|
-
|
|
77
|
+
if (selection.kind === 'InlineFragment' && selection.typeCondition) {
|
|
78
|
+
// the type of the fragment
|
|
79
|
+
const fragmentType = config.schema.getType(selection.typeCondition.name.value);
|
|
80
|
+
// if the parent is a non-union or interface then the __typename is only going to have a single
|
|
81
|
+
// value so we just need to add every field to the list
|
|
82
|
+
if (!graphql.isInterfaceType(type) && !graphql.isUnionType(type)) {
|
|
83
|
+
selectedFields.push(...selection.selectionSet.selections);
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
// the parent type is not concrete so the selections will have to be organized
|
|
87
|
+
// into discriminated and non discriminated parts
|
|
88
|
+
// if the fragment type is not an interface or union, we should just
|
|
89
|
+
// add the selection as part of the discriminated selection
|
|
90
|
+
if (!graphql.isInterfaceType(fragmentType) && !graphql.isUnionType(fragmentType)) {
|
|
91
|
+
// make sure we have to place to put the discriminated type
|
|
92
|
+
if (!inlineFragments[fragmentType.name]) {
|
|
93
|
+
inlineFragments[fragmentType.name] = [];
|
|
94
|
+
}
|
|
95
|
+
inlineFragments[fragmentType.name].push(...selection.selectionSet.selections);
|
|
96
|
+
// we're done processing this type
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const possibleParents = config.schema.getPossibleTypes(type).map((t) => t.name);
|
|
100
|
+
// the fragment type is an interface or union and is getting mixed into an interface or union
|
|
101
|
+
// which means every possible type of fragment type needs to be mixed into the discriminated
|
|
102
|
+
// portion for the particular type
|
|
103
|
+
for (const possibleType of config.schema.getPossibleTypes(fragmentType)) {
|
|
104
|
+
// if the possible type is not a possible type of the parent, the intersection isn't possible
|
|
105
|
+
if (!possibleParents.includes(possibleType.name)) {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
// make sure we have to place to put the discriminated type
|
|
109
|
+
if (!inlineFragments[possibleType.name]) {
|
|
110
|
+
inlineFragments[possibleType.name] = [];
|
|
111
|
+
}
|
|
112
|
+
// add the selection to the discriminated object of the intersecting type
|
|
113
|
+
inlineFragments[possibleType.name].push(...selection.selectionSet.selections);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// an inline fragment without a selection is just a fancy way of asking for fields
|
|
117
|
+
else if (selection.kind === 'InlineFragment' && !selection.typeCondition) {
|
|
118
|
+
selectedFields.push(...selection.selectionSet.selections);
|
|
72
119
|
}
|
|
120
|
+
// the selection is just a normal field, add it to the non-discriminated object
|
|
73
121
|
else {
|
|
74
122
|
selectedFields.push(selection);
|
|
75
123
|
}
|
|
@@ -105,12 +153,7 @@ function inlineType({ config, filepath, rootType, selections, root, allowReadonl
|
|
|
105
153
|
}
|
|
106
154
|
// if we are mixing in inline fragments, we need to a union of the possible options,
|
|
107
155
|
// discriminated by the value of __typename
|
|
108
|
-
const inlineFragmentSelections = inlineFragments.flatMap((fragment) => {
|
|
109
|
-
// look up the type pointed by the type condition
|
|
110
|
-
if (!fragment.typeCondition) {
|
|
111
|
-
return [];
|
|
112
|
-
}
|
|
113
|
-
const typeName = fragment.typeCondition.name.value;
|
|
156
|
+
const inlineFragmentSelections = Object.entries(inlineFragments).flatMap(([typeName, fragment]) => {
|
|
114
157
|
const fragmentRootType = config.schema.getType(typeName);
|
|
115
158
|
if (!fragmentRootType) {
|
|
116
159
|
return [];
|
|
@@ -120,7 +163,7 @@ function inlineType({ config, filepath, rootType, selections, root, allowReadonl
|
|
|
120
163
|
config,
|
|
121
164
|
filepath,
|
|
122
165
|
rootType: fragmentRootType,
|
|
123
|
-
selections: fragment
|
|
166
|
+
selections: fragment,
|
|
124
167
|
allowReadonly,
|
|
125
168
|
visitedTypes,
|
|
126
169
|
root,
|
|
@@ -153,34 +196,14 @@ function inlineType({ config, filepath, rootType, selections, root, allowReadonl
|
|
|
153
196
|
// we're done massaging the type
|
|
154
197
|
return [{ type: fragmentRootType, tsType: fragmentType }];
|
|
155
198
|
});
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
//
|
|
159
|
-
|
|
160
|
-
const unionFragments = inlineFragmentSelections.filter(({ type }) => graphql.isUnionType(type));
|
|
161
|
-
const concreteFragments = inlineFragmentSelections.filter(({ type }) => {
|
|
162
|
-
// look up the type in the schema
|
|
163
|
-
return !graphql.isUnionType(type) && !graphql.isInterfaceType(type);
|
|
164
|
-
});
|
|
165
|
-
// build up the discriminated type
|
|
166
|
-
let selectionTypes = concreteFragments.map(({ type, tsType }) => {
|
|
199
|
+
//
|
|
200
|
+
if (Object.keys(inlineFragmentSelections).length > 0) {
|
|
201
|
+
// // build up the discriminated type
|
|
202
|
+
let selectionTypes = Object.entries(inlineFragmentSelections).map(([typeName, { type, tsType }]) => {
|
|
167
203
|
// the selection for a concrete type is really the intersection of itself
|
|
168
204
|
// with every abstract type it implements. go over every fragment belonging
|
|
169
205
|
// to an abstract type and check if this type implements it.
|
|
170
206
|
return AST.tsParenthesizedType(AST.tsIntersectionType([tsType]
|
|
171
|
-
// include the interface fragment if the concrete type implements it
|
|
172
|
-
.concat(interfaceFragments
|
|
173
|
-
.filter(({ type: abstractType }) => config.schema
|
|
174
|
-
.getImplementations(abstractType)
|
|
175
|
-
.objects.map(({ name }) => name)
|
|
176
|
-
.includes(type.name))
|
|
177
|
-
.map(({ tsType }) => tsType))
|
|
178
|
-
// include the union fragment if the concrete type is a member
|
|
179
|
-
.concat(unionFragments
|
|
180
|
-
.filter(({ type }) => {
|
|
181
|
-
return true;
|
|
182
|
-
})
|
|
183
|
-
.map(({ tsType }) => tsType))
|
|
184
207
|
// remove any inner nullability flags
|
|
185
208
|
.flatMap((type) => {
|
|
186
209
|
// if we are looking at a union we might have nulls in there
|
|
@@ -196,7 +219,6 @@ function inlineType({ config, filepath, rootType, selections, root, allowReadonl
|
|
|
196
219
|
result,
|
|
197
220
|
AST.tsParenthesizedType(AST.tsUnionType(selectionTypes)),
|
|
198
221
|
]);
|
|
199
|
-
// if we're supposed to leave a nullable type behind
|
|
200
222
|
}
|
|
201
223
|
}
|
|
202
224
|
// we shouldn't get here
|
package/build/cmd.js
CHANGED
|
@@ -72951,7 +72951,7 @@ export * from "${definitionsDir}"
|
|
|
72951
72951
|
|
|
72952
72952
|
async function metaGenerator(config) {
|
|
72953
72953
|
const meta = {
|
|
72954
|
-
version: '0.15.
|
|
72954
|
+
version: '0.15.2',
|
|
72955
72955
|
};
|
|
72956
72956
|
await writeFile(config.metaFilePath, JSON.stringify(meta));
|
|
72957
72957
|
}
|
|
@@ -73128,16 +73128,64 @@ function inlineType({ config, filepath, rootType, selections, root, allowReadonl
|
|
|
73128
73128
|
// if we are looking at something with a selection set
|
|
73129
73129
|
else if (selections) {
|
|
73130
73130
|
const rootObj = type;
|
|
73131
|
+
// a selection can contain 1 of 3 things:
|
|
73132
|
+
// - a field
|
|
73133
|
+
// - an inline fragment
|
|
73134
|
+
// - a fragment spread
|
|
73135
|
+
// an inline fragment can refer to an interface that's not refered in another
|
|
73136
|
+
// fragment so we need to break down all fragments into their concrete versions
|
|
73137
|
+
// discriminated by __typename
|
|
73131
73138
|
// before we can begin, we need to sort the selection set for this field for
|
|
73132
73139
|
// fields defined on the interface as well as subtypes of the interface
|
|
73133
|
-
const inlineFragments =
|
|
73140
|
+
const inlineFragments = {};
|
|
73134
73141
|
// the rest of the selection can be a single type in the union
|
|
73135
73142
|
const selectedFields = [];
|
|
73136
73143
|
for (const selection of selections) {
|
|
73137
73144
|
// if we found an inline fragment then we have a sub-condition on the fragment
|
|
73138
|
-
if (selection.kind === 'InlineFragment') {
|
|
73139
|
-
|
|
73145
|
+
if (selection.kind === 'InlineFragment' && selection.typeCondition) {
|
|
73146
|
+
// the type of the fragment
|
|
73147
|
+
const fragmentType = config.schema.getType(selection.typeCondition.name.value);
|
|
73148
|
+
// if the parent is a non-union or interface then the __typename is only going to have a single
|
|
73149
|
+
// value so we just need to add every field to the list
|
|
73150
|
+
if (!graphql.isInterfaceType(type) && !graphql.isUnionType(type)) {
|
|
73151
|
+
selectedFields.push(...selection.selectionSet.selections);
|
|
73152
|
+
continue;
|
|
73153
|
+
}
|
|
73154
|
+
// the parent type is not concrete so the selections will have to be organized
|
|
73155
|
+
// into discriminated and non discriminated parts
|
|
73156
|
+
// if the fragment type is not an interface or union, we should just
|
|
73157
|
+
// add the selection as part of the discriminated selection
|
|
73158
|
+
if (!graphql.isInterfaceType(fragmentType) && !graphql.isUnionType(fragmentType)) {
|
|
73159
|
+
// make sure we have to place to put the discriminated type
|
|
73160
|
+
if (!inlineFragments[fragmentType.name]) {
|
|
73161
|
+
inlineFragments[fragmentType.name] = [];
|
|
73162
|
+
}
|
|
73163
|
+
inlineFragments[fragmentType.name].push(...selection.selectionSet.selections);
|
|
73164
|
+
// we're done processing this type
|
|
73165
|
+
continue;
|
|
73166
|
+
}
|
|
73167
|
+
const possibleParents = config.schema.getPossibleTypes(type).map((t) => t.name);
|
|
73168
|
+
// the fragment type is an interface or union and is getting mixed into an interface or union
|
|
73169
|
+
// which means every possible type of fragment type needs to be mixed into the discriminated
|
|
73170
|
+
// portion for the particular type
|
|
73171
|
+
for (const possibleType of config.schema.getPossibleTypes(fragmentType)) {
|
|
73172
|
+
// if the possible type is not a possible type of the parent, the intersection isn't possible
|
|
73173
|
+
if (!possibleParents.includes(possibleType.name)) {
|
|
73174
|
+
continue;
|
|
73175
|
+
}
|
|
73176
|
+
// make sure we have to place to put the discriminated type
|
|
73177
|
+
if (!inlineFragments[possibleType.name]) {
|
|
73178
|
+
inlineFragments[possibleType.name] = [];
|
|
73179
|
+
}
|
|
73180
|
+
// add the selection to the discriminated object of the intersecting type
|
|
73181
|
+
inlineFragments[possibleType.name].push(...selection.selectionSet.selections);
|
|
73182
|
+
}
|
|
73183
|
+
}
|
|
73184
|
+
// an inline fragment without a selection is just a fancy way of asking for fields
|
|
73185
|
+
else if (selection.kind === 'InlineFragment' && !selection.typeCondition) {
|
|
73186
|
+
selectedFields.push(...selection.selectionSet.selections);
|
|
73140
73187
|
}
|
|
73188
|
+
// the selection is just a normal field, add it to the non-discriminated object
|
|
73141
73189
|
else {
|
|
73142
73190
|
selectedFields.push(selection);
|
|
73143
73191
|
}
|
|
@@ -73173,12 +73221,7 @@ function inlineType({ config, filepath, rootType, selections, root, allowReadonl
|
|
|
73173
73221
|
}
|
|
73174
73222
|
// if we are mixing in inline fragments, we need to a union of the possible options,
|
|
73175
73223
|
// discriminated by the value of __typename
|
|
73176
|
-
const inlineFragmentSelections = inlineFragments.flatMap((fragment) => {
|
|
73177
|
-
// look up the type pointed by the type condition
|
|
73178
|
-
if (!fragment.typeCondition) {
|
|
73179
|
-
return [];
|
|
73180
|
-
}
|
|
73181
|
-
const typeName = fragment.typeCondition.name.value;
|
|
73224
|
+
const inlineFragmentSelections = Object.entries(inlineFragments).flatMap(([typeName, fragment]) => {
|
|
73182
73225
|
const fragmentRootType = config.schema.getType(typeName);
|
|
73183
73226
|
if (!fragmentRootType) {
|
|
73184
73227
|
return [];
|
|
@@ -73188,7 +73231,7 @@ function inlineType({ config, filepath, rootType, selections, root, allowReadonl
|
|
|
73188
73231
|
config,
|
|
73189
73232
|
filepath,
|
|
73190
73233
|
rootType: fragmentRootType,
|
|
73191
|
-
selections: fragment
|
|
73234
|
+
selections: fragment,
|
|
73192
73235
|
allowReadonly,
|
|
73193
73236
|
visitedTypes,
|
|
73194
73237
|
root,
|
|
@@ -73221,34 +73264,14 @@ function inlineType({ config, filepath, rootType, selections, root, allowReadonl
|
|
|
73221
73264
|
// we're done massaging the type
|
|
73222
73265
|
return [{ type: fragmentRootType, tsType: fragmentType }];
|
|
73223
73266
|
});
|
|
73224
|
-
|
|
73225
|
-
|
|
73226
|
-
//
|
|
73227
|
-
|
|
73228
|
-
const unionFragments = inlineFragmentSelections.filter(({ type }) => graphql.isUnionType(type));
|
|
73229
|
-
const concreteFragments = inlineFragmentSelections.filter(({ type }) => {
|
|
73230
|
-
// look up the type in the schema
|
|
73231
|
-
return !graphql.isUnionType(type) && !graphql.isInterfaceType(type);
|
|
73232
|
-
});
|
|
73233
|
-
// build up the discriminated type
|
|
73234
|
-
let selectionTypes = concreteFragments.map(({ type, tsType }) => {
|
|
73267
|
+
//
|
|
73268
|
+
if (Object.keys(inlineFragmentSelections).length > 0) {
|
|
73269
|
+
// // build up the discriminated type
|
|
73270
|
+
let selectionTypes = Object.entries(inlineFragmentSelections).map(([typeName, { type, tsType }]) => {
|
|
73235
73271
|
// the selection for a concrete type is really the intersection of itself
|
|
73236
73272
|
// with every abstract type it implements. go over every fragment belonging
|
|
73237
73273
|
// to an abstract type and check if this type implements it.
|
|
73238
73274
|
return AST$2.tsParenthesizedType(AST$2.tsIntersectionType([tsType]
|
|
73239
|
-
// include the interface fragment if the concrete type implements it
|
|
73240
|
-
.concat(interfaceFragments
|
|
73241
|
-
.filter(({ type: abstractType }) => config.schema
|
|
73242
|
-
.getImplementations(abstractType)
|
|
73243
|
-
.objects.map(({ name }) => name)
|
|
73244
|
-
.includes(type.name))
|
|
73245
|
-
.map(({ tsType }) => tsType))
|
|
73246
|
-
// include the union fragment if the concrete type is a member
|
|
73247
|
-
.concat(unionFragments
|
|
73248
|
-
.filter(({ type }) => {
|
|
73249
|
-
return true;
|
|
73250
|
-
})
|
|
73251
|
-
.map(({ tsType }) => tsType))
|
|
73252
73275
|
// remove any inner nullability flags
|
|
73253
73276
|
.flatMap((type) => {
|
|
73254
73277
|
// if we are looking at a union we might have nulls in there
|
|
@@ -73264,7 +73287,6 @@ function inlineType({ config, filepath, rootType, selections, root, allowReadonl
|
|
|
73264
73287
|
result,
|
|
73265
73288
|
AST$2.tsParenthesizedType(AST$2.tsUnionType(selectionTypes)),
|
|
73266
73289
|
]);
|
|
73267
|
-
// if we're supposed to leave a nullable type behind
|
|
73268
73290
|
}
|
|
73269
73291
|
}
|
|
73270
73292
|
// we shouldn't get here
|
|
@@ -74631,7 +74653,7 @@ async function runPipeline(config, docs) {
|
|
|
74631
74653
|
}
|
|
74632
74654
|
catch { }
|
|
74633
74655
|
// if the previous version is different from the current version
|
|
74634
|
-
const versionChanged = previousVersion && previousVersion !== '0.15.
|
|
74656
|
+
const versionChanged = previousVersion && previousVersion !== '0.15.2';
|
|
74635
74657
|
await runPipeline$1(config, [
|
|
74636
74658
|
typeCheck,
|
|
74637
74659
|
uniqueDocumentNames,
|
|
@@ -74658,7 +74680,7 @@ async function runPipeline(config, docs) {
|
|
|
74658
74680
|
if (config.logLevel === LogLevel.Quiet) ;
|
|
74659
74681
|
else if (versionChanged) {
|
|
74660
74682
|
console.log('💣 Detected new version of Houdini. Regenerating all documents...');
|
|
74661
|
-
console.log('🎉 Welcome to 0.15.
|
|
74683
|
+
console.log('🎉 Welcome to 0.15.2!');
|
|
74662
74684
|
// if the user is coming from a version pre-15, point them to the migration guide
|
|
74663
74685
|
const major = parseInt(previousVersion.split('.')[1]);
|
|
74664
74686
|
if (major < 15) {
|
package/package.json
CHANGED
|
@@ -62,17 +62,77 @@ export function inlineType({
|
|
|
62
62
|
else if (selections) {
|
|
63
63
|
const rootObj = type as graphql.GraphQLObjectType<any, any>
|
|
64
64
|
|
|
65
|
+
// a selection can contain 1 of 3 things:
|
|
66
|
+
// - a field
|
|
67
|
+
// - an inline fragment
|
|
68
|
+
// - a fragment spread
|
|
69
|
+
|
|
70
|
+
// an inline fragment can refer to an interface that's not refered in another
|
|
71
|
+
// fragment so we need to break down all fragments into their concrete versions
|
|
72
|
+
// discriminated by __typename
|
|
73
|
+
|
|
65
74
|
// before we can begin, we need to sort the selection set for this field for
|
|
66
75
|
// fields defined on the interface as well as subtypes of the interface
|
|
67
|
-
const inlineFragments: graphql.
|
|
76
|
+
const inlineFragments: { [typeName: string]: graphql.SelectionNode[] } = {}
|
|
68
77
|
// the rest of the selection can be a single type in the union
|
|
69
78
|
const selectedFields: graphql.SelectionNode[] = []
|
|
70
79
|
|
|
71
80
|
for (const selection of selections) {
|
|
72
81
|
// if we found an inline fragment then we have a sub-condition on the fragment
|
|
73
|
-
if (selection.kind === 'InlineFragment') {
|
|
74
|
-
|
|
75
|
-
|
|
82
|
+
if (selection.kind === 'InlineFragment' && selection.typeCondition) {
|
|
83
|
+
// the type of the fragment
|
|
84
|
+
const fragmentType = config.schema.getType(selection.typeCondition.name.value)!
|
|
85
|
+
|
|
86
|
+
// if the parent is a non-union or interface then the __typename is only going to have a single
|
|
87
|
+
// value so we just need to add every field to the list
|
|
88
|
+
if (!graphql.isInterfaceType(type) && !graphql.isUnionType(type)) {
|
|
89
|
+
selectedFields.push(...selection.selectionSet.selections)
|
|
90
|
+
continue
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// the parent type is not concrete so the selections will have to be organized
|
|
94
|
+
// into discriminated and non discriminated parts
|
|
95
|
+
|
|
96
|
+
// if the fragment type is not an interface or union, we should just
|
|
97
|
+
// add the selection as part of the discriminated selection
|
|
98
|
+
if (!graphql.isInterfaceType(fragmentType) && !graphql.isUnionType(fragmentType)) {
|
|
99
|
+
// make sure we have to place to put the discriminated type
|
|
100
|
+
if (!inlineFragments[fragmentType.name]) {
|
|
101
|
+
inlineFragments[fragmentType.name] = []
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
inlineFragments[fragmentType.name].push(...selection.selectionSet.selections)
|
|
105
|
+
|
|
106
|
+
// we're done processing this type
|
|
107
|
+
continue
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const possibleParents = config.schema.getPossibleTypes(type).map((t) => t.name)
|
|
111
|
+
|
|
112
|
+
// the fragment type is an interface or union and is getting mixed into an interface or union
|
|
113
|
+
// which means every possible type of fragment type needs to be mixed into the discriminated
|
|
114
|
+
// portion for the particular type
|
|
115
|
+
for (const possibleType of config.schema.getPossibleTypes(fragmentType)) {
|
|
116
|
+
// if the possible type is not a possible type of the parent, the intersection isn't possible
|
|
117
|
+
if (!possibleParents.includes(possibleType.name)) {
|
|
118
|
+
continue
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// make sure we have to place to put the discriminated type
|
|
122
|
+
if (!inlineFragments[possibleType.name]) {
|
|
123
|
+
inlineFragments[possibleType.name] = []
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// add the selection to the discriminated object of the intersecting type
|
|
127
|
+
inlineFragments[possibleType.name].push(...selection.selectionSet.selections)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// an inline fragment without a selection is just a fancy way of asking for fields
|
|
131
|
+
else if (selection.kind === 'InlineFragment' && !selection.typeCondition) {
|
|
132
|
+
selectedFields.push(...selection.selectionSet.selections)
|
|
133
|
+
}
|
|
134
|
+
// the selection is just a normal field, add it to the non-discriminated object
|
|
135
|
+
else {
|
|
76
136
|
selectedFields.push(selection)
|
|
77
137
|
}
|
|
78
138
|
}
|
|
@@ -151,12 +211,7 @@ export function inlineType({
|
|
|
151
211
|
const inlineFragmentSelections: {
|
|
152
212
|
type: graphql.GraphQLNamedType
|
|
153
213
|
tsType: TSTypeKind
|
|
154
|
-
}[] = inlineFragments.flatMap((fragment
|
|
155
|
-
// look up the type pointed by the type condition
|
|
156
|
-
if (!fragment.typeCondition) {
|
|
157
|
-
return []
|
|
158
|
-
}
|
|
159
|
-
const typeName = fragment.typeCondition.name.value
|
|
214
|
+
}[] = Object.entries(inlineFragments).flatMap(([typeName, fragment]) => {
|
|
160
215
|
const fragmentRootType = config.schema.getType(typeName)
|
|
161
216
|
if (!fragmentRootType) {
|
|
162
217
|
return []
|
|
@@ -167,7 +222,7 @@ export function inlineType({
|
|
|
167
222
|
config,
|
|
168
223
|
filepath,
|
|
169
224
|
rootType: fragmentRootType,
|
|
170
|
-
selections: fragment
|
|
225
|
+
selections: fragment,
|
|
171
226
|
allowReadonly,
|
|
172
227
|
visitedTypes,
|
|
173
228
|
root,
|
|
@@ -217,72 +272,40 @@ export function inlineType({
|
|
|
217
272
|
// we're done massaging the type
|
|
218
273
|
return [{ type: fragmentRootType, tsType: fragmentType }]
|
|
219
274
|
})
|
|
220
|
-
if (inlineFragmentSelections.length > 0) {
|
|
221
|
-
// these fragments could refer to types, unions, or interfaces
|
|
222
|
-
// only mix the relevant ones
|
|
223
|
-
const interfaceFragments = inlineFragmentSelections.filter(({ type }) =>
|
|
224
|
-
graphql.isInterfaceType(type)
|
|
225
|
-
)
|
|
226
|
-
const unionFragments = inlineFragmentSelections.filter(({ type }) =>
|
|
227
|
-
graphql.isUnionType(type)
|
|
228
|
-
)
|
|
229
|
-
const concreteFragments = inlineFragmentSelections.filter(({ type }) => {
|
|
230
|
-
// look up the type in the schema
|
|
231
|
-
return !graphql.isUnionType(type) && !graphql.isInterfaceType(type)
|
|
232
|
-
})
|
|
233
275
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
.filter(({ type }) => {
|
|
259
|
-
return true
|
|
260
|
-
})
|
|
261
|
-
.map(({ tsType }) => tsType)
|
|
262
|
-
)
|
|
263
|
-
// remove any inner nullability flags
|
|
264
|
-
.flatMap((type) => {
|
|
265
|
-
// if we are looking at a union we might have nulls in there
|
|
266
|
-
if (type.type === 'TSUnionType') {
|
|
267
|
-
return type.types.filter(
|
|
268
|
-
(innerType) =>
|
|
269
|
-
innerType.type !== 'TSNullKeyword' &&
|
|
270
|
-
innerType.type !== 'TSUndefinedKeyword'
|
|
271
|
-
)
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
return type
|
|
275
|
-
})
|
|
276
|
+
//
|
|
277
|
+
if (Object.keys(inlineFragmentSelections).length > 0) {
|
|
278
|
+
// // build up the discriminated type
|
|
279
|
+
let selectionTypes = Object.entries(inlineFragmentSelections).map(
|
|
280
|
+
([typeName, { type, tsType }]) => {
|
|
281
|
+
// the selection for a concrete type is really the intersection of itself
|
|
282
|
+
// with every abstract type it implements. go over every fragment belonging
|
|
283
|
+
// to an abstract type and check if this type implements it.
|
|
284
|
+
return AST.tsParenthesizedType(
|
|
285
|
+
AST.tsIntersectionType(
|
|
286
|
+
[tsType]
|
|
287
|
+
// remove any inner nullability flags
|
|
288
|
+
.flatMap((type) => {
|
|
289
|
+
// if we are looking at a union we might have nulls in there
|
|
290
|
+
if (type.type === 'TSUnionType') {
|
|
291
|
+
return type.types.filter(
|
|
292
|
+
(innerType) =>
|
|
293
|
+
innerType.type !== 'TSNullKeyword' &&
|
|
294
|
+
innerType.type !== 'TSUndefinedKeyword'
|
|
295
|
+
)
|
|
296
|
+
}
|
|
297
|
+
return type
|
|
298
|
+
})
|
|
299
|
+
)
|
|
276
300
|
)
|
|
277
|
-
|
|
278
|
-
|
|
301
|
+
}
|
|
302
|
+
)
|
|
279
303
|
|
|
280
304
|
// build up the list of fragment types
|
|
281
305
|
result = AST.tsIntersectionType([
|
|
282
306
|
result,
|
|
283
307
|
AST.tsParenthesizedType(AST.tsUnionType(selectionTypes)),
|
|
284
308
|
])
|
|
285
|
-
// if we're supposed to leave a nullable type behind
|
|
286
309
|
}
|
|
287
310
|
}
|
|
288
311
|
// we shouldn't get here
|