houdini 0.17.9 → 0.17.11
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 +2 -2
- package/build/cmd-esm/index.js +2 -2
- package/package.json +16 -1
- package/.turbo/turbo-compile.log +0 -5
- package/.turbo/turbo-typedefs.log +0 -5
- package/CHANGELOG.md +0 -377
- 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 -3246
- 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 -281
- 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 -236
- 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 -484
- package/src/codegen/transforms/lists.test.ts +0 -530
- package/src/codegen/transforms/paginate.test.ts +0 -1528
- package/src/codegen/transforms/paginate.ts +0 -770
- package/src/codegen/transforms/schema.test.ts +0 -136
- package/src/codegen/transforms/schema.ts +0 -109
- 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 -960
- package/src/codegen/validators/typeCheck.ts +0 -1086
- 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 -954
- 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 -1026
- package/src/runtime/cache/gc.ts +0 -56
- package/src/runtime/cache/index.ts +0 -3
- package/src/runtime/cache/lists.ts +0 -516
- 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 -3854
- 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 -211
- 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 -195
- 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,136 +0,0 @@
|
|
|
1
|
-
import { describe, test } from 'vitest'
|
|
2
|
-
|
|
3
|
-
import { pipelineTest, testConfig } from '../../test'
|
|
4
|
-
|
|
5
|
-
describe('schema transform', function () {
|
|
6
|
-
// we'll test the schema additions by pushing some documents through
|
|
7
|
-
// and make sure they don't error
|
|
8
|
-
const table = [
|
|
9
|
-
{
|
|
10
|
-
title: 'list directive',
|
|
11
|
-
documents: [
|
|
12
|
-
`
|
|
13
|
-
fragment Foo on User {
|
|
14
|
-
|
|
15
|
-
friends @list(name:"Friends") {
|
|
16
|
-
id
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
`,
|
|
20
|
-
],
|
|
21
|
-
pass: true,
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
title: 'prepend directive',
|
|
25
|
-
documents: [
|
|
26
|
-
`
|
|
27
|
-
mutation Update {
|
|
28
|
-
updateUser {
|
|
29
|
-
...A @prepend
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
`,
|
|
33
|
-
`
|
|
34
|
-
fragment A on User {
|
|
35
|
-
id
|
|
36
|
-
}
|
|
37
|
-
`,
|
|
38
|
-
],
|
|
39
|
-
pass: true,
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
title: 'append directive',
|
|
43
|
-
documents: [
|
|
44
|
-
`
|
|
45
|
-
mutation Update {
|
|
46
|
-
updateUser {
|
|
47
|
-
...A @prepend
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
`,
|
|
51
|
-
`
|
|
52
|
-
fragment A on User {
|
|
53
|
-
id
|
|
54
|
-
}
|
|
55
|
-
`,
|
|
56
|
-
],
|
|
57
|
-
pass: true,
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
title: 'prepend directive - when arg',
|
|
61
|
-
documents: [
|
|
62
|
-
`
|
|
63
|
-
mutation Update {
|
|
64
|
-
updateUser {
|
|
65
|
-
...A @prepend(when: { value: "value" })
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
`,
|
|
69
|
-
`
|
|
70
|
-
fragment A on User {
|
|
71
|
-
id
|
|
72
|
-
}
|
|
73
|
-
`,
|
|
74
|
-
],
|
|
75
|
-
pass: true,
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
title: 'when directive',
|
|
79
|
-
documents: [
|
|
80
|
-
`
|
|
81
|
-
mutation Update {
|
|
82
|
-
updateUser {
|
|
83
|
-
...A @when(argument: "value", value: "value")
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
`,
|
|
87
|
-
`
|
|
88
|
-
fragment A on User {
|
|
89
|
-
id
|
|
90
|
-
}
|
|
91
|
-
`,
|
|
92
|
-
],
|
|
93
|
-
pass: true,
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
title: 'when_not directive',
|
|
97
|
-
documents: [
|
|
98
|
-
`
|
|
99
|
-
mutation Update {
|
|
100
|
-
updateUser {
|
|
101
|
-
...A @when_not(argument: "value", value: "value")
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
`,
|
|
105
|
-
`
|
|
106
|
-
fragment A on User {
|
|
107
|
-
id
|
|
108
|
-
}
|
|
109
|
-
`,
|
|
110
|
-
],
|
|
111
|
-
pass: true,
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
title: 'append directive - when arg',
|
|
115
|
-
documents: [
|
|
116
|
-
`
|
|
117
|
-
mutation Update {
|
|
118
|
-
updateUser {
|
|
119
|
-
...A @append(when: { value: "value" })
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
`,
|
|
123
|
-
`
|
|
124
|
-
fragment A on User {
|
|
125
|
-
id
|
|
126
|
-
}
|
|
127
|
-
`,
|
|
128
|
-
],
|
|
129
|
-
pass: true,
|
|
130
|
-
},
|
|
131
|
-
]
|
|
132
|
-
|
|
133
|
-
for (const row of table) {
|
|
134
|
-
test(row.title, pipelineTest(testConfig(), row.documents, row.pass))
|
|
135
|
-
}
|
|
136
|
-
})
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import * as graphql from 'graphql'
|
|
2
|
-
|
|
3
|
-
import { Config, CollectedGraphQLDocument, siteURL } from '../../lib'
|
|
4
|
-
import { CachePolicy } from '../../runtime/lib/types'
|
|
5
|
-
|
|
6
|
-
// graphqlExtensions adds a few different things to the graphql schema
|
|
7
|
-
export default async function graphqlExtensions(
|
|
8
|
-
config: Config,
|
|
9
|
-
documents: CollectedGraphQLDocument[]
|
|
10
|
-
): Promise<void> {
|
|
11
|
-
// the bits to add to the schema
|
|
12
|
-
const internalSchema = `
|
|
13
|
-
enum CachePolicy {
|
|
14
|
-
${CachePolicy.CacheAndNetwork}
|
|
15
|
-
${CachePolicy.CacheOnly}
|
|
16
|
-
${CachePolicy.CacheOrNetwork}
|
|
17
|
-
${CachePolicy.NetworkOnly}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
"""
|
|
21
|
-
@${config.listDirective} is used to mark a field for the runtime as a place to add or remove
|
|
22
|
-
entities in mutations
|
|
23
|
-
"""
|
|
24
|
-
directive @${config.listDirective}(${config.listNameArg}: String!, connection: Boolean) on FIELD
|
|
25
|
-
|
|
26
|
-
"""
|
|
27
|
-
@${config.paginateDirective} is used to to mark a field for pagination.
|
|
28
|
-
More info in the [doc](${siteURL}/guides/pagination).
|
|
29
|
-
"""
|
|
30
|
-
directive @${config.paginateDirective}(${config.paginateNameArg}: String) on FIELD
|
|
31
|
-
|
|
32
|
-
"""
|
|
33
|
-
@${config.listPrependDirective} is used to tell the runtime to add the result to the end of the list
|
|
34
|
-
"""
|
|
35
|
-
directive @${config.listPrependDirective}(
|
|
36
|
-
${config.listDirectiveParentIDArg}: ID
|
|
37
|
-
) on FRAGMENT_SPREAD
|
|
38
|
-
|
|
39
|
-
"""
|
|
40
|
-
@${
|
|
41
|
-
config.listAppendDirective
|
|
42
|
-
} is used to tell the runtime to add the result to the start of the list
|
|
43
|
-
"""
|
|
44
|
-
directive @${config.listAppendDirective}(${config.listDirectiveParentIDArg}: ID) on FRAGMENT_SPREAD
|
|
45
|
-
|
|
46
|
-
"""
|
|
47
|
-
@${config.listAllListsDirective} is used to tell the runtime to add the result to all list
|
|
48
|
-
"""
|
|
49
|
-
directive @${config.listAllListsDirective} on FRAGMENT_SPREAD
|
|
50
|
-
|
|
51
|
-
"""
|
|
52
|
-
@${
|
|
53
|
-
config.listParentDirective
|
|
54
|
-
} is used to provide a parentID without specifying position or in situations
|
|
55
|
-
where it doesn't make sense (eg when deleting a node.)
|
|
56
|
-
"""
|
|
57
|
-
directive @${config.listParentDirective}(value: ID!) on FRAGMENT_SPREAD
|
|
58
|
-
|
|
59
|
-
"""
|
|
60
|
-
@${
|
|
61
|
-
config.whenDirective
|
|
62
|
-
} is used to provide a conditional or in situations where it doesn't make sense (eg when removing or deleting a node.)
|
|
63
|
-
"""
|
|
64
|
-
directive @${config.whenDirective} on FRAGMENT_SPREAD
|
|
65
|
-
|
|
66
|
-
"""
|
|
67
|
-
@${
|
|
68
|
-
config.whenNotDirective
|
|
69
|
-
} is used to provide a conditional or in situations where it doesn't make sense (eg when removing or deleting a node.)
|
|
70
|
-
"""
|
|
71
|
-
directive @${config.whenNotDirective} on FRAGMENT_SPREAD
|
|
72
|
-
|
|
73
|
-
"""
|
|
74
|
-
@${config.argumentsDirective} is used to define the arguments of a fragment
|
|
75
|
-
"""
|
|
76
|
-
directive @${config.argumentsDirective} on FRAGMENT_DEFINITION
|
|
77
|
-
|
|
78
|
-
"""
|
|
79
|
-
@${config.cacheDirective} is used to specify cache rules for a query
|
|
80
|
-
"""
|
|
81
|
-
directive @${config.cacheDirective}(${config.cachePolicyArg}: CachePolicy, ${
|
|
82
|
-
config.cachePartialArg
|
|
83
|
-
}: Boolean) on QUERY
|
|
84
|
-
|
|
85
|
-
"""
|
|
86
|
-
@${config.houdiniDirective} is used to configure houdini's internal behavior
|
|
87
|
-
"""
|
|
88
|
-
directive @${config.houdiniDirective}(
|
|
89
|
-
"""
|
|
90
|
-
Opt-in to an automatic load function (only valid when used at queries)
|
|
91
|
-
"""
|
|
92
|
-
load: Boolean! = true
|
|
93
|
-
"""
|
|
94
|
-
Mask fragment fields (only valid when used at a fragment spread)
|
|
95
|
-
"""
|
|
96
|
-
mask: Boolean! = ${config.disableMasking ? 'false' : 'true'}
|
|
97
|
-
) on QUERY | FRAGMENT_SPREAD
|
|
98
|
-
`
|
|
99
|
-
|
|
100
|
-
// if the config does not have the cache directive, then we need to add it
|
|
101
|
-
let currentSchema = graphql.printSchema(config.schema)
|
|
102
|
-
if (!currentSchema.includes(`directive @${config.listDirective}`)) {
|
|
103
|
-
currentSchema += internalSchema
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
config.newSchema += internalSchema
|
|
107
|
-
// add the static extra bits that will be used by other transforms
|
|
108
|
-
config.schema = graphql.buildSchema(currentSchema)
|
|
109
|
-
}
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { test, expect } from 'vitest'
|
|
2
|
-
|
|
3
|
-
import { runPipeline } from '../../codegen'
|
|
4
|
-
import { mockCollectedDoc, testConfig } from '../../test'
|
|
5
|
-
|
|
6
|
-
test('adds __typename on interface selection sets under query', async function () {
|
|
7
|
-
const docs = [
|
|
8
|
-
mockCollectedDoc(
|
|
9
|
-
`
|
|
10
|
-
query Friends {
|
|
11
|
-
friends {
|
|
12
|
-
... on Cat {
|
|
13
|
-
id
|
|
14
|
-
}
|
|
15
|
-
... on Ghost {
|
|
16
|
-
name
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
`
|
|
21
|
-
),
|
|
22
|
-
]
|
|
23
|
-
|
|
24
|
-
// run the pipeline
|
|
25
|
-
const config = testConfig()
|
|
26
|
-
await runPipeline(config, docs)
|
|
27
|
-
|
|
28
|
-
expect(docs[0].document).toMatchInlineSnapshot(`
|
|
29
|
-
query Friends {
|
|
30
|
-
friends {
|
|
31
|
-
... on Cat {
|
|
32
|
-
id
|
|
33
|
-
}
|
|
34
|
-
... on Ghost {
|
|
35
|
-
name
|
|
36
|
-
}
|
|
37
|
-
__typename
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
`)
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
test('adds __typename on interface selection sets under an object', async function () {
|
|
45
|
-
const docs = [
|
|
46
|
-
mockCollectedDoc(
|
|
47
|
-
`
|
|
48
|
-
query Friends {
|
|
49
|
-
users(stringValue: "hello") {
|
|
50
|
-
friendsInterface {
|
|
51
|
-
... on Cat {
|
|
52
|
-
id
|
|
53
|
-
}
|
|
54
|
-
... on Ghost {
|
|
55
|
-
name
|
|
56
|
-
aka
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
`
|
|
62
|
-
),
|
|
63
|
-
]
|
|
64
|
-
|
|
65
|
-
// run the pipeline
|
|
66
|
-
const config = testConfig()
|
|
67
|
-
await runPipeline(config, docs)
|
|
68
|
-
|
|
69
|
-
expect(docs[0].document).toMatchInlineSnapshot(`
|
|
70
|
-
query Friends {
|
|
71
|
-
users(stringValue: "hello") {
|
|
72
|
-
friendsInterface {
|
|
73
|
-
... on Cat {
|
|
74
|
-
id
|
|
75
|
-
}
|
|
76
|
-
... on Ghost {
|
|
77
|
-
name
|
|
78
|
-
aka
|
|
79
|
-
}
|
|
80
|
-
__typename
|
|
81
|
-
}
|
|
82
|
-
id
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
`)
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
test('adds __typename on unions', async function () {
|
|
90
|
-
const docs = [
|
|
91
|
-
mockCollectedDoc(
|
|
92
|
-
`
|
|
93
|
-
query Friends {
|
|
94
|
-
entities {
|
|
95
|
-
... on Cat {
|
|
96
|
-
id
|
|
97
|
-
}
|
|
98
|
-
... on Ghost {
|
|
99
|
-
name
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
`
|
|
104
|
-
),
|
|
105
|
-
]
|
|
106
|
-
|
|
107
|
-
// run the pipeline
|
|
108
|
-
const config = testConfig()
|
|
109
|
-
await runPipeline(config, docs)
|
|
110
|
-
|
|
111
|
-
expect(docs[0].document).toMatchInlineSnapshot(`
|
|
112
|
-
query Friends {
|
|
113
|
-
entities {
|
|
114
|
-
... on Cat {
|
|
115
|
-
id
|
|
116
|
-
}
|
|
117
|
-
... on Ghost {
|
|
118
|
-
name
|
|
119
|
-
}
|
|
120
|
-
__typename
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
`)
|
|
125
|
-
})
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import * as graphql from 'graphql'
|
|
2
|
-
|
|
3
|
-
import { Config, parentTypeFromAncestors, CollectedGraphQLDocument } from '../../lib'
|
|
4
|
-
import { unwrapType } from '../utils'
|
|
5
|
-
|
|
6
|
-
// typename adds __typename to the selection set of any unions or interfaces
|
|
7
|
-
export default async function addTypename(
|
|
8
|
-
config: Config,
|
|
9
|
-
documents: CollectedGraphQLDocument[]
|
|
10
|
-
): Promise<void> {
|
|
11
|
-
// visit every document
|
|
12
|
-
for (const doc of documents) {
|
|
13
|
-
// update the document (graphql.visit is pure)
|
|
14
|
-
doc.document = graphql.visit(doc.document, {
|
|
15
|
-
Field(node, key, parent, path, ancestors): graphql.ASTNode | undefined {
|
|
16
|
-
// if we are looking at a leaf type
|
|
17
|
-
if (!node.selectionSet) {
|
|
18
|
-
return
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// figure out the parent type
|
|
22
|
-
const type = parentTypeFromAncestors(
|
|
23
|
-
config.schema,
|
|
24
|
-
doc.filename,
|
|
25
|
-
ancestors.slice(0, -1)
|
|
26
|
-
)
|
|
27
|
-
// look up the field definition in the parent type
|
|
28
|
-
const field = type.getFields()[node.name.value]
|
|
29
|
-
|
|
30
|
-
// look up the field in the parent
|
|
31
|
-
const fieldType = unwrapType(config, field.type).type
|
|
32
|
-
// if we are looking at an interface
|
|
33
|
-
if (graphql.isInterfaceType(fieldType) || graphql.isUnionType(fieldType)) {
|
|
34
|
-
// add the __typename selection to the field's selection set
|
|
35
|
-
return {
|
|
36
|
-
...node,
|
|
37
|
-
selectionSet: {
|
|
38
|
-
...node.selectionSet,
|
|
39
|
-
selections: [
|
|
40
|
-
...node.selectionSet.selections,
|
|
41
|
-
{
|
|
42
|
-
kind: graphql.Kind.FIELD,
|
|
43
|
-
name: {
|
|
44
|
-
kind: graphql.Kind.NAME,
|
|
45
|
-
value: '__typename',
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
],
|
|
49
|
-
},
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
})
|
|
54
|
-
}
|
|
55
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
// this file exports a few functions that can be used to help generate
|
|
2
|
-
// commonjs files
|
|
3
|
-
export const cjsIndexFilePreamble = `"use strict";
|
|
4
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
5
|
-
if (k2 === undefined) k2 = k;
|
|
6
|
-
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
7
|
-
}) : (function(o, m, k, k2) {
|
|
8
|
-
if (k2 === undefined) k2 = k;
|
|
9
|
-
o[k2] = m[k];
|
|
10
|
-
}));
|
|
11
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
12
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
13
|
-
};
|
|
14
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
-
};
|
|
17
|
-
Object.defineProperty(exports, "__esModule", { value: true });`
|
|
18
|
-
|
|
19
|
-
export function exportStarFrom(where: string): string {
|
|
20
|
-
return `__exportStar(require("${where}"), exports);`
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function exportDefaultFrom(where: string, as: string): string {
|
|
24
|
-
return `var ${as} = require("${where}");
|
|
25
|
-
Object.defineProperty(exports, "${as}", { enumerable: true, get: function () { return __importDefault(${as}).default; } });`
|
|
26
|
-
}
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
import * as graphql from 'graphql'
|
|
2
|
-
|
|
3
|
-
import { Config, HoudiniError } from '../../lib'
|
|
4
|
-
|
|
5
|
-
export function flattenSelections({
|
|
6
|
-
config,
|
|
7
|
-
filepath,
|
|
8
|
-
selections,
|
|
9
|
-
fragmentDefinitions,
|
|
10
|
-
}: {
|
|
11
|
-
config: Config
|
|
12
|
-
filepath: string
|
|
13
|
-
selections: readonly graphql.SelectionNode[]
|
|
14
|
-
fragmentDefinitions: { [name: string]: graphql.FragmentDefinitionNode }
|
|
15
|
-
}): readonly graphql.SelectionNode[] {
|
|
16
|
-
// collect all of the fields together
|
|
17
|
-
const fields = new FieldCollection({
|
|
18
|
-
config,
|
|
19
|
-
filepath,
|
|
20
|
-
selections,
|
|
21
|
-
fragmentDefinitions,
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
// convert the flat fields into a selection set
|
|
25
|
-
return fields.toSelectionSet()
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
class FieldCollection {
|
|
29
|
-
config: Config
|
|
30
|
-
fragmentDefinitions: { [name: string]: graphql.FragmentDefinitionNode }
|
|
31
|
-
filepath: string
|
|
32
|
-
|
|
33
|
-
fields: { [name: string]: Field<graphql.FieldNode> }
|
|
34
|
-
inlineFragments: { [typeName: string]: Field<graphql.InlineFragmentNode> }
|
|
35
|
-
fragmentSpreads: { [fragmentName: string]: graphql.FragmentSpreadNode }
|
|
36
|
-
|
|
37
|
-
constructor(args: {
|
|
38
|
-
config: Config
|
|
39
|
-
filepath: string
|
|
40
|
-
selections: readonly graphql.SelectionNode[]
|
|
41
|
-
fragmentDefinitions: { [name: string]: graphql.FragmentDefinitionNode }
|
|
42
|
-
}) {
|
|
43
|
-
this.config = args.config
|
|
44
|
-
this.fragmentDefinitions = args.fragmentDefinitions
|
|
45
|
-
|
|
46
|
-
this.fields = {}
|
|
47
|
-
this.inlineFragments = {}
|
|
48
|
-
this.fragmentSpreads = {}
|
|
49
|
-
|
|
50
|
-
this.filepath = args.filepath
|
|
51
|
-
|
|
52
|
-
for (const selection of args.selections) {
|
|
53
|
-
this.add(selection)
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
add(selection: graphql.SelectionNode) {
|
|
58
|
-
// how we handle the field depends on what kind of field it is
|
|
59
|
-
if (selection.kind === 'Field') {
|
|
60
|
-
// figure out the key of the field
|
|
61
|
-
const key = selection.alias?.value || selection.name.value
|
|
62
|
-
|
|
63
|
-
// if we don't already have a field with that name
|
|
64
|
-
if (!this.fields[key]) {
|
|
65
|
-
// create an entry for the selection field
|
|
66
|
-
this.fields[key] = {
|
|
67
|
-
astNode: selection,
|
|
68
|
-
selection: this.empty(),
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// its safe to all this fields selections if they exist
|
|
73
|
-
for (const subselect of selection.selectionSet?.selections || []) {
|
|
74
|
-
this.fields[key].selection.add(subselect)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// we're done
|
|
78
|
-
return
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// we could run into an inline fragment that doesn't assert a type (treat it as a field selection)
|
|
82
|
-
if (selection.kind === 'InlineFragment' && !selection.typeCondition) {
|
|
83
|
-
for (const subselect of selection.selectionSet.selections) {
|
|
84
|
-
this.add(subselect)
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// we could run into an inline fragment. the application has been validated already
|
|
89
|
-
// so we just need to add it to the inline fragment for the appropriate type
|
|
90
|
-
if (selection.kind === 'InlineFragment' && selection.typeCondition) {
|
|
91
|
-
// figure out the key of the field
|
|
92
|
-
const key = selection.typeCondition.name.value
|
|
93
|
-
|
|
94
|
-
// if we don't already have an inline fragment of that type
|
|
95
|
-
if (!this.inlineFragments[key]) {
|
|
96
|
-
// create an entry for the selection field
|
|
97
|
-
this.inlineFragments[key] = {
|
|
98
|
-
astNode: selection,
|
|
99
|
-
selection: this.empty(),
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// its safe to all this fields selections if they exist
|
|
104
|
-
for (const subselect of selection.selectionSet?.selections || []) {
|
|
105
|
-
this.inlineFragments[key].selection.add(subselect)
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// we're done
|
|
109
|
-
return
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// the only thing that's left is external fragment spreads
|
|
113
|
-
if (selection.kind === 'FragmentSpread') {
|
|
114
|
-
// the application of the fragment has been validated already so track it
|
|
115
|
-
// so we can recreate
|
|
116
|
-
this.fragmentSpreads[selection.name.value] = selection
|
|
117
|
-
|
|
118
|
-
// find whether to include fragment fields
|
|
119
|
-
const houdiniDirective = selection.directives?.find(
|
|
120
|
-
({ name }) => name.value === this.config.houdiniDirective
|
|
121
|
-
)
|
|
122
|
-
const maskArgument = houdiniDirective?.arguments?.find(
|
|
123
|
-
({ name }) => name.value === 'mask'
|
|
124
|
-
)
|
|
125
|
-
let includeFragments = this.config.disableMasking
|
|
126
|
-
if (maskArgument?.value.kind === 'BooleanValue') {
|
|
127
|
-
includeFragments = !maskArgument.value.value
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// we're finished if we're not supposed to include fragments in the selection
|
|
131
|
-
if (!includeFragments) {
|
|
132
|
-
return
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const definition = this.fragmentDefinitions[selection.name.value]
|
|
136
|
-
if (!definition) {
|
|
137
|
-
throw new HoudiniError({
|
|
138
|
-
filepath: this.filepath,
|
|
139
|
-
message:
|
|
140
|
-
'Could not find referenced fragment definition: ' + selection.name.value,
|
|
141
|
-
})
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
for (const subselect of definition.selectionSet.selections) {
|
|
145
|
-
this.add(subselect)
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
toSelectionSet(): graphql.SelectionNode[] {
|
|
151
|
-
return Object.values(this.inlineFragments)
|
|
152
|
-
.map<graphql.SelectionNode>((fragment) => {
|
|
153
|
-
fragment.astNode.selectionSet.selections = fragment.selection.toSelectionSet()
|
|
154
|
-
|
|
155
|
-
return fragment.astNode
|
|
156
|
-
})
|
|
157
|
-
.concat(
|
|
158
|
-
Object.values(this.fields).map((field) => {
|
|
159
|
-
if (field.astNode.selectionSet) {
|
|
160
|
-
field.astNode.selectionSet.selections = field.selection.toSelectionSet()
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return field.astNode
|
|
164
|
-
})
|
|
165
|
-
)
|
|
166
|
-
.concat(Object.values(this.fragmentSpreads))
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
empty() {
|
|
170
|
-
return new FieldCollection({
|
|
171
|
-
config: this.config,
|
|
172
|
-
fragmentDefinitions: this.fragmentDefinitions,
|
|
173
|
-
selections: [],
|
|
174
|
-
filepath: this.filepath,
|
|
175
|
-
})
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
type Field<_AST> = { astNode: _AST; selection: FieldCollection }
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import * as graphql from 'graphql'
|
|
2
|
-
import { test, expect, describe } from 'vitest'
|
|
3
|
-
|
|
4
|
-
import { testConfig } from '../../test'
|
|
5
|
-
import { TypeWrapper, unwrapType } from './graphql'
|
|
6
|
-
|
|
7
|
-
describe('unwrapType', () => {
|
|
8
|
-
test('list of lists', function () {
|
|
9
|
-
const type: graphql.TypeNode = {
|
|
10
|
-
kind: graphql.Kind.LIST_TYPE,
|
|
11
|
-
type: {
|
|
12
|
-
kind: graphql.Kind.NON_NULL_TYPE,
|
|
13
|
-
type: {
|
|
14
|
-
kind: graphql.Kind.NAMED_TYPE,
|
|
15
|
-
name: {
|
|
16
|
-
kind: graphql.Kind.NAME,
|
|
17
|
-
value: 'User',
|
|
18
|
-
},
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const unwrapped = unwrapType(testConfig(), type)
|
|
24
|
-
|
|
25
|
-
// make sure we can get the inner type
|
|
26
|
-
expect(unwrapped.type.name).toEqual('User')
|
|
27
|
-
|
|
28
|
-
// and that we have the correct set of wrappers
|
|
29
|
-
expect(unwrapped.wrappers).toEqual([
|
|
30
|
-
TypeWrapper.NonNull,
|
|
31
|
-
TypeWrapper.List,
|
|
32
|
-
TypeWrapper.Nullable,
|
|
33
|
-
])
|
|
34
|
-
})
|
|
35
|
-
})
|