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.
Files changed (148) hide show
  1. package/README.md +33 -0
  2. package/build/cmd-cjs/index.js +124 -38
  3. package/build/cmd-esm/index.js +124 -38
  4. package/build/codegen-cjs/index.js +112 -36
  5. package/build/codegen-esm/index.js +112 -36
  6. package/build/lib/config.d.ts +3 -0
  7. package/build/lib-cjs/index.js +31 -12
  8. package/build/lib-esm/index.js +31 -12
  9. package/build/runtime/cache/cache.d.ts +1 -1
  10. package/build/runtime/cache/lists.d.ts +1 -1
  11. package/build/runtime/lib/config.d.ts +10 -2
  12. package/build/runtime/lib/types.d.ts +1 -0
  13. package/build/runtime-cjs/cache/cache.d.ts +1 -1
  14. package/build/runtime-cjs/cache/cache.js +6 -6
  15. package/build/runtime-cjs/cache/lists.d.ts +1 -1
  16. package/build/runtime-cjs/cache/lists.js +15 -6
  17. package/build/runtime-cjs/cache/tests/list.test.js +160 -70
  18. package/build/runtime-cjs/lib/config.d.ts +10 -2
  19. package/build/runtime-cjs/lib/types.d.ts +1 -0
  20. package/build/runtime-esm/cache/cache.d.ts +1 -1
  21. package/build/runtime-esm/cache/cache.js +6 -6
  22. package/build/runtime-esm/cache/lists.d.ts +1 -1
  23. package/build/runtime-esm/cache/lists.js +15 -6
  24. package/build/runtime-esm/cache/tests/list.test.js +160 -70
  25. package/build/runtime-esm/lib/config.d.ts +10 -2
  26. package/build/runtime-esm/lib/types.d.ts +1 -0
  27. package/build/test-cjs/index.js +122 -36
  28. package/build/test-esm/index.js +122 -36
  29. package/build/vite-cjs/index.js +122 -36
  30. package/build/vite-esm/index.js +122 -36
  31. package/package.json +16 -1
  32. package/.turbo/turbo-compile.log +0 -5
  33. package/.turbo/turbo-typedefs.log +0 -5
  34. package/CHANGELOG.md +0 -367
  35. package/src/cmd/generate.ts +0 -54
  36. package/src/cmd/index.ts +0 -60
  37. package/src/cmd/init.ts +0 -637
  38. package/src/cmd/pullSchema.ts +0 -40
  39. package/src/codegen/generators/artifacts/artifacts.test.ts +0 -2978
  40. package/src/codegen/generators/artifacts/fieldKey.ts +0 -60
  41. package/src/codegen/generators/artifacts/index.ts +0 -330
  42. package/src/codegen/generators/artifacts/indexFile.ts +0 -24
  43. package/src/codegen/generators/artifacts/inputs.ts +0 -81
  44. package/src/codegen/generators/artifacts/operations.ts +0 -263
  45. package/src/codegen/generators/artifacts/pagination.test.ts +0 -664
  46. package/src/codegen/generators/artifacts/policy.test.ts +0 -298
  47. package/src/codegen/generators/artifacts/selection.ts +0 -208
  48. package/src/codegen/generators/artifacts/utils.test.ts +0 -118
  49. package/src/codegen/generators/artifacts/utils.ts +0 -108
  50. package/src/codegen/generators/definitions/enums.test.ts +0 -61
  51. package/src/codegen/generators/definitions/enums.ts +0 -68
  52. package/src/codegen/generators/definitions/index.ts +0 -11
  53. package/src/codegen/generators/definitions/schema.test.ts +0 -227
  54. package/src/codegen/generators/index.ts +0 -6
  55. package/src/codegen/generators/indexFile/index.ts +0 -63
  56. package/src/codegen/generators/indexFile/indexFile.test.ts +0 -72
  57. package/src/codegen/generators/persistedQueries/index.ts +0 -55
  58. package/src/codegen/generators/persistedQueries/persistedQuery.test.ts +0 -26
  59. package/src/codegen/generators/runtime/index.test.ts +0 -74
  60. package/src/codegen/generators/runtime/index.ts +0 -64
  61. package/src/codegen/generators/runtime/runtime.test.ts +0 -25
  62. package/src/codegen/generators/typescript/addReferencedInputTypes.ts +0 -77
  63. package/src/codegen/generators/typescript/index.ts +0 -412
  64. package/src/codegen/generators/typescript/inlineType.ts +0 -409
  65. package/src/codegen/generators/typescript/typeReference.ts +0 -44
  66. package/src/codegen/generators/typescript/types.ts +0 -81
  67. package/src/codegen/generators/typescript/typescript.test.ts +0 -1434
  68. package/src/codegen/index.ts +0 -406
  69. package/src/codegen/transforms/addID.test.ts +0 -93
  70. package/src/codegen/transforms/addID.ts +0 -86
  71. package/src/codegen/transforms/composeQueries.test.ts +0 -50
  72. package/src/codegen/transforms/composeQueries.ts +0 -154
  73. package/src/codegen/transforms/fragmentVariables.test.ts +0 -636
  74. package/src/codegen/transforms/fragmentVariables.ts +0 -417
  75. package/src/codegen/transforms/index.ts +0 -7
  76. package/src/codegen/transforms/list.ts +0 -485
  77. package/src/codegen/transforms/lists.test.ts +0 -530
  78. package/src/codegen/transforms/paginate.test.ts +0 -1481
  79. package/src/codegen/transforms/paginate.ts +0 -750
  80. package/src/codegen/transforms/schema.test.ts +0 -136
  81. package/src/codegen/transforms/schema.ts +0 -104
  82. package/src/codegen/transforms/typename.test.ts +0 -125
  83. package/src/codegen/transforms/typename.ts +0 -55
  84. package/src/codegen/utils/commonjs.ts +0 -26
  85. package/src/codegen/utils/flattenSelections.ts +0 -179
  86. package/src/codegen/utils/graphql.test.ts +0 -35
  87. package/src/codegen/utils/graphql.ts +0 -79
  88. package/src/codegen/utils/index.ts +0 -5
  89. package/src/codegen/utils/moduleExport.ts +0 -27
  90. package/src/codegen/utils/murmur.ts +0 -79
  91. package/src/codegen/validators/index.ts +0 -4
  92. package/src/codegen/validators/noIDAlias.test.ts +0 -71
  93. package/src/codegen/validators/noIDAlias.ts +0 -39
  94. package/src/codegen/validators/plugins.ts +0 -25
  95. package/src/codegen/validators/typeCheck.test.ts +0 -904
  96. package/src/codegen/validators/typeCheck.ts +0 -1031
  97. package/src/codegen/validators/uniqueNames.test.ts +0 -59
  98. package/src/codegen/validators/uniqueNames.ts +0 -39
  99. package/src/lib/cleanupFiles.ts +0 -20
  100. package/src/lib/config.test.ts +0 -13
  101. package/src/lib/config.ts +0 -943
  102. package/src/lib/constants.ts +0 -11
  103. package/src/lib/error.ts +0 -24
  104. package/src/lib/fs.ts +0 -285
  105. package/src/lib/graphql.test.ts +0 -211
  106. package/src/lib/graphql.ts +0 -200
  107. package/src/lib/imports.ts +0 -82
  108. package/src/lib/index.ts +0 -17
  109. package/src/lib/introspection.ts +0 -39
  110. package/src/lib/parse.test.ts +0 -75
  111. package/src/lib/parse.ts +0 -23
  112. package/src/lib/path.ts +0 -49
  113. package/src/lib/pipeline.ts +0 -17
  114. package/src/lib/types.ts +0 -34
  115. package/src/lib/walk.ts +0 -104
  116. package/src/runtime/cache/cache.ts +0 -1023
  117. package/src/runtime/cache/gc.ts +0 -56
  118. package/src/runtime/cache/index.ts +0 -3
  119. package/src/runtime/cache/lists.ts +0 -502
  120. package/src/runtime/cache/storage.ts +0 -574
  121. package/src/runtime/cache/stuff.ts +0 -77
  122. package/src/runtime/cache/subscription.ts +0 -329
  123. package/src/runtime/cache/tests/availability.test.ts +0 -408
  124. package/src/runtime/cache/tests/gc.test.ts +0 -319
  125. package/src/runtime/cache/tests/keys.test.ts +0 -36
  126. package/src/runtime/cache/tests/list.test.ts +0 -3747
  127. package/src/runtime/cache/tests/readwrite.test.ts +0 -1201
  128. package/src/runtime/cache/tests/scalars.test.ts +0 -218
  129. package/src/runtime/cache/tests/storage.test.ts +0 -426
  130. package/src/runtime/cache/tests/subscriptions.test.ts +0 -1757
  131. package/src/runtime/index.ts +0 -29
  132. package/src/runtime/lib/config.ts +0 -201
  133. package/src/runtime/lib/constants.ts +0 -17
  134. package/src/runtime/lib/deepEquals.ts +0 -32
  135. package/src/runtime/lib/errors.ts +0 -8
  136. package/src/runtime/lib/index.ts +0 -8
  137. package/src/runtime/lib/log.ts +0 -69
  138. package/src/runtime/lib/network.ts +0 -303
  139. package/src/runtime/lib/networkUtils.ts +0 -151
  140. package/src/runtime/lib/scalars.test.ts +0 -877
  141. package/src/runtime/lib/scalars.ts +0 -195
  142. package/src/runtime/lib/types.ts +0 -194
  143. package/src/test/index.ts +0 -294
  144. package/src/vite/ast.ts +0 -107
  145. package/src/vite/houdini.ts +0 -113
  146. package/src/vite/imports.ts +0 -129
  147. package/src/vite/index.ts +0 -55
  148. 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,104 +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
