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.
Files changed (121) hide show
  1. package/README.md +33 -0
  2. package/build/cmd-cjs/index.js +2 -2
  3. package/build/cmd-esm/index.js +2 -2
  4. package/package.json +16 -1
  5. package/.turbo/turbo-compile.log +0 -5
  6. package/.turbo/turbo-typedefs.log +0 -5
  7. package/CHANGELOG.md +0 -377
  8. package/src/cmd/generate.ts +0 -54
  9. package/src/cmd/index.ts +0 -60
  10. package/src/cmd/init.ts +0 -637
  11. package/src/cmd/pullSchema.ts +0 -40
  12. package/src/codegen/generators/artifacts/artifacts.test.ts +0 -3246
  13. package/src/codegen/generators/artifacts/fieldKey.ts +0 -60
  14. package/src/codegen/generators/artifacts/index.ts +0 -330
  15. package/src/codegen/generators/artifacts/indexFile.ts +0 -24
  16. package/src/codegen/generators/artifacts/inputs.ts +0 -81
  17. package/src/codegen/generators/artifacts/operations.ts +0 -281
  18. package/src/codegen/generators/artifacts/pagination.test.ts +0 -664
  19. package/src/codegen/generators/artifacts/policy.test.ts +0 -298
  20. package/src/codegen/generators/artifacts/selection.ts +0 -208
  21. package/src/codegen/generators/artifacts/utils.test.ts +0 -118
  22. package/src/codegen/generators/artifacts/utils.ts +0 -108
  23. package/src/codegen/generators/definitions/enums.test.ts +0 -61
  24. package/src/codegen/generators/definitions/enums.ts +0 -68
  25. package/src/codegen/generators/definitions/index.ts +0 -11
  26. package/src/codegen/generators/definitions/schema.test.ts +0 -236
  27. package/src/codegen/generators/index.ts +0 -6
  28. package/src/codegen/generators/indexFile/index.ts +0 -63
  29. package/src/codegen/generators/indexFile/indexFile.test.ts +0 -72
  30. package/src/codegen/generators/persistedQueries/index.ts +0 -55
  31. package/src/codegen/generators/persistedQueries/persistedQuery.test.ts +0 -26
  32. package/src/codegen/generators/runtime/index.test.ts +0 -74
  33. package/src/codegen/generators/runtime/index.ts +0 -64
  34. package/src/codegen/generators/runtime/runtime.test.ts +0 -25
  35. package/src/codegen/generators/typescript/addReferencedInputTypes.ts +0 -77
  36. package/src/codegen/generators/typescript/index.ts +0 -412
  37. package/src/codegen/generators/typescript/inlineType.ts +0 -409
  38. package/src/codegen/generators/typescript/typeReference.ts +0 -44
  39. package/src/codegen/generators/typescript/types.ts +0 -81
  40. package/src/codegen/generators/typescript/typescript.test.ts +0 -1434
  41. package/src/codegen/index.ts +0 -406
  42. package/src/codegen/transforms/addID.test.ts +0 -93
  43. package/src/codegen/transforms/addID.ts +0 -86
  44. package/src/codegen/transforms/composeQueries.test.ts +0 -50
  45. package/src/codegen/transforms/composeQueries.ts +0 -154
  46. package/src/codegen/transforms/fragmentVariables.test.ts +0 -636
  47. package/src/codegen/transforms/fragmentVariables.ts +0 -417
  48. package/src/codegen/transforms/index.ts +0 -7
  49. package/src/codegen/transforms/list.ts +0 -484
  50. package/src/codegen/transforms/lists.test.ts +0 -530
  51. package/src/codegen/transforms/paginate.test.ts +0 -1528
  52. package/src/codegen/transforms/paginate.ts +0 -770
  53. package/src/codegen/transforms/schema.test.ts +0 -136
  54. package/src/codegen/transforms/schema.ts +0 -109
  55. package/src/codegen/transforms/typename.test.ts +0 -125
  56. package/src/codegen/transforms/typename.ts +0 -55
  57. package/src/codegen/utils/commonjs.ts +0 -26
  58. package/src/codegen/utils/flattenSelections.ts +0 -179
  59. package/src/codegen/utils/graphql.test.ts +0 -35
  60. package/src/codegen/utils/graphql.ts +0 -79
  61. package/src/codegen/utils/index.ts +0 -5
  62. package/src/codegen/utils/moduleExport.ts +0 -27
  63. package/src/codegen/utils/murmur.ts +0 -79
  64. package/src/codegen/validators/index.ts +0 -4
  65. package/src/codegen/validators/noIDAlias.test.ts +0 -71
  66. package/src/codegen/validators/noIDAlias.ts +0 -39
  67. package/src/codegen/validators/plugins.ts +0 -25
  68. package/src/codegen/validators/typeCheck.test.ts +0 -960
  69. package/src/codegen/validators/typeCheck.ts +0 -1086
  70. package/src/codegen/validators/uniqueNames.test.ts +0 -59
  71. package/src/codegen/validators/uniqueNames.ts +0 -39
  72. package/src/lib/cleanupFiles.ts +0 -20
  73. package/src/lib/config.test.ts +0 -13
  74. package/src/lib/config.ts +0 -954
  75. package/src/lib/constants.ts +0 -11
  76. package/src/lib/error.ts +0 -24
  77. package/src/lib/fs.ts +0 -285
  78. package/src/lib/graphql.test.ts +0 -211
  79. package/src/lib/graphql.ts +0 -200
  80. package/src/lib/imports.ts +0 -82
  81. package/src/lib/index.ts +0 -17
  82. package/src/lib/introspection.ts +0 -39
  83. package/src/lib/parse.test.ts +0 -75
  84. package/src/lib/parse.ts +0 -23
  85. package/src/lib/path.ts +0 -49
  86. package/src/lib/pipeline.ts +0 -17
  87. package/src/lib/types.ts +0 -34
  88. package/src/lib/walk.ts +0 -104
  89. package/src/runtime/cache/cache.ts +0 -1026
  90. package/src/runtime/cache/gc.ts +0 -56
  91. package/src/runtime/cache/index.ts +0 -3
  92. package/src/runtime/cache/lists.ts +0 -516
  93. package/src/runtime/cache/storage.ts +0 -574
  94. package/src/runtime/cache/stuff.ts +0 -77
  95. package/src/runtime/cache/subscription.ts +0 -329
  96. package/src/runtime/cache/tests/availability.test.ts +0 -408
  97. package/src/runtime/cache/tests/gc.test.ts +0 -319
  98. package/src/runtime/cache/tests/keys.test.ts +0 -36
  99. package/src/runtime/cache/tests/list.test.ts +0 -3854
  100. package/src/runtime/cache/tests/readwrite.test.ts +0 -1201
  101. package/src/runtime/cache/tests/scalars.test.ts +0 -218
  102. package/src/runtime/cache/tests/storage.test.ts +0 -426
  103. package/src/runtime/cache/tests/subscriptions.test.ts +0 -1757
  104. package/src/runtime/index.ts +0 -29
  105. package/src/runtime/lib/config.ts +0 -211
  106. package/src/runtime/lib/constants.ts +0 -17
  107. package/src/runtime/lib/deepEquals.ts +0 -32
  108. package/src/runtime/lib/errors.ts +0 -8
  109. package/src/runtime/lib/index.ts +0 -8
  110. package/src/runtime/lib/log.ts +0 -69
  111. package/src/runtime/lib/network.ts +0 -303
  112. package/src/runtime/lib/networkUtils.ts +0 -151
  113. package/src/runtime/lib/scalars.test.ts +0 -877
  114. package/src/runtime/lib/scalars.ts +0 -195
  115. package/src/runtime/lib/types.ts +0 -195
  116. package/src/test/index.ts +0 -294
  117. package/src/vite/ast.ts +0 -107
  118. package/src/vite/houdini.ts +0 -113
  119. package/src/vite/imports.ts +0 -129
  120. package/src/vite/index.ts +0 -55
  121. package/src/vite/schema.ts +0 -80
