houdini 0.17.8 → 0.17.10
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/README.md +33 -0
- package/build/cmd-cjs/index.js +124 -38
- package/build/cmd-esm/index.js +124 -38
- package/build/codegen-cjs/index.js +112 -36
- package/build/codegen-esm/index.js +112 -36
- package/build/lib/config.d.ts +3 -0
- package/build/lib-cjs/index.js +31 -12
- package/build/lib-esm/index.js +31 -12
- package/build/runtime/cache/cache.d.ts +1 -1
- package/build/runtime/cache/lists.d.ts +1 -1
- package/build/runtime/lib/config.d.ts +10 -2
- package/build/runtime/lib/types.d.ts +1 -0
- package/build/runtime-cjs/cache/cache.d.ts +1 -1
- package/build/runtime-cjs/cache/cache.js +6 -6
- package/build/runtime-cjs/cache/lists.d.ts +1 -1
- package/build/runtime-cjs/cache/lists.js +15 -6
- package/build/runtime-cjs/cache/tests/list.test.js +160 -70
- package/build/runtime-cjs/lib/config.d.ts +10 -2
- package/build/runtime-cjs/lib/types.d.ts +1 -0
- package/build/runtime-esm/cache/cache.d.ts +1 -1
- package/build/runtime-esm/cache/cache.js +6 -6
- package/build/runtime-esm/cache/lists.d.ts +1 -1
- package/build/runtime-esm/cache/lists.js +15 -6
- package/build/runtime-esm/cache/tests/list.test.js +160 -70
- package/build/runtime-esm/lib/config.d.ts +10 -2
- package/build/runtime-esm/lib/types.d.ts +1 -0
- package/build/test-cjs/index.js +122 -36
- package/build/test-esm/index.js +122 -36
- package/build/vite-cjs/index.js +122 -36
- package/build/vite-esm/index.js +122 -36
- package/package.json +16 -1
- package/.turbo/turbo-compile.log +0 -5
- package/.turbo/turbo-typedefs.log +0 -5
- package/CHANGELOG.md +0 -367
- package/src/cmd/generate.ts +0 -54
- package/src/cmd/index.ts +0 -60
- package/src/cmd/init.ts +0 -637
- package/src/cmd/pullSchema.ts +0 -40
- package/src/codegen/generators/artifacts/artifacts.test.ts +0 -2978
- package/src/codegen/generators/artifacts/fieldKey.ts +0 -60
- package/src/codegen/generators/artifacts/index.ts +0 -330
- package/src/codegen/generators/artifacts/indexFile.ts +0 -24
- package/src/codegen/generators/artifacts/inputs.ts +0 -81
- package/src/codegen/generators/artifacts/operations.ts +0 -263
- package/src/codegen/generators/artifacts/pagination.test.ts +0 -664
- package/src/codegen/generators/artifacts/policy.test.ts +0 -298
- package/src/codegen/generators/artifacts/selection.ts +0 -208
- package/src/codegen/generators/artifacts/utils.test.ts +0 -118
- package/src/codegen/generators/artifacts/utils.ts +0 -108
- package/src/codegen/generators/definitions/enums.test.ts +0 -61
- package/src/codegen/generators/definitions/enums.ts +0 -68
- package/src/codegen/generators/definitions/index.ts +0 -11
- package/src/codegen/generators/definitions/schema.test.ts +0 -227
- package/src/codegen/generators/index.ts +0 -6
- package/src/codegen/generators/indexFile/index.ts +0 -63
- package/src/codegen/generators/indexFile/indexFile.test.ts +0 -72
- package/src/codegen/generators/persistedQueries/index.ts +0 -55
- package/src/codegen/generators/persistedQueries/persistedQuery.test.ts +0 -26
- package/src/codegen/generators/runtime/index.test.ts +0 -74
- package/src/codegen/generators/runtime/index.ts +0 -64
- package/src/codegen/generators/runtime/runtime.test.ts +0 -25
- package/src/codegen/generators/typescript/addReferencedInputTypes.ts +0 -77
- package/src/codegen/generators/typescript/index.ts +0 -412
- package/src/codegen/generators/typescript/inlineType.ts +0 -409
- package/src/codegen/generators/typescript/typeReference.ts +0 -44
- package/src/codegen/generators/typescript/types.ts +0 -81
- package/src/codegen/generators/typescript/typescript.test.ts +0 -1434
- package/src/codegen/index.ts +0 -406
- package/src/codegen/transforms/addID.test.ts +0 -93
- package/src/codegen/transforms/addID.ts +0 -86
- package/src/codegen/transforms/composeQueries.test.ts +0 -50
- package/src/codegen/transforms/composeQueries.ts +0 -154
- package/src/codegen/transforms/fragmentVariables.test.ts +0 -636
- package/src/codegen/transforms/fragmentVariables.ts +0 -417
- package/src/codegen/transforms/index.ts +0 -7
- package/src/codegen/transforms/list.ts +0 -485
- package/src/codegen/transforms/lists.test.ts +0 -530
- package/src/codegen/transforms/paginate.test.ts +0 -1481
- package/src/codegen/transforms/paginate.ts +0 -750
- package/src/codegen/transforms/schema.test.ts +0 -136
- package/src/codegen/transforms/schema.ts +0 -104
- package/src/codegen/transforms/typename.test.ts +0 -125
- package/src/codegen/transforms/typename.ts +0 -55
- package/src/codegen/utils/commonjs.ts +0 -26
- package/src/codegen/utils/flattenSelections.ts +0 -179
- package/src/codegen/utils/graphql.test.ts +0 -35
- package/src/codegen/utils/graphql.ts +0 -79
- package/src/codegen/utils/index.ts +0 -5
- package/src/codegen/utils/moduleExport.ts +0 -27
- package/src/codegen/utils/murmur.ts +0 -79
- package/src/codegen/validators/index.ts +0 -4
- package/src/codegen/validators/noIDAlias.test.ts +0 -71
- package/src/codegen/validators/noIDAlias.ts +0 -39
- package/src/codegen/validators/plugins.ts +0 -25
- package/src/codegen/validators/typeCheck.test.ts +0 -904
- package/src/codegen/validators/typeCheck.ts +0 -1031
- package/src/codegen/validators/uniqueNames.test.ts +0 -59
- package/src/codegen/validators/uniqueNames.ts +0 -39
- package/src/lib/cleanupFiles.ts +0 -20
- package/src/lib/config.test.ts +0 -13
- package/src/lib/config.ts +0 -943
- package/src/lib/constants.ts +0 -11
- package/src/lib/error.ts +0 -24
- package/src/lib/fs.ts +0 -285
- package/src/lib/graphql.test.ts +0 -211
- package/src/lib/graphql.ts +0 -200
- package/src/lib/imports.ts +0 -82
- package/src/lib/index.ts +0 -17
- package/src/lib/introspection.ts +0 -39
- package/src/lib/parse.test.ts +0 -75
- package/src/lib/parse.ts +0 -23
- package/src/lib/path.ts +0 -49
- package/src/lib/pipeline.ts +0 -17
- package/src/lib/types.ts +0 -34
- package/src/lib/walk.ts +0 -104
- package/src/runtime/cache/cache.ts +0 -1023
- package/src/runtime/cache/gc.ts +0 -56
- package/src/runtime/cache/index.ts +0 -3
- package/src/runtime/cache/lists.ts +0 -502
- package/src/runtime/cache/storage.ts +0 -574
- package/src/runtime/cache/stuff.ts +0 -77
- package/src/runtime/cache/subscription.ts +0 -329
- package/src/runtime/cache/tests/availability.test.ts +0 -408
- package/src/runtime/cache/tests/gc.test.ts +0 -319
- package/src/runtime/cache/tests/keys.test.ts +0 -36
- package/src/runtime/cache/tests/list.test.ts +0 -3747
- package/src/runtime/cache/tests/readwrite.test.ts +0 -1201
- package/src/runtime/cache/tests/scalars.test.ts +0 -218
- package/src/runtime/cache/tests/storage.test.ts +0 -426
- package/src/runtime/cache/tests/subscriptions.test.ts +0 -1757
- package/src/runtime/index.ts +0 -29
- package/src/runtime/lib/config.ts +0 -201
- package/src/runtime/lib/constants.ts +0 -17
- package/src/runtime/lib/deepEquals.ts +0 -32
- package/src/runtime/lib/errors.ts +0 -8
- package/src/runtime/lib/index.ts +0 -8
- package/src/runtime/lib/log.ts +0 -69
- package/src/runtime/lib/network.ts +0 -303
- package/src/runtime/lib/networkUtils.ts +0 -151
- package/src/runtime/lib/scalars.test.ts +0 -877
- package/src/runtime/lib/scalars.ts +0 -195
- package/src/runtime/lib/types.ts +0 -194
- package/src/test/index.ts +0 -294
- package/src/vite/ast.ts +0 -107
- package/src/vite/houdini.ts +0 -113
- package/src/vite/imports.ts +0 -129
- package/src/vite/index.ts +0 -55
- package/src/vite/schema.ts +0 -80
|
@@ -1,409 +0,0 @@
|
|
|
1
|
-
import type { TSTypeKind, StatementKind } from 'ast-types/gen/kinds'
|
|
2
|
-
import * as graphql from 'graphql'
|
|
3
|
-
import * as recast from 'recast'
|
|
4
|
-
|
|
5
|
-
import { Config, ensureImports, HoudiniError } from '../../../lib'
|
|
6
|
-
import { TypeWrapper, unwrapType } from '../../utils'
|
|
7
|
-
import { nullableField, readonlyProperty, scalarPropertyValue } from './types'
|
|
8
|
-
|
|
9
|
-
const AST = recast.types.builders
|
|
10
|
-
|
|
11
|
-
export const fragmentKey = '$fragments'
|
|
12
|
-
|
|
13
|
-
export function inlineType({
|
|
14
|
-
config,
|
|
15
|
-
filepath,
|
|
16
|
-
rootType,
|
|
17
|
-
selections,
|
|
18
|
-
root,
|
|
19
|
-
allowReadonly,
|
|
20
|
-
body,
|
|
21
|
-
visitedTypes,
|
|
22
|
-
missingScalars,
|
|
23
|
-
includeFragments,
|
|
24
|
-
allOptional,
|
|
25
|
-
}: {
|
|
26
|
-
config: Config
|
|
27
|
-
filepath: string
|
|
28
|
-
rootType: graphql.GraphQLNamedType
|
|
29
|
-
selections: readonly graphql.SelectionNode[] | undefined
|
|
30
|
-
root: boolean
|
|
31
|
-
allowReadonly: boolean
|
|
32
|
-
body: StatementKind[]
|
|
33
|
-
visitedTypes: Set<string>
|
|
34
|
-
missingScalars: Set<string>
|
|
35
|
-
includeFragments: boolean
|
|
36
|
-
allOptional?: boolean
|
|
37
|
-
}): TSTypeKind {
|
|
38
|
-
// start unwrapping non-nulls and lists (we'll wrap it back up before we return)
|
|
39
|
-
const { type, wrappers } = unwrapType(config, rootType)
|
|
40
|
-
|
|
41
|
-
let result: TSTypeKind
|
|
42
|
-
// if we are looking at a scalar field
|
|
43
|
-
if (graphql.isScalarType(type)) {
|
|
44
|
-
result = scalarPropertyValue(config, missingScalars, type as graphql.GraphQLNamedType)
|
|
45
|
-
}
|
|
46
|
-
// we could have encountered an enum
|
|
47
|
-
else if (graphql.isEnumType(type)) {
|
|
48
|
-
// have we seen the enum before
|
|
49
|
-
if (!visitedTypes.has(type.name)) {
|
|
50
|
-
ensureImports({
|
|
51
|
-
config,
|
|
52
|
-
// @ts-ignore
|
|
53
|
-
body,
|
|
54
|
-
import: [type.name],
|
|
55
|
-
sourceModule: '$houdini/graphql/enums',
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
// register that we've visited the type already
|
|
59
|
-
visitedTypes.add(type.name)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
result = AST.tsTypeReference(AST.identifier(type.name))
|
|
63
|
-
}
|
|
64
|
-
// if we are looking at something with a selection set
|
|
65
|
-
else if (selections) {
|
|
66
|
-
const rootObj = type as graphql.GraphQLObjectType<any, any>
|
|
67
|
-
|
|
68
|
-
// a selection can contain 1 of 3 things:
|
|
69
|
-
// - a field
|
|
70
|
-
// - an inline fragment
|
|
71
|
-
// - a fragment spread
|
|
72
|
-
|
|
73
|
-
// an inline fragment can refer to an interface that's not referred in another
|
|
74
|
-
// fragment so we need to break down all fragments into their concrete versions
|
|
75
|
-
// discriminated by __typename
|
|
76
|
-
|
|
77
|
-
// before we can begin, we need to sort the selection set for this field for
|
|
78
|
-
// fields defined on the interface as well as subtypes of the interface
|
|
79
|
-
const inlineFragments: { [typeName: string]: graphql.SelectionNode[] } = {}
|
|
80
|
-
// the rest of the selection can be a single type in the union
|
|
81
|
-
const selectedFields: graphql.SelectionNode[] = []
|
|
82
|
-
|
|
83
|
-
for (const selection of selections) {
|
|
84
|
-
// if we found an inline fragment then we have a sub-condition on the fragment
|
|
85
|
-
if (selection.kind === 'InlineFragment' && selection.typeCondition) {
|
|
86
|
-
// the type of the fragment
|
|
87
|
-
const fragmentType = config.schema.getType(selection.typeCondition.name.value)!
|
|
88
|
-
|
|
89
|
-
// if the parent is a non-union or interface then the __typename is only going to have a single
|
|
90
|
-
// value so we just need to add every field to the list
|
|
91
|
-
if (!graphql.isInterfaceType(type) && !graphql.isUnionType(type)) {
|
|
92
|
-
selectedFields.push(...selection.selectionSet.selections)
|
|
93
|
-
continue
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// the parent type is not concrete so the selections will have to be organized
|
|
97
|
-
// into discriminated and non discriminated parts
|
|
98
|
-
|
|
99
|
-
// if the fragment type is not an interface or union, we should just
|
|
100
|
-
// add the selection as part of the discriminated selection
|
|
101
|
-
if (!graphql.isInterfaceType(fragmentType) && !graphql.isUnionType(fragmentType)) {
|
|
102
|
-
// make sure we have to place to put the discriminated type
|
|
103
|
-
if (!inlineFragments[fragmentType.name]) {
|
|
104
|
-
inlineFragments[fragmentType.name] = []
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
inlineFragments[fragmentType.name].push(...selection.selectionSet.selections)
|
|
108
|
-
|
|
109
|
-
// we're done processing this type
|
|
110
|
-
continue
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const possibleParents = config.schema.getPossibleTypes(type).map((t) => t.name)
|
|
114
|
-
|
|
115
|
-
// the fragment type is an interface or union and is getting mixed into an interface or union
|
|
116
|
-
// which means every possible type of fragment type needs to be mixed into the discriminated
|
|
117
|
-
// portion for the particular type
|
|
118
|
-
for (const possibleType of config.schema.getPossibleTypes(fragmentType)) {
|
|
119
|
-
// if the possible type is not a possible type of the parent, the intersection isn't possible
|
|
120
|
-
if (!possibleParents.includes(possibleType.name)) {
|
|
121
|
-
continue
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// make sure we have to place to put the discriminated type
|
|
125
|
-
if (!inlineFragments[possibleType.name]) {
|
|
126
|
-
inlineFragments[possibleType.name] = []
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// add the selection to the discriminated object of the intersecting type
|
|
130
|
-
inlineFragments[possibleType.name].push(...selection.selectionSet.selections)
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
// an inline fragment without a selection is just a fancy way of asking for fields
|
|
134
|
-
else if (selection.kind === 'InlineFragment' && !selection.typeCondition) {
|
|
135
|
-
selectedFields.push(...selection.selectionSet.selections)
|
|
136
|
-
}
|
|
137
|
-
// the selection is just a normal field, add it to the non-discriminated object
|
|
138
|
-
else {
|
|
139
|
-
selectedFields.push(selection)
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// turn the set of selected fields into their own type
|
|
144
|
-
result = AST.tsTypeLiteral([
|
|
145
|
-
// every field gets an entry in the object
|
|
146
|
-
...(
|
|
147
|
-
(selectedFields || []).filter(
|
|
148
|
-
(field) => field.kind === 'Field'
|
|
149
|
-
) as graphql.FieldNode[]
|
|
150
|
-
).map((selection) => {
|
|
151
|
-
// grab the type info for the selection
|
|
152
|
-
const { type, field } = selectionTypeInfo(
|
|
153
|
-
config.schema,
|
|
154
|
-
filepath,
|
|
155
|
-
rootObj,
|
|
156
|
-
selection
|
|
157
|
-
)
|
|
158
|
-
|
|
159
|
-
// figure out the response name
|
|
160
|
-
const attributeName = selection.alias?.value || selection.name.value
|
|
161
|
-
|
|
162
|
-
// figure out the corresponding typescript type
|
|
163
|
-
let attributeType = inlineType({
|
|
164
|
-
config,
|
|
165
|
-
filepath,
|
|
166
|
-
rootType: field.type as graphql.GraphQLNamedType,
|
|
167
|
-
selections: selection.selectionSet?.selections as graphql.SelectionNode[],
|
|
168
|
-
root: false,
|
|
169
|
-
allowReadonly,
|
|
170
|
-
visitedTypes,
|
|
171
|
-
body,
|
|
172
|
-
missingScalars,
|
|
173
|
-
includeFragments,
|
|
174
|
-
allOptional,
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
// we're done
|
|
178
|
-
const prop = readonlyProperty(
|
|
179
|
-
AST.tsPropertySignature(
|
|
180
|
-
AST.identifier(attributeName),
|
|
181
|
-
AST.tsTypeAnnotation(attributeType)
|
|
182
|
-
),
|
|
183
|
-
allowReadonly
|
|
184
|
-
)
|
|
185
|
-
|
|
186
|
-
if (allOptional) {
|
|
187
|
-
prop.optional = true
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return prop
|
|
191
|
-
}),
|
|
192
|
-
])
|
|
193
|
-
|
|
194
|
-
// embed any referenced fragments in the result
|
|
195
|
-
const fragmentSpreads = selections?.filter(({ kind }) => kind === 'FragmentSpread') as
|
|
196
|
-
| graphql.FragmentSpreadNode[]
|
|
197
|
-
| undefined
|
|
198
|
-
|
|
199
|
-
if (includeFragments && fragmentSpreads && fragmentSpreads.length) {
|
|
200
|
-
result.members.push(
|
|
201
|
-
readonlyProperty(
|
|
202
|
-
AST.tsPropertySignature(
|
|
203
|
-
AST.identifier(fragmentKey),
|
|
204
|
-
AST.tsTypeAnnotation(
|
|
205
|
-
AST.tsTypeLiteral(
|
|
206
|
-
(fragmentSpreads || []).map((fragmentSpread) =>
|
|
207
|
-
AST.tsPropertySignature(
|
|
208
|
-
AST.identifier(fragmentSpread.name.value),
|
|
209
|
-
AST.tsTypeAnnotation(
|
|
210
|
-
AST.tsLiteralType(AST.booleanLiteral(true))
|
|
211
|
-
)
|
|
212
|
-
)
|
|
213
|
-
)
|
|
214
|
-
)
|
|
215
|
-
)
|
|
216
|
-
),
|
|
217
|
-
allowReadonly
|
|
218
|
-
)
|
|
219
|
-
)
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// if we are mixing in inline fragments, we need to a union of the possible options,
|
|
223
|
-
// discriminated by the value of __typename
|
|
224
|
-
const inlineFragmentSelections: {
|
|
225
|
-
type: graphql.GraphQLNamedType
|
|
226
|
-
tsType: TSTypeKind
|
|
227
|
-
}[] = Object.entries(inlineFragments).flatMap(([typeName, fragment]) => {
|
|
228
|
-
const fragmentRootType = config.schema.getType(typeName)
|
|
229
|
-
if (!fragmentRootType) {
|
|
230
|
-
return []
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// generate the type for the inline fragment
|
|
234
|
-
const fragmentType = inlineType({
|
|
235
|
-
config,
|
|
236
|
-
filepath,
|
|
237
|
-
rootType: fragmentRootType,
|
|
238
|
-
selections: fragment,
|
|
239
|
-
allowReadonly,
|
|
240
|
-
visitedTypes,
|
|
241
|
-
root,
|
|
242
|
-
body,
|
|
243
|
-
missingScalars,
|
|
244
|
-
includeFragments,
|
|
245
|
-
allOptional,
|
|
246
|
-
})
|
|
247
|
-
|
|
248
|
-
// we need to handle __typename in the generated type. this means removing
|
|
249
|
-
// it if it was declared by tsType and adding the right value
|
|
250
|
-
let objectType = fragmentType
|
|
251
|
-
// if we got a nullable field, we need to point at the type def
|
|
252
|
-
if (fragmentType.type === 'TSUnionType') {
|
|
253
|
-
for (const inner of fragmentType.types) {
|
|
254
|
-
if (inner.type === 'TSTypeLiteral') {
|
|
255
|
-
objectType = inner
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
if (
|
|
261
|
-
objectType.type === 'TSTypeLiteral' &&
|
|
262
|
-
!graphql.isInterfaceType(fragmentRootType) &&
|
|
263
|
-
!graphql.isUnionType(fragmentRootType)
|
|
264
|
-
) {
|
|
265
|
-
const existingTypenameIndex = objectType.members.findIndex(
|
|
266
|
-
(member) =>
|
|
267
|
-
member.type === 'TSPropertySignature' &&
|
|
268
|
-
member.key.type === 'Identifier' &&
|
|
269
|
-
member.key.name === '__typename'
|
|
270
|
-
)
|
|
271
|
-
if (existingTypenameIndex !== -1) {
|
|
272
|
-
objectType.members.splice(existingTypenameIndex, 1)
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
// add __typename to the list
|
|
276
|
-
objectType.members.push(
|
|
277
|
-
readonlyProperty(
|
|
278
|
-
AST.tsPropertySignature(
|
|
279
|
-
AST.identifier('__typename'),
|
|
280
|
-
AST.tsTypeAnnotation(AST.tsLiteralType(AST.stringLiteral(typeName)))
|
|
281
|
-
),
|
|
282
|
-
allowReadonly
|
|
283
|
-
)
|
|
284
|
-
)
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// we're done massaging the type
|
|
288
|
-
return [{ type: fragmentRootType, tsType: fragmentType }]
|
|
289
|
-
})
|
|
290
|
-
|
|
291
|
-
//
|
|
292
|
-
if (Object.keys(inlineFragmentSelections).length > 0) {
|
|
293
|
-
// // build up the discriminated type
|
|
294
|
-
let selectionTypes = Object.entries(inlineFragmentSelections).map(
|
|
295
|
-
([typeName, { type, tsType }]) => {
|
|
296
|
-
// the selection for a concrete type is really the intersection of itself
|
|
297
|
-
// with every abstract type it implements. go over every fragment belonging
|
|
298
|
-
// to an abstract type and check if this type implements it.
|
|
299
|
-
return AST.tsParenthesizedType(
|
|
300
|
-
AST.tsIntersectionType(
|
|
301
|
-
[tsType]
|
|
302
|
-
// remove any inner nullability flags
|
|
303
|
-
.flatMap((type) => {
|
|
304
|
-
// if we are looking at a union we might have nulls in there
|
|
305
|
-
if (type.type === 'TSUnionType') {
|
|
306
|
-
return type.types.filter(
|
|
307
|
-
(innerType) =>
|
|
308
|
-
innerType.type !== 'TSNullKeyword' &&
|
|
309
|
-
innerType.type !== 'TSUndefinedKeyword'
|
|
310
|
-
)
|
|
311
|
-
}
|
|
312
|
-
return type
|
|
313
|
-
})
|
|
314
|
-
)
|
|
315
|
-
)
|
|
316
|
-
}
|
|
317
|
-
)
|
|
318
|
-
|
|
319
|
-
// build up the list of fragment types
|
|
320
|
-
result = AST.tsIntersectionType([
|
|
321
|
-
result,
|
|
322
|
-
AST.tsParenthesizedType(AST.tsUnionType(selectionTypes)),
|
|
323
|
-
])
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
// we shouldn't get here
|
|
327
|
-
else {
|
|
328
|
-
throw Error('Could not convert selection to typescript')
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// we need to wrap the result in the right combination of nullable, list, and non-null markers
|
|
332
|
-
for (const toWrap of wrappers) {
|
|
333
|
-
if (!root && toWrap === TypeWrapper.Nullable) {
|
|
334
|
-
result = nullableField(result)
|
|
335
|
-
}
|
|
336
|
-
// if its a non-null we don't need to add anything
|
|
337
|
-
else if (toWrap === TypeWrapper.NonNull) {
|
|
338
|
-
continue
|
|
339
|
-
}
|
|
340
|
-
// it could be a list
|
|
341
|
-
else if (toWrap === TypeWrapper.List) {
|
|
342
|
-
result = AST.tsArrayType(AST.tsParenthesizedType(result))
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
return result
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
// look up the selection type info
|
|
350
|
-
export function selectionTypeInfo(
|
|
351
|
-
schema: graphql.GraphQLSchema,
|
|
352
|
-
filepath: string,
|
|
353
|
-
rootType: graphql.GraphQLObjectType<any, any>,
|
|
354
|
-
selection: graphql.SelectionNode
|
|
355
|
-
): { field: graphql.GraphQLField<any, any>; type: graphql.GraphQLNamedType } {
|
|
356
|
-
// the field we are looking at
|
|
357
|
-
const selectionName = (selection as graphql.FieldNode).name.value
|
|
358
|
-
|
|
359
|
-
// look up the fields for the root object
|
|
360
|
-
let fields: { [fieldName: string]: graphql.GraphQLField<any, any> } = {}
|
|
361
|
-
|
|
362
|
-
// if the parent type in question is a union, there is only __typename
|
|
363
|
-
if (selection.kind === 'Field' && selection.name.value === '__typename') {
|
|
364
|
-
return {
|
|
365
|
-
field: {
|
|
366
|
-
name: '__typename',
|
|
367
|
-
// @ts-ignore
|
|
368
|
-
type: schema.getType('String')!,
|
|
369
|
-
args: [],
|
|
370
|
-
},
|
|
371
|
-
type: schema.getType('String')!,
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
// unwrap non-nulls
|
|
375
|
-
else if (graphql.isNonNullType(rootType) && 'getFields' in rootType.ofType) {
|
|
376
|
-
fields = rootType.ofType.getFields()
|
|
377
|
-
}
|
|
378
|
-
// anything else
|
|
379
|
-
else {
|
|
380
|
-
fields = rootType.getFields()
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
const field = fields[selectionName]
|
|
384
|
-
|
|
385
|
-
if (!field) {
|
|
386
|
-
throw new HoudiniError({
|
|
387
|
-
filepath,
|
|
388
|
-
message: `Could not find type information for field ${rootType.toString()}.${selectionName} ${field}`,
|
|
389
|
-
})
|
|
390
|
-
}
|
|
391
|
-
const fieldType = graphql.getNamedType(field.type) as unknown as graphql.GraphQLNamedType
|
|
392
|
-
if (!fieldType) {
|
|
393
|
-
throw new HoudiniError({
|
|
394
|
-
filepath,
|
|
395
|
-
message: `Could not find type information for field ${rootType.toString()}.${selectionName} ${field}`,
|
|
396
|
-
})
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
const fieldTypeName = fieldType.name
|
|
400
|
-
|
|
401
|
-
// and the actual object type that it refers to
|
|
402
|
-
// @ts-ignore
|
|
403
|
-
const selectionType = schema.getType(fieldTypeName) as graphql.GraphQLObjectType
|
|
404
|
-
if (!selectionType) {
|
|
405
|
-
throw new HoudiniError({ filepath, message: 'Could not find type for ' + fieldTypeName })
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
return { field, type: selectionType }
|
|
409
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import type { TSTypeKind } from 'ast-types/gen/kinds'
|
|
2
|
-
import * as graphql from 'graphql'
|
|
3
|
-
import * as recast from 'recast'
|
|
4
|
-
|
|
5
|
-
import { Config } from '../../../lib'
|
|
6
|
-
import { TypeWrapper, unwrapType } from '../../utils'
|
|
7
|
-
import { nullableField, scalarPropertyValue } from './types'
|
|
8
|
-
|
|
9
|
-
const AST = recast.types.builders
|
|
10
|
-
|
|
11
|
-
// return the property
|
|
12
|
-
export function tsTypeReference(
|
|
13
|
-
config: Config,
|
|
14
|
-
missingScalars: Set<string>,
|
|
15
|
-
definition: { type: graphql.TypeNode }
|
|
16
|
-
): TSTypeKind {
|
|
17
|
-
const { type, wrappers } = unwrapType(config, definition.type)
|
|
18
|
-
|
|
19
|
-
// convert the inner type
|
|
20
|
-
let result
|
|
21
|
-
// if we're looking at a scalar
|
|
22
|
-
if (graphql.isScalarType(type)) {
|
|
23
|
-
result = scalarPropertyValue(config, missingScalars, type)
|
|
24
|
-
}
|
|
25
|
-
// we're looking at an object
|
|
26
|
-
else {
|
|
27
|
-
// the fields of the object end up as properties in the type literal
|
|
28
|
-
result = AST.tsTypeReference(AST.identifier(type.name))
|
|
29
|
-
}
|
|
30
|
-
for (const toWrap of wrappers) {
|
|
31
|
-
// if its a non-null we don't need to add anything
|
|
32
|
-
if (toWrap === TypeWrapper.NonNull) {
|
|
33
|
-
continue
|
|
34
|
-
} else if (toWrap === TypeWrapper.Nullable) {
|
|
35
|
-
result = nullableField(result, true)
|
|
36
|
-
}
|
|
37
|
-
// it could be a list
|
|
38
|
-
else if (toWrap === TypeWrapper.List) {
|
|
39
|
-
result = AST.tsArrayType(AST.tsParenthesizedType(result))
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return result
|
|
44
|
-
}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import type { TSTypeKind } from 'ast-types/gen/kinds'
|
|
2
|
-
import * as graphql from 'graphql'
|
|
3
|
-
import * as recast from 'recast'
|
|
4
|
-
|
|
5
|
-
import { Config } from '../../../lib'
|
|
6
|
-
|
|
7
|
-
const AST = recast.types.builders
|
|
8
|
-
|
|
9
|
-
export function readonlyProperty(
|
|
10
|
-
prop: recast.types.namedTypes.TSPropertySignature,
|
|
11
|
-
enable: boolean = true
|
|
12
|
-
): recast.types.namedTypes.TSPropertySignature {
|
|
13
|
-
if (enable) {
|
|
14
|
-
prop.readonly = true
|
|
15
|
-
}
|
|
16
|
-
return prop
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function nullableField(inner: TSTypeKind, input = false) {
|
|
20
|
-
// the members of the union
|
|
21
|
-
const members = [inner, AST.tsNullKeyword()]
|
|
22
|
-
if (input) {
|
|
23
|
-
members.push(AST.tsUndefinedKeyword())
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return AST.tsUnionType(members)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function scalarPropertyValue(
|
|
30
|
-
config: Config,
|
|
31
|
-
missingScalars: Set<string>,
|
|
32
|
-
target: graphql.GraphQLNamedType
|
|
33
|
-
): TSTypeKind {
|
|
34
|
-
switch (target.name) {
|
|
35
|
-
case 'String': {
|
|
36
|
-
return AST.tsStringKeyword()
|
|
37
|
-
}
|
|
38
|
-
case 'Int': {
|
|
39
|
-
return AST.tsNumberKeyword()
|
|
40
|
-
}
|
|
41
|
-
case 'Float': {
|
|
42
|
-
return AST.tsNumberKeyword()
|
|
43
|
-
}
|
|
44
|
-
case 'Boolean': {
|
|
45
|
-
return AST.tsBooleanKeyword()
|
|
46
|
-
}
|
|
47
|
-
case 'ID': {
|
|
48
|
-
return AST.tsStringKeyword()
|
|
49
|
-
}
|
|
50
|
-
default: {
|
|
51
|
-
// if we're looking at a non-null type
|
|
52
|
-
if (graphql.isNonNullType(target) && 'ofType' in target) {
|
|
53
|
-
return scalarPropertyValue(
|
|
54
|
-
config,
|
|
55
|
-
missingScalars,
|
|
56
|
-
target.ofType as graphql.GraphQLNamedType
|
|
57
|
-
)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// the type could be a custom scalar we know about
|
|
61
|
-
if (config.scalars?.[target.name]) {
|
|
62
|
-
return AST.tsTypeReference(AST.identifier(config.scalars?.[target.name].type))
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
missingScalars.add(target.name)
|
|
66
|
-
|
|
67
|
-
return AST.tsAnyKeyword()
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export function enumDeclaration(type: graphql.GraphQLEnumType) {
|
|
73
|
-
return AST.tsEnumDeclaration(
|
|
74
|
-
AST.identifier(type.name),
|
|
75
|
-
type
|
|
76
|
-
.getValues()
|
|
77
|
-
.map((value) =>
|
|
78
|
-
AST.tsEnumMember(AST.identifier(value.name), AST.stringLiteral(value.name))
|
|
79
|
-
)
|
|
80
|
-
)
|
|
81
|
-
}
|