- @${
48
- config.listParentDirective
49
- } is used to provide a parentID without specifying position or in situations
50
- where it doesn't make sense (eg when deleting a node.)
51
- """
52
- directive @${config.listParentDirective}(value: ID!) on FRAGMENT_SPREAD
53
-
54
- """
55
- @${
56
- config.whenDirective
57
- } is used to provide a conditional or in situations where it doesn't make sense (eg when removing or deleting a node.)
58
- """
59
- directive @${config.whenDirective} on FRAGMENT_SPREAD
60
-
61
- """
62
- @${
63
- config.whenNotDirective
64
- } is used to provide a conditional or in situations where it doesn't make sense (eg when removing or deleting a node.)
65
- """
66
- directive @${config.whenNotDirective} on FRAGMENT_SPREAD
67
-
68
- """
69
- @${config.argumentsDirective} is used to define the arguments of a fragment
70
- """
71
- directive @${config.argumentsDirective} on FRAGMENT_DEFINITION
72
-
73
- """
74
- @${config.cacheDirective} is used to specify cache rules for a query
75
- """
76
- directive @${config.cacheDirective}(${config.cachePolicyArg}: CachePolicy, ${
77
- config.cachePartialArg
78
- }: Boolean) on QUERY
79
-
80
- """
81
- @${config.houdiniDirective} is used to configure houdini's internal behavior
82
- """
83
- directive @${config.houdiniDirective}(
84
- """
85
- Opt-in to an automatic load function (only valid when used at queries)
86
- """
87
- load: Boolean! = true
88
- """
89
- Mask fragment fields (only valid when used at a fragment spread)
90
- """
91
- mask: Boolean! = ${config.disableMasking ? 'false' : 'true'}
92
- ) on QUERY | FRAGMENT_SPREAD
93
- `
94
-
95
- // if the config does not have the cache directive, then we need to add it
96
- let currentSchema = graphql.printSchema(config.schema)
97
- if (!currentSchema.includes(`directive @${config.listDirective}`)) {
98
- currentSchema += internalSchema
99
- }
100
-
101
- config.newSchema += internalSchema
102
- // add the static extra bits that will be used by other transforms
103
- config.schema = graphql.buildSchema(currentSchema)
104
- }
@@ -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
- })