@@ -1,108 +0,0 @@
1
- import type { ExpressionKind } from 'ast-types/gen/kinds'
2
- import * as graphql from 'graphql'
3
- import * as recast from 'recast'
4
-
5
- import { HoudiniError } from '../../../lib'
6
-
7
- const AST = recast.types.builders
8
-
9
- export function serializeValue(value: any): ExpressionKind {
10
- // if we are serializing a list
11
- if (Array.isArray(value)) {
12
- // return an array expression with every element serialize
13
- return AST.arrayExpression(value.map(serializeValue))
14
- }
15
-
16
- // if we are serializing an object
17
- if (typeof value === 'object' && value !== null) {
18
- return AST.objectExpression(
19
- Object.entries(value)
20
- .filter(([, value]) => typeof value !== 'undefined')
21
- .map(([key, value]) =>
22
- AST.objectProperty(AST.identifier(key), serializeValue(value))
23
- )
24
- )
25
- }
26
-
27
- // if we are serializing a string
28
- if (typeof value === 'string') {
29
- // if there are new lines, use a template. otherwise, just use a string
30
- if (value.indexOf('\n') !== -1) {
31
- return AST.templateLiteral(
32
- [AST.templateElement({ raw: value, cooked: value }, true)],
33
- []
34
- )
35
- }
36
- return AST.stringLiteral(value)
37
- }
38
-
39
- // anything else can just use its literal value
40
- return AST.literal(value)
41
- }
42
-
43
- export function deepMerge(filepath: string, ...targets: {}[]): {} {
44
- // look at the first target to know what type we're merging
45
-
46
- // if we aren't looking at an object
47
- if (typeof targets[0] !== 'object') {
48
- // make sure all of the values are the same
49
- const matches = targets.filter((val) => val !== targets[0]).length === 0
50
- if (!matches) {
51
- throw new HoudiniError({ filepath, message: 'could not merge: ' + targets })
52
- }
53
-
54
- // return the matching value
55
- return targets[0]
56
- }
57
-
58
- // if we are looking at a list of lists
59
- if (Array.isArray(targets[0])) {
60
- return (targets[0] as {}[]).concat(...targets.slice(1))
61
- }
62
-
63
- // collect all of the fields that the targets specify and map them to their value
64
- const fields: Record<string, any[]> = {}
65
-
66
- for (const target of targets) {
67
- // add every field of the target to the bag
68
- for (const [key, value] of Object.entries(target)) {
69
- // if we haven't seen the key before
70
- if (!fields[key]) {
71
- // save it as a list
72
- fields[key] = []
73
- }
74
-
75
- fields[key].push(value)
76
- }
77
- }
78
-
79
- return Object.fromEntries(
80
- Object.entries(fields).map(([key, value]) => [key, deepMerge(filepath, ...value)])
81
- )
82
- }
83
-
84
- export function convertValue(val: graphql.ValueNode) {
85
- // figure out the value to use
86
- let value
87
- let kind
88
-
89
- // the value of the arg is always going to be a
90
- if (val.kind === graphql.Kind.INT) {
91
- value = parseInt(val.value, 10)
92
- kind = 'Int'
93
- } else if (val.kind === graphql.Kind.FLOAT) {
94
- value = parseFloat(val.value)
95
- kind = 'Float'
96
- } else if (val.kind === graphql.Kind.BOOLEAN) {
97
- value = val.value
98
- kind = 'Boolean'
99
- } else if (val.kind === graphql.Kind.VARIABLE) {
100
- value = val.name.value
101
- kind = 'Variable'
102
- } else if (val.kind === graphql.Kind.STRING) {
103
- value = val.value
104
- kind = 'String'
105
- }
106
-
107
- return { kind, value }
108
- }
@@ -1,61 +0,0 @@
1
- import type { ProgramKind } from 'ast-types/gen/kinds'
2
- import * as recast from 'recast'
3
- import * as typeScriptParser from 'recast/parsers/typescript'
4
- import { test, expect } from 'vitest'
5
-
6
- import { runPipeline } from '../..'
7
- import { fs, CollectedGraphQLDocument, path } from '../../../lib'
8
- import { mockCollectedDoc, testConfig } from '../../../test'
9
-
10
- // the config to use in tests
11
- const config = testConfig()
12
-
13
- // the documents to test
14
- const docs: CollectedGraphQLDocument[] = [
15
- mockCollectedDoc(`query TestQuery { version }`),
16
- mockCollectedDoc(`fragment TestFragment on User { firstName }`),
17
- ]
18
-
19
- test('generates runtime definitions for each enum', async function () {
20
- // execute the generator
21
- await runPipeline(config, [])
22
-
23
- // load the contents of the type definitions file
24
- let fileContents = await fs.readFile(path.join(config.enumTypesDefinitionsPath))
25
- expect(fileContents).toBeTruthy()
26
- let parsedQuery: ProgramKind = recast.parse(fileContents!.toString(), {
27
- parser: typeScriptParser,
28
- }).program
29
-
30
- expect(parsedQuery).toMatchInlineSnapshot(`
31
- export declare enum TestEnum1 {
32
- Value1 = "Value1",
33
- Value2 = "Value2"
34
- }
35
-
36
- export declare enum TestEnum2 {
37
- Value3 = "Value3",
38
- Value2 = "Value2"
39
- }
40
- `)
41
-
42
- // load the contents of the type definitions file
43
- fileContents = await fs.readFile(path.join(config.enumRuntimeDefinitionsPath))
44
-
45
- expect(fileContents).toBeTruthy()
46
- parsedQuery = recast.parse(fileContents!.toString(), {
47
- parser: typeScriptParser,
48
- }).program
49
-
50
- expect(parsedQuery).toMatchInlineSnapshot(`
51
- export const TestEnum1 = {
52
- "Value1": "Value1",
53
- "Value2": "Value2"
54
- };
55
-
56
- export const TestEnum2 = {
57
- "Value3": "Value3",
58
- "Value2": "Value2"
59
- };
60
- `)
61
- })
@@ -1,68 +0,0 @@
1
- import * as graphql from 'graphql'
2
- import * as recast from 'recast'
3
-
4
- import { Config, fs, path } from '../../../lib'
5
- import { moduleExport } from '../../utils'
6
-
7
- const AST = recast.types.builders
8
-
9
- // the enum generator creates runtime definitions and centralizes the type definitions in a
10
- // single place to avoid conflicting exported types
11
- export default async function definitionsGenerator(config: Config) {
12
- // grab every enum definition in the project's schema
13
- const enums = (
14
- graphql
15
- .parse(graphql.printSchema(config.schema))
16
- .definitions.filter(
17
- (definition) => definition.kind === 'EnumTypeDefinition'
18
- ) as graphql.EnumTypeDefinitionNode[]
19
- ).filter((def) => !config.isInternalEnum(def))
20
-
21
- // generate the runtime definitions
22
- const runtimeDefinitions = recast.print(
23
- AST.program(
24
- enums.map((defn) => {
25
- const name = defn.name.value
26
-
27
- return moduleExport(
28
- config,
29
- name,
30
- AST.objectExpression(
31
- defn.values?.map((value) => {
32
- const str = value.name.value
33
- return AST.objectProperty(
34
- AST.stringLiteral(str),
35
- AST.stringLiteral(str)
36
- )
37
- }) || []
38
- )
39
- )
40
- })
41
- )
42
- ).code
43
-
44
- // generate the type definitions
45
- const typeDefinitions = enums
46
- .sort((a, b) => a.name.value.localeCompare(b.name.value))
47
- .map(
48
- (definition) => `
49
- export declare enum ${definition.name.value} {
50
- ${definition.values?.map((value) => ` ${value.name.value} = "${value.name.value}"`).join(',\n')}
51
- }
52
- `
53
- )
54
- .join('')
55
-
56
- // the index file for the definitions directory
57
- const definitionsIndex = `
58
- export * from './enums.js'
59
- `
60
-
61
- // write the typedefinition to disk
62
- await Promise.all([
63
- fs.writeFile(config.enumTypesDefinitionsPath, typeDefinitions),
64
- fs.writeFile(config.enumRuntimeDefinitionsPath, runtimeDefinitions),
65
- fs.writeFile(path.join(config.definitionsDirectory, 'index.js'), definitionsIndex),
66
- fs.writeFile(path.join(config.definitionsDirectory, 'index.d.ts'), definitionsIndex),
67
- ])
68
- }
@@ -1,11 +0,0 @@
1
- import { Config, fs } from '../../../lib'
2
- import enums from './enums'
3
-
4
- // schemaGenerator updates the schema file to contain all of the generated
5
- export default async function schemaGenerator(config: Config) {
6
- await Promise.all([
7
- fs.writeFile(config.definitionsSchemaPath, config.newSchema),
8
- fs.writeFile(config.definitionsDocumentsPath, config.newDocuments),
9
- enums(config),
10
- ])
11
- }
@@ -1,236 +0,0 @@
1
- // external
2
- import * as graphql from 'graphql'
3
- import { test, expect } from 'vitest'
4
-
5
- import { runPipeline } from '../..'
6
- import { CollectedGraphQLDocument, fs } from '../../../lib'
7
- import { mockCollectedDoc, testConfig } from '../../../test'
8
-
9
- const config = testConfig()
10
-
11
- test('adds internal documents to schema', async function () {
12
- const docs: CollectedGraphQLDocument[] = [
13
- mockCollectedDoc(`query TestQuery { version }`),
14
- mockCollectedDoc(`fragment TestFragment on User { firstName }`),
15
- ]
16
-
17
- // execute the generator
18
- await runPipeline(config, docs)
19
-
20
- // read the schema file and make sure it got the internal documents
21
- expect(graphql.parse((await fs.readFile(config.definitionsSchemaPath))!))
22
- .toMatchInlineSnapshot(`
23
- enum CachePolicy {
24
- CacheAndNetwork
25
- CacheOnly
26
- CacheOrNetwork
27
- NetworkOnly
28
- }
29
-
30
- """
31
- @list is used to mark a field for the runtime as a place to add or remove
32
- entities in mutations
33
- """
34
- directive @list(name: String!, connection: Boolean) on FIELD
35
-
36
- """
37
- @paginate is used to to mark a field for pagination.
38
- More info in the [doc](https://houdinigraphql.com/guides/pagination).
39
- """
40
- directive @paginate(name: String) on FIELD
41
-
42
- """@prepend is used to tell the runtime to add the result to the end of the list"""
43
- directive @prepend(parentID: ID) on FRAGMENT_SPREAD
44
-
45
- """@append is used to tell the runtime to add the result to the start of the list"""
46
- directive @append(parentID: ID) on FRAGMENT_SPREAD
47
-
48
- """@allLists is used to tell the runtime to add the result to all list"""
49
- directive @allLists on FRAGMENT_SPREAD
50
-
51
- """
52
- @parentID is used to provide a parentID without specifying position or in situations
53
- where it doesn't make sense (eg when deleting a node.)
54
- """
55
- directive @parentID(value: ID!) on FRAGMENT_SPREAD
56
-
57
- """@when is used to provide a conditional or in situations where it doesn't make sense (eg when removing or deleting a node.)"""
58
- directive @when on FRAGMENT_SPREAD
59
-
60
- """@when_not is used to provide a conditional or in situations where it doesn't make sense (eg when removing or deleting a node.)"""
61
- directive @when_not on FRAGMENT_SPREAD
62
-
63
- """@arguments is used to define the arguments of a fragment"""
64
- directive @arguments on FRAGMENT_DEFINITION
65
-
66
- """@cache is used to specify cache rules for a query"""
67
- directive @cache(policy: CachePolicy, partial: Boolean) on QUERY
68
-
69
- """@houdini is used to configure houdini's internal behavior"""
70
- directive @houdini(
71
- """Opt-in to an automatic load function (only valid when used at queries)"""
72
- load: Boolean! = true
73
- """Mask fragment fields (only valid when used at a fragment spread)"""
74
- mask: Boolean! = true
75
- ) on QUERY | FRAGMENT_SPREAD
76
- `)
77
- })
78
-
79
- test('list operations are included', async function () {
80
- const docs: CollectedGraphQLDocument[] = [
81
- mockCollectedDoc(
82
- `query TestQuery { usersByCursor @list(name: "Friends") { edges { node { id } } } }`
83
- ),
84
- mockCollectedDoc(`fragment TestFragment on User { firstName }`),
85
- ]
86
-
87
- // execute the generator
88
- await runPipeline(config, docs)
89
-
90
- // read the schema file
91
- expect(graphql.parse((await fs.readFile(config.definitionsSchemaPath))!))
92
- .toMatchInlineSnapshot(`
93
- enum CachePolicy {
94
- CacheAndNetwork
95
- CacheOnly
96
- CacheOrNetwork
97
- NetworkOnly
98
- }
99
-
100
- """
101
- @list is used to mark a field for the runtime as a place to add or remove
102
- entities in mutations
103
- """
104
- directive @list(name: String!, connection: Boolean) on FIELD
105
-
106
- """
107
- @paginate is used to to mark a field for pagination.
108
- More info in the [doc](https://houdinigraphql.com/guides/pagination).
109
- """
110
- directive @paginate(name: String) on FIELD
111
-
112
- """@prepend is used to tell the runtime to add the result to the end of the list"""
113
- directive @prepend(parentID: ID) on FRAGMENT_SPREAD
114
-
115
- """@append is used to tell the runtime to add the result to the start of the list"""
116
- directive @append(parentID: ID) on FRAGMENT_SPREAD
117
-
118
- """@allLists is used to tell the runtime to add the result to all list"""
119
- directive @allLists on FRAGMENT_SPREAD
120
-
121
- """
122
- @parentID is used to provide a parentID without specifying position or in situations
123
- where it doesn't make sense (eg when deleting a node.)
124
- """
125
- directive @parentID(value: ID!) on FRAGMENT_SPREAD
126
-
127
- """@when is used to provide a conditional or in situations where it doesn't make sense (eg when removing or deleting a node.)"""
128
- directive @when on FRAGMENT_SPREAD
129
-
130
- """@when_not is used to provide a conditional or in situations where it doesn't make sense (eg when removing or deleting a node.)"""
131
- directive @when_not on FRAGMENT_SPREAD
132
-
133
- """@arguments is used to define the arguments of a fragment"""
134
- directive @arguments on FRAGMENT_DEFINITION
135
-
136
- """@cache is used to specify cache rules for a query"""
137
- directive @cache(policy: CachePolicy, partial: Boolean) on QUERY
138
-
139
- """@houdini is used to configure houdini's internal behavior"""
140
- directive @houdini(
141
- """Opt-in to an automatic load function (only valid when used at queries)"""
142
- load: Boolean! = true
143
- """Mask fragment fields (only valid when used at a fragment spread)"""
144
- mask: Boolean! = true
145
- ) on QUERY | FRAGMENT_SPREAD
146
-
147
- directive @User_delete repeatable on FIELD
148
- `)
149
-
150
- // read the documents file
151
- expect(graphql.parse((await fs.readFile(config.definitionsDocumentsPath))!))
152
- .toMatchInlineSnapshot(`
153
- fragment Friends_insert on User {
154
- id
155
- }
156
-
157
- fragment Friends_toggle on User {
158
- id
159
- id
160
- }
161
-
162
- fragment Friends_remove on User {
163
- id
164
- }
165
-
166
- `)
167
- })
168
-
169
- test("writing twice doesn't duplicate definitions", async function () {
170
- const docs: CollectedGraphQLDocument[] = [
171
- mockCollectedDoc(`query TestQuery { version }`),
172
- mockCollectedDoc(`fragment TestFragment on User { firstName }`),
173
- ]
174
-
175
- // execute the generator twice
176
- await runPipeline(config, docs)
177
- await runPipeline(config, docs)
178
-
179
- // read the schema file and make sure it got the internal documents
180
- expect(graphql.parse((await fs.readFile(config.definitionsSchemaPath))!))
181
- .toMatchInlineSnapshot(`
182
- enum CachePolicy {
183
- CacheAndNetwork
184
- CacheOnly
185
- CacheOrNetwork
186
- NetworkOnly
187
- }
188
-
189
- """
190
- @list is used to mark a field for the runtime as a place to add or remove
191
- entities in mutations
192
- """
193
- directive @list(name: String!, connection: Boolean) on FIELD
194
-
195
- """
196
- @paginate is used to to mark a field for pagination.
197
- More info in the [doc](https://houdinigraphql.com/guides/pagination).
198
- """
199
- directive @paginate(name: String) on FIELD
200
-
201
- """@prepend is used to tell the runtime to add the result to the end of the list"""
202
- directive @prepend(parentID: ID) on FRAGMENT_SPREAD
203
-
204
- """@append is used to tell the runtime to add the result to the start of the list"""
205
- directive @append(parentID: ID) on FRAGMENT_SPREAD
206
-
207
- """@allLists is used to tell the runtime to add the result to all list"""
208
- directive @allLists on FRAGMENT_SPREAD
209
-
210
- """
211
- @parentID is used to provide a parentID without specifying position or in situations
212
- where it doesn't make sense (eg when deleting a node.)
213
- """
214
- directive @parentID(value: ID!) on FRAGMENT_SPREAD
215
-
216
- """@when is used to provide a conditional or in situations where it doesn't make sense (eg when removing or deleting a node.)"""
217
- directive @when on FRAGMENT_SPREAD
218
-
219
- """@when_not is used to provide a conditional or in situations where it doesn't make sense (eg when removing or deleting a node.)"""
220
- directive @when_not on FRAGMENT_SPREAD
221
-
222
- """@arguments is used to define the arguments of a fragment"""
223
- directive @arguments on FRAGMENT_DEFINITION
224
-
225
- """@cache is used to specify cache rules for a query"""
226
- directive @cache(policy: CachePolicy, partial: Boolean) on QUERY
227
-
228
- """@houdini is used to configure houdini's internal behavior"""
229
- directive @houdini(
230
- """Opt-in to an automatic load function (only valid when used at queries)"""
231
- load: Boolean! = true
232
- """Mask fragment fields (only valid when used at a fragment spread)"""
233
- mask: Boolean! = true
234
- ) on QUERY | FRAGMENT_SPREAD
235
- `)
236
- })
@@ -1,6 +0,0 @@
1
- export { default as artifacts } from './artifacts'
2
- export { default as runtime } from './runtime'
3
- export { default as typescript } from './typescript'
4
- export { default as persistOutput } from './persistedQueries'
5
- export { default as definitions } from './definitions'
6
- export { default as indexFile } from './indexFile'
@@ -1,63 +0,0 @@
1
- // locals
2
- import { Config, CollectedGraphQLDocument, fs, path } from '../../../lib'
3
- import { cjsIndexFilePreamble, exportStarFrom, exportDefaultFrom } from '../../utils'
4
-
5
- // every document in the application should be re-exported from the root. this allows the user to balance
6
- // code-splitting concerns with the "cleanliness" of importing from a single location
7
- export default async function writeIndexFile(config: Config, docs: CollectedGraphQLDocument[]) {
8
- const relative = (target: string) => './' + path.relative(config.rootDir, target)
9
-
10
- // the directories we want to export
11
- const runtimeDir = relative(config.runtimeDirectory)
12
- const artifactDir = relative(config.artifactDirectory)
13
- const definitionsDir = relative(config.definitionsDirectory)
14
-
15
- // if we are rendering an index file for sapper we need to compile it for commonjs
16
- const cjs = config.module === 'commonjs'
17
- let body = cjs ? cjsIndexFilePreamble : ''
18
-
19
- // create the export functions
20
- const export_star_from = ({ module }: { module: string }) =>
21
- '\n' + (cjs ? exportStarFrom(module) : `export * from "${module}"`) + '\n'
22
- const export_default_as = ({ module, as }: { module: string; as: string }) =>
23
- '\n' +
24
- (cjs ? exportDefaultFrom(module, as) : `export { default as ${as} } from "${module}"`) +
25
- '\n'
26
-
27
- // add the standard exports
28
- body += [
29
- export_star_from({ module: runtimeDir }),
30
- export_star_from({ module: artifactDir }),
31
- export_star_from({ module: definitionsDir }),
32
- ].join('')
33
-
34
- // plugins can influence the index file
35
- for (const plugin of config.plugins) {
36
- // if they need to add stuff directly (from directories that were generated)
37
- if (plugin.index_file) {
38
- body = plugin.index_file({
39
- config,
40
- content: body,
41
- export_default_as,
42
- export_star_from,
43
- plugin_root: config.pluginDirectory(plugin.name),
44
- typedef: false,
45
- documents: docs,
46
- })
47
- }
48
-
49
- // if the plugin generated a runtime
50
- if (plugin.include_runtime) {
51
- body += export_star_from({
52
- module: relative(config.pluginRuntimeDirectory(plugin.name)),
53
- })
54
- }
55
-
56
- if (!plugin.index_file) {
57
- continue
58
- }
59
- }
60
-
61
- // write the index file that exports the runtime
62
- await fs.writeFile(path.join(config.rootDir, 'index.js'), body)
63
- }
@@ -1,72 +0,0 @@
1
- import type { ProgramKind } from 'ast-types/gen/kinds'
2
- import * as recast from 'recast'
3
- import * as typeScriptParser from 'recast/parsers/typescript'
4
- import { test, expect } from 'vitest'
5
-
6
- import { runPipeline } from '../..'
7
- import { fs, CollectedGraphQLDocument, path } from '../../../lib'
8
- import { mockCollectedDoc, testConfig } from '../../../test'
9
-
10
- // the config to use in tests
11
- const config = testConfig()
12
-
13
- // the documents to test
14
- const docs: CollectedGraphQLDocument[] = [
15
- mockCollectedDoc(`query TestQuery { version }`),
16
- mockCollectedDoc(`fragment TestFragment on User { firstName }`),
17
- ]
18
-
19
- test('index file - esm', async function () {
20
- const config = testConfig({ module: 'esm' })
21
-
22
- // execute the generator
23
- await runPipeline(config, docs)
24
-
25
- // open up the index file
26
- const queryContents = await fs.readFile(path.join(config.artifactDirectory, 'index.js'))
27
- expect(queryContents).toBeTruthy()
28
- // parse the contents
29
- const parsedQuery: ProgramKind = recast.parse(queryContents!, {
30
- parser: typeScriptParser,
31
- }).program
32
- // verify contents
33
- expect(parsedQuery).toMatchInlineSnapshot(`
34
- export { default as TestFragment} from './TestFragment'
35
- export { default as TestQuery} from './TestQuery'
36
- `)
37
- })
38
-
39
- test('index file - commonjs', async function () {
40
- // execute the generator
41
- await runPipeline(testConfig({ module: 'commonjs' }), docs)
42
-
43
- // open up the index file
44
- const queryContents = await fs.readFile(path.join(config.artifactDirectory, 'index.js'))
45
- expect(queryContents).toBeTruthy()
46
- // parse the contents
47
- const parsedQuery: ProgramKind = recast.parse(queryContents!, {
48
- parser: typeScriptParser,
49
- }).program
50
- // verify contents
51
- expect(parsedQuery).toMatchInlineSnapshot(`
52
- "use strict";
53
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
54
- if (k2 === undefined) k2 = k;
55
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
56
- }) : (function(o, m, k, k2) {
57
- if (k2 === undefined) k2 = k;
58
- o[k2] = m[k];
59
- }));
60
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
61
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
62
- };
63
- var __importDefault = (this && this.__importDefault) || function (mod) {
64
- return (mod && mod.__esModule) ? mod : { "default": mod };
65
- };
66
- Object.defineProperty(exports, "__esModule", { value: true });
67
- var TestFragment = require("./TestFragment");
68
- Object.defineProperty(exports, "TestFragment", { enumerable: true, get: function () { return __importDefault(TestFragment).default; } });
69
- var TestQuery = require("./TestQuery");
70
- Object.defineProperty(exports, "TestQuery", { enumerable: true, get: function () { return __importDefault(TestQuery).default; } });
71
- `)
72
- })
@@ -1,55 +0,0 @@
1
- //externals
2
- import * as graphql from 'graphql'
3
-
4
- // internals
5
- import { Config, hashDocument, fs, CollectedGraphQLDocument } from '../../../lib'
6
-
7
- // the persist output generator is responsible for generating a queryMap.json
8
- // to the provided path with the `hash` as key and the raw query as value.
9
- export default async function persistOutputGenerator(
10
- config: Config,
11
- docs: CollectedGraphQLDocument[]
12
- ) {
13
- if (typeof config.persistedQueryPath !== 'string' || config.persistedQueryPath.length === 0)
14
- return
15
-
16
- if (!config.persistedQueryPath.endsWith('.json')) {
17
- console.log('Can only write the queryMap to a json file')
18
- return
19
- }
20
-
21
- const queryMap = docs.reduce<Record<string, string>>((acc, { document, generateArtifact }) => {
22
- // if the document is generated, just return early since there is no operation
23
- if (!generateArtifact) {
24
- return acc
25
- }
26
-
27
- // Strip all references to internal directives
28
- let rawString = graphql.print(
29
- graphql.visit(document, {
30
- Directive(node) {
31
- // if the directive is one of the internal ones, remove it
32
- if (config.isInternalDirective(node)) {
33
- return null
34
- }
35
- },
36
- })
37
- )
38
-
39
- const operations = document.definitions.filter(
40
- ({ kind }) => kind === graphql.Kind.OPERATION_DEFINITION
41
- ) as graphql.OperationDefinitionNode[]
42
-
43
- // if there are operations in the document
44
- if (operations.length > 0 && operations[0].kind === 'OperationDefinition') {
45
- acc[hashDocument(rawString)] = rawString
46
- }
47
-
48
- return acc
49
- }, {})
50
-
51
- if (Object.keys(queryMap).length === 0) return
52
-
53
- // Write the queryMap to the provided path
54
- await fs.writeFile(config.persistedQueryPath, JSON.stringify(queryMap, null, 4))
55
- }