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,26 +0,0 @@
1
- import { test, expect } from 'vitest'
2
-
3
- import { runPipeline } from '../../../codegen'
4
- import { CollectedGraphQLDocument, fs, path } from '../../../lib'
5
- import { mockCollectedDoc, testConfig } from '../../../test'
6
-
7
- test('generates an artifact for every document', async function () {
8
- const config = testConfig()
9
- config.persistedQueryPath = path.join(config.rootDir, 'hash.json')
10
-
11
- // the documents to test
12
- const docs: CollectedGraphQLDocument[] = [
13
- mockCollectedDoc(`query TestQuery1 { version }`),
14
- mockCollectedDoc(`query TestQuery2 { user { ...TestFragment } }`),
15
- mockCollectedDoc(`fragment TestFragment on User { firstName }`),
16
- ]
17
- // execute the generator
18
- await runPipeline(config, docs)
19
-
20
- expect(JSON.parse((await fs.readFile(config.persistedQueryPath))!)).toMatchInlineSnapshot(`
21
- {
22
- "361432f464ed44eed788f3ea66c4dabc46437b88edbe7daccca87045fd31447f": "query TestQuery1 {\\n version\\n}\\n",
23
- "17f12389123502b3d5d81202d0af249bdf0ec95cea480c9c12501ef627abd463": "query TestQuery2 {\\n user {\\n ...TestFragment\\n id\\n }\\n}\\n\\nfragment TestFragment on User {\\n firstName\\n}\\n"
24
- }
25
- `)
26
- })
@@ -1,74 +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, path } from '../../../lib'
8
- import { CollectedGraphQLDocument } from '../../../lib/types'
9
- import { testConfig, mockCollectedDoc } from '../../../test'
10
-
11
- // the documents to test
12
- const docs: CollectedGraphQLDocument[] = [
13
- mockCollectedDoc(`query TestQuery { version }`),
14
- mockCollectedDoc(`fragment TestFragment on User { firstName }`),
15
- ]
16
-
17
- test('runtime index file - sapper', async function () {
18
- const config = testConfig({ module: 'commonjs' })
19
- // execute the generator
20
- await runPipeline(config, docs)
21
-
22
- // open up the index file
23
- const queryContents = await fs.readFile(path.join(config.rootDir, 'index.js'))
24
- expect(queryContents).toBeTruthy()
25
- // parse the contents
26
- const parsedQuery: ProgramKind = recast.parse(queryContents!, {
27
- parser: typeScriptParser,
28
- }).program
29
- // verify contents
30
- expect(parsedQuery).toMatchInlineSnapshot(`
31
- "use strict";
32
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
33
- if (k2 === undefined) k2 = k;
34
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
35
- }) : (function(o, m, k, k2) {
36
- if (k2 === undefined) k2 = k;
37
- o[k2] = m[k];
38
- }));
39
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
40
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
41
- };
42
- var __importDefault = (this && this.__importDefault) || function (mod) {
43
- return (mod && mod.__esModule) ? mod : { "default": mod };
44
- };
45
- Object.defineProperty(exports, "__esModule", { value: true });
46
- __exportStar(require("./runtime"), exports);
47
-
48
- __exportStar(require("./artifacts"), exports);
49
-
50
- __exportStar(require("./graphql"), exports);
51
- `)
52
- })
53
-
54
- test('runtime index file - kit', async function () {
55
- const config = testConfig({ module: 'esm', framework: 'kit' })
56
- // execute the generator
57
- await runPipeline(config, docs)
58
-
59
- // open up the index file
60
- const queryContents = await fs.readFile(path.join(config.rootDir, 'index.js'))
61
- expect(queryContents).toBeTruthy()
62
- // parse the contents
63
- const parsedQuery: ProgramKind = recast.parse(queryContents!, {
64
- parser: typeScriptParser,
65
- }).program
66
- // verify contents
67
- expect(parsedQuery).toMatchInlineSnapshot(`
68
- export * from "./runtime"
69
-
70
- export * from "./artifacts"
71
-
72
- export * from "./graphql"
73
- `)
74
- })
@@ -1,64 +0,0 @@
1
- import { Config, siteURL as SITE_URL, fs, HoudiniError, path, houdini_mode } from '../../../lib'
2
-
3
- export default async function runtimeGenerator(config: Config) {
4
- // generate the adapter to normalize interactions with the framework
5
- // update the generated runtime to point to the client
6
- await Promise.all([
7
- fs.recursiveCopy(config.runtimeSource, config.runtimeDirectory, {
8
- // transform the files while we are copying so we don't trigger unnecessary changes
9
- [path.join(config.runtimeSource, 'lib', 'config.js')]: (content) => {
10
- // the path to the config file
11
- const configFilePath = path.join(config.runtimeDirectory, 'lib', 'config.js')
12
- // the relative path
13
- const relativePath = path.relative(path.dirname(configFilePath), config.filepath)
14
-
15
- return content.replace('HOUDINI_CONFIG_PATH', relativePath)
16
- },
17
- [path.join(config.runtimeSource, 'lib', 'constants.js')]: (content) => {
18
- return content.replace('SITE_URL', SITE_URL)
19
- },
20
- }),
21
- ...config.plugins
22
- .filter((plugin) => plugin.include_runtime)
23
- .map((plugin) => generatePluginRuntime(config, plugin)),
24
- ])
25
- }
26
-
27
- async function generatePluginRuntime(config: Config, plugin: Config['plugins'][number]) {
28
- if (houdini_mode.is_testing) {
29
- return
30
- }
31
-
32
- // a plugin with a generated runtime has something at <dir>/build/runtime-{esm,cjs}
33
-
34
- // find the location of the plugin
35
- const source = path.join(
36
- plugin.directory,
37
- 'build',
38
- 'runtime-' + (config.module === 'esm' ? 'esm' : 'cjs')
39
- )
40
- try {
41
- await fs.stat(source)
42
- } catch {
43
- throw new HoudiniError({
44
- message: name + ' does not have a runtime to generate',
45
- description: 'please use the houdini-scripts command to bundle your plugin',
46
- })
47
- }
48
-
49
- const which = config.module === 'esm' ? 'esm' : 'cjs'
50
-
51
- // copy the runtime
52
- const pluginDir = config.pluginRuntimeDirectory(plugin.name)
53
- await fs.mkdirp(pluginDir)
54
- await fs.recursiveCopy(
55
- source,
56
- pluginDir,
57
- Object.fromEntries(
58
- Object.entries(plugin.transform_runtime ?? {}).map(([key, value]) => [
59
- path.join(plugin.directory, 'build', `runtime-${which}`, key),
60
- (content) => value({ config, content }),
61
- ])
62
- )
63
- )
64
- }
@@ -1,25 +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, path } from '../../../lib'
8
- import { testConfig } from '../../../test'
9
-
10
- test('updates the config file with import path', async function () {
11
- const config = testConfig({ module: 'esm' })
12
- // execute the generator
13
- await runPipeline(config, [])
14
-
15
- // open up the index file
16
- const fileContents = await fs.readFile(path.join(config.runtimeDirectory, 'lib', 'config.js'))
17
- expect(fileContents).toBeTruthy()
18
-
19
- // parse the contents
20
- const parsedQuery: ProgramKind = recast.parse(fileContents!, {
21
- parser: typeScriptParser,
22
- }).program
23
- // verify contents
24
- expect(recast.print(parsedQuery).code).toContain('import("../../../config.cjs")')
25
- })
@@ -1,77 +0,0 @@
1
- import type { StatementKind, TSPropertySignatureKind } 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 { unwrapType } from '../../utils'
7
- import { tsTypeReference } from './typeReference'
8
-
9
- const AST = recast.types.builders
10
-
11
- // add any object types found in the input
12
- export function addReferencedInputTypes(
13
- config: Config,
14
- filepath: string,
15
- body: StatementKind[],
16
- visitedTypes: Set<string>,
17
- missingScalars: Set<string>,
18
- rootType: graphql.TypeNode
19
- ) {
20
- // try to find the name of the type
21
- const { type } = unwrapType(config, rootType)
22
-
23
- // if we are looking at a scalar
24
- if (graphql.isScalarType(type)) {
25
- // we're done
26
- return
27
- }
28
-
29
- // if we have already processed this type, don't do anything
30
- if (visitedTypes.has(type.name)) {
31
- return
32
- }
33
-
34
- // if we ran into a union
35
- if (graphql.isUnionType(type)) {
36
- // we don't support them yet
37
- throw new HoudiniError({ filepath, message: 'Input Unions are not supported yet. Sorry!' })
38
- }
39
-
40
- // track that we are processing the type
41
- visitedTypes.add(type.name)
42
-
43
- // if we ran into an enum, add its definition to the file
44
- if (graphql.isEnumType(type)) {
45
- // we need to add an import for the enum
46
- ensureImports({
47
- config,
48
- // @ts-ignore
49
- body,
50
- import: [type.name],
51
- sourceModule: '$houdini/graphql/enums',
52
- importKind: 'type',
53
- })
54
- return
55
- }
56
-
57
- // we found an object type so build up the list of fields (and walk down any object fields)
58
- const members: TSPropertySignatureKind[] = []
59
-
60
- for (const field of Object.values(type.getFields())) {
61
- // walk down the referenced fields and build stuff back up
62
- addReferencedInputTypes(config, filepath, body, visitedTypes, missingScalars, field.type)
63
-
64
- // check if the type is optional so we can label the value as optional
65
-
66
- members.push(
67
- AST.tsPropertySignature(
68
- AST.identifier(field.name),
69
- AST.tsTypeAnnotation(tsTypeReference(config, missingScalars, field)),
70
- graphql.isNullableType(field.type)
71
- )
72
- )
73
- }
74
-
75
- // add the type def to the body
76
- body.push(AST.tsTypeAliasDeclaration(AST.identifier(type.name), AST.tsTypeLiteral(members)))
77
- }
@@ -1,412 +0,0 @@
1
- import { logCyan, logGreen } from '@kitql/helper'
2
- import type { StatementKind } from 'ast-types/gen/kinds'
3
- import * as graphql from 'graphql'
4
- import * as recast from 'recast'
5
-
6
- import { Config, HoudiniError, siteURL, fs, CollectedGraphQLDocument, path } from '../../../lib'
7
- import { flattenSelections } from '../../utils'
8
- import { addReferencedInputTypes } from './addReferencedInputTypes'
9
- import { fragmentKey, inlineType } from './inlineType'
10
- import { tsTypeReference } from './typeReference'
11
- import { readonlyProperty } from './types'
12
-
13
- const AST = recast.types.builders
14
-
15
- // typescriptGenerator generates typescript definitions for the artifacts
16
- export default async function typescriptGenerator(
17
- config: Config,
18
- docs: CollectedGraphQLDocument[]
19
- ) {
20
- // build up a list of paths we have types in (to export from index.d.ts)
21
- const typePaths: string[] = []
22
-
23
- // we need every fragment definition
24
- const fragmentDefinitions: { [name: string]: graphql.FragmentDefinitionNode } = {}
25
- for (const document of docs) {
26
- for (const defn of document.originalDocument.definitions.filter(
27
- ({ kind }) => kind === 'FragmentDefinition'
28
- ) as graphql.FragmentDefinitionNode[]) {
29
- fragmentDefinitions[defn.name.value] = defn
30
- }
31
- }
32
-
33
- const missingScalars = new Set<string>()
34
-
35
- // every document needs a generated type
36
- await Promise.all(
37
- // the generated types depend solely on user-provided information
38
- // so we need to use the original document that we haven't mutated
39
- // as part of the compiler
40
- docs.map(async ({ originalDocument, name, filename, generateArtifact }) => {
41
- if (!generateArtifact) {
42
- return
43
- }
44
-
45
- // the place to put the artifact's type definition
46
- const typeDefPath = config.artifactTypePath(originalDocument)
47
-
48
- // build up the program
49
- const program = AST.program([])
50
-
51
- // if we have to define any types along the way, make sure we only do it once
52
- const visitedTypes = new Set<string>()
53
-
54
- // if there's an operation definition
55
- let definition = originalDocument.definitions.find(
56
- (def) =>
57
- (def.kind === 'OperationDefinition' || def.kind === 'FragmentDefinition') &&
58
- def.name?.value === name
59
- ) as graphql.OperationDefinitionNode | graphql.FragmentDefinitionNode
60
-
61
- const selections = flattenSelections({
62
- config,
63
- filepath: filename,
64
- selections: definition.selectionSet.selections,
65
- fragmentDefinitions,
66
- })
67
-
68
- if (definition?.kind === 'OperationDefinition') {
69
- // treat it as an operation document
70
- await generateOperationTypeDefs(
71
- config,
72
- filename,
73
- program.body,
74
- definition,
75
- selections,
76
- visitedTypes,
77
- missingScalars
78
- )
79
- } else {
80
- // treat it as a fragment document
81
- await generateFragmentTypeDefs(
82
- config,
83
- filename,
84
- program.body,
85
- selections,
86
- originalDocument.definitions,
87
- visitedTypes,
88
- missingScalars
89
- )
90
- }
91
-
92
- // write the file contents
93
- await fs.writeFile(typeDefPath, recast.print(program).code)
94
-
95
- typePaths.push(typeDefPath)
96
- })
97
- )
98
-
99
- // now that we have every type generated, create an index file in the runtime root that exports the types
100
- const typeIndex = AST.program(
101
- typePaths
102
- .sort((a, b) => a.localeCompare(b))
103
- .map((typePath) => {
104
- return AST.exportAllDeclaration(
105
- AST.literal(
106
- './' +
107
- path
108
- .relative(path.resolve(config.typeIndexPath, '..'), typePath)
109
- // remove the .d.ts from the end of the path
110
- .replace(/\.[^/.]+\.[^/.]+$/, '')
111
- ),
112
- null
113
- )
114
- })
115
- .concat([
116
- AST.exportAllDeclaration(AST.literal('./runtime'), null),
117
- AST.exportAllDeclaration(AST.literal('./graphql'), null),
118
- ])
119
- )
120
-
121
- // stringify the value so we can push it through the plugins
122
- const export_default_as = ({ module, as }: { module: string; as: string }) =>
123
- `\nexport { default as ${as} } from "${module}"\n`
124
- const export_star_from = ({ module }: { module: string }) => `\nexport * from "${module}"\n`
125
- let indexContent = recast.print(typeIndex).code
126
- for (const plugin of config.plugins) {
127
- if (!plugin.index_file) {
128
- continue
129
- }
130
- indexContent = plugin.index_file({
131
- config,
132
- content: indexContent,
133
- export_default_as,
134
- export_star_from,
135
- plugin_root: config.pluginDirectory(plugin.name),
136
- typedef: true,
137
- documents: docs,
138
- })
139
-
140
- // if the plugin generated a runtime
141
- if (plugin.include_runtime) {
142
- indexContent += export_star_from({
143
- module:
144
- './' +
145
- path.relative(config.rootDir, config.pluginRuntimeDirectory(plugin.name)),
146
- })
147
- }
148
- }
149
-
150
- // write the contents
151
- await fs.writeFile(config.typeIndexPath, indexContent)
152
-
153
- // if we were missing scalars, we need to warn the user and tell them
154
- if (missingScalars.size > 0) {
155
- console.warn(`⚠️ Missing definitions for the following scalars: ${[...missingScalars].join(
156
- ', '
157
- )}
158
- Generated types will contain an any type in place of these values. To fix this, provide an equivalent
159
- type in your config file:
160
-
161
- {
162
- scalars: {
163
- ${logCyan(`/* in your case, something like */`)}
164
- ${[...missingScalars]
165
- .map(
166
- (c) =>
167
- ` ${c}: { ${logGreen(`// <- The GraphQL Scalar`)}
168
- type: "${logCyan(`YourType_${c}`)}" ${logGreen(`// <- The TypeScript type`)}
169
- }`
170
- )
171
- .join(
172
- `,
173
- `
174
- )}
175
- }
176
- }
177
-
178
- For more information, please visit this link: ${siteURL}/api/config#custom-scalars`)
179
- }
180
- }
181
-
182
- async function generateOperationTypeDefs(
183
- config: Config,
184
- filepath: string,
185
- body: StatementKind[],
186
- definition: graphql.OperationDefinitionNode,
187
- selections: readonly graphql.SelectionNode[],
188
- visitedTypes: Set<string>,
189
- missingScalars: Set<string>
190
- ) {
191
- let parentType: graphql.GraphQLCompositeType | null = null
192
- if (definition.operation === 'query') {
193
- parentType = config.schema.getQueryType()!
194
- } else if (definition.operation === 'mutation') {
195
- parentType = config.schema.getMutationType()!
196
- } else if (definition.operation === 'subscription') {
197
- parentType = config.schema.getSubscriptionType()!
198
- }
199
- if (!parentType) {
200
- throw new HoudiniError({ filepath, message: 'Could not find root type for document' })
201
- }
202
-
203
- // the name of the types we will define
204
- const inputTypeName = `${definition.name!.value}$input`
205
- const shapeTypeName = `${definition.name!.value}$result`
206
- const optimisticTypeName = `${definition.name!.value}$optimistic`
207
-
208
- // dry
209
- const hasInputs = definition.variableDefinitions && definition.variableDefinitions.length > 0
210
-
211
- // add our types to the body
212
- body.push(
213
- // add the root type named after the document that links the input and result types
214
- AST.exportNamedDeclaration(
215
- AST.tsTypeAliasDeclaration(
216
- AST.identifier(definition.name!.value),
217
- AST.tsTypeLiteral([
218
- readonlyProperty(
219
- AST.tsPropertySignature(
220
- AST.stringLiteral('input'),
221
- AST.tsTypeAnnotation(AST.tsTypeReference(AST.identifier(inputTypeName)))
222
- )
223
- ),
224
- readonlyProperty(
225
- AST.tsPropertySignature(
226
- AST.stringLiteral('result'),
227
- AST.tsTypeAnnotation(
228
- definition.operation === 'mutation'
229
- ? AST.tsTypeReference(AST.identifier(shapeTypeName))
230
- : AST.tsUnionType([
231
- AST.tsTypeReference(AST.identifier(shapeTypeName)),
232
- AST.tsUndefinedKeyword(),
233
- ])
234
- )
235
- )
236
- ),
237
- ])
238
- )
239
- ),
240
- // export the type that describes the result
241
- AST.exportNamedDeclaration(
242
- AST.tsTypeAliasDeclaration(
243
- AST.identifier(shapeTypeName),
244
- inlineType({
245
- config,
246
- filepath,
247
- rootType: parentType,
248
- selections,
249
- root: true,
250
- allowReadonly: true,
251
- visitedTypes,
252
- body,
253
- missingScalars,
254
- includeFragments: true,
255
- })
256
- )
257
- )
258
- )
259
-
260
- // if there are variables in this query
261
- if (hasInputs && definition.variableDefinitions && definition.variableDefinitions.length > 0) {
262
- for (const variableDefinition of definition.variableDefinitions) {
263
- addReferencedInputTypes(
264
- config,
265
- filepath,
266
- body,
267
- visitedTypes,
268
- missingScalars,
269
- variableDefinition.type
270
- )
271
- }
272
-
273
- // merge all of the variables into a single object
274
- body.push(
275
- AST.exportNamedDeclaration(
276
- AST.tsTypeAliasDeclaration(
277
- AST.identifier(inputTypeName),
278
- AST.tsTypeLiteral(
279
- (definition.variableDefinitions || []).map(
280
- (definition: graphql.VariableDefinitionNode) => {
281
- // add a property describing the variable to the root object
282
- return AST.tsPropertySignature(
283
- AST.identifier(definition.variable.name.value),
284
- AST.tsTypeAnnotation(
285
- tsTypeReference(config, missingScalars, definition)
286
- ),
287
- definition.type.kind !== 'NonNullType'
288
- )
289
- }
290
- )
291
- )
292
- )
293
- )
294
- )
295
- } else {
296
- body.push(
297
- AST.exportNamedDeclaration(
298
- AST.tsTypeAliasDeclaration(AST.identifier(inputTypeName), AST.tsNullKeyword())
299
- )
300
- )
301
- }
302
-
303
- // mutations need to have an optimistic response type defined
304
- if (definition.operation === 'mutation') {
305
- body.push(
306
- AST.exportNamedDeclaration(
307
- AST.tsTypeAliasDeclaration(
308
- AST.identifier(optimisticTypeName),
309
- inlineType({
310
- config,
311
- filepath,
312
- rootType: parentType,
313
- selections,
314
- root: true,
315
- allowReadonly: true,
316
- visitedTypes,
317
- body,
318
- missingScalars,
319
- includeFragments: false,
320
- allOptional: true,
321
- })
322
- )
323
- )
324
- )
325
- }
326
- }
327
-
328
- async function generateFragmentTypeDefs(
329
- config: Config,
330
- filepath: string,
331
- body: StatementKind[],
332
- selections: readonly graphql.SelectionNode[],
333
- definitions: readonly graphql.DefinitionNode[],
334
- visitedTypes: Set<string>,
335
- missingScalars: Set<string>
336
- ) {
337
- // every definition will contribute the same thing to the typedefs
338
- for (const definition of definitions) {
339
- // if its not a fragment definition
340
- if (definition.kind !== 'FragmentDefinition') {
341
- // we don't know what to do
342
- continue
343
- }
344
-
345
- // the name of the prop type
346
- const propTypeName = definition.name.value
347
- // the name of the shape type
348
- const shapeTypeName = `${definition.name.value}$data`
349
-
350
- // look up the root type of the document
351
- const type = config.schema.getType(definition.typeCondition.name.value)
352
- if (!type) {
353
- throw new Error('Should not get here')
354
- }
355
-
356
- body.push(
357
- // we need to add a type that will act as the entry point for the fragment
358
- // and be assigned to the prop that holds the reference passed from
359
- // the fragment's parent
360
- AST.exportNamedDeclaration(
361
- AST.tsTypeAliasDeclaration(
362
- AST.identifier(propTypeName),
363
- AST.tsTypeLiteral([
364
- readonlyProperty(
365
- AST.tsPropertySignature(
366
- AST.stringLiteral('shape'),
367
- AST.tsTypeAnnotation(
368
- AST.tsTypeReference(AST.identifier(shapeTypeName))
369
- ),
370
- true
371
- )
372
- ),
373
- readonlyProperty(
374
- AST.tsPropertySignature(
375
- AST.stringLiteral(fragmentKey),
376
- AST.tsTypeAnnotation(
377
- AST.tsTypeLiteral([
378
- AST.tsPropertySignature(
379
- AST.stringLiteral(propTypeName),
380
- AST.tsTypeAnnotation(
381
- AST.tsLiteralType(AST.booleanLiteral(true))
382
- )
383
- ),
384
- ])
385
- )
386
- )
387
- ),
388
- ])
389
- )
390
- ),
391
-
392
- // export the type that describes the fragments response data
393
- AST.exportNamedDeclaration(
394
- AST.tsTypeAliasDeclaration(
395
- AST.identifier(shapeTypeName),
396
- inlineType({
397
- config,
398
- filepath,
399
- rootType: type,
400
- selections,
401
- root: true,
402
- allowReadonly: true,
403
- body,
404
- visitedTypes,
405
- missingScalars,
406
- includeFragments: true,
407
- })
408
- )
409
- )
410
- )
411
- }
412
- }