@stepzen/transpiler 0.0.32 → 0.0.35

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 (65) hide show
  1. package/LICENSE +1 -1
  2. package/lib/actions/configure.js +15 -14
  3. package/lib/actions/configure.js.map +1 -0
  4. package/lib/actions/lint.js +6 -5
  5. package/lib/actions/lint.js.map +1 -0
  6. package/lib/actions/merge.js +14 -15
  7. package/lib/actions/merge.js.map +1 -0
  8. package/lib/actions/print.d.ts +1 -1
  9. package/lib/actions/print.js +2 -1
  10. package/lib/actions/print.js.map +1 -0
  11. package/lib/actions/stitch.js +14 -13
  12. package/lib/actions/stitch.js.map +1 -0
  13. package/lib/actions/transpile.js +7 -6
  14. package/lib/actions/transpile.js.map +1 -0
  15. package/lib/actions/validate.js +4 -3
  16. package/lib/actions/validate.js.map +1 -0
  17. package/lib/index.d.ts +7 -1
  18. package/lib/index.js +16 -16
  19. package/lib/index.js.map +1 -0
  20. package/lib/mutations/config/envvars.js +3 -2
  21. package/lib/mutations/config/envvars.js.map +1 -0
  22. package/lib/mutations/config/index.js +1 -0
  23. package/lib/mutations/config/index.js.map +1 -0
  24. package/lib/utils/constants.js +2 -1
  25. package/lib/utils/constants.js.map +1 -0
  26. package/lib/utils/dedupe-query-and-mutation-types.js +7 -6
  27. package/lib/utils/dedupe-query-and-mutation-types.js.map +1 -0
  28. package/lib/utils/ensure-query-and-mutation-types.d.ts +1 -1
  29. package/lib/utils/ensure-query-and-mutation-types.js +7 -6
  30. package/lib/utils/ensure-query-and-mutation-types.js.map +1 -0
  31. package/lib/utils/graphql-helpers.js +1 -0
  32. package/lib/utils/graphql-helpers.js.map +1 -0
  33. package/lib/utils/merge-helpers.d.ts +1 -1
  34. package/lib/utils/merge-helpers.js +9 -6
  35. package/lib/utils/merge-helpers.js.map +1 -0
  36. package/lib/utils/set-files-in-sdl.js +9 -8
  37. package/lib/utils/set-files-in-sdl.js.map +1 -0
  38. package/lib/utils/strip-empty-queries-and-mutations.d.ts +1 -1
  39. package/lib/utils/strip-empty-queries-and-mutations.js +7 -6
  40. package/lib/utils/strip-empty-queries-and-mutations.js.map +1 -0
  41. package/lib/validators/config-exists/index.d.ts +1 -1
  42. package/lib/validators/config-exists/index.js +11 -10
  43. package/lib/validators/config-exists/index.js.map +1 -0
  44. package/lib/validators/index.js +1 -0
  45. package/lib/validators/index.js.map +1 -0
  46. package/package.json +24 -16
  47. package/src/actions/configure.ts +120 -0
  48. package/src/actions/lint.ts +45 -0
  49. package/src/actions/merge.ts +186 -0
  50. package/src/actions/print.ts +8 -0
  51. package/src/actions/stitch.ts +105 -0
  52. package/src/actions/transpile.ts +70 -0
  53. package/src/actions/validate.ts +54 -0
  54. package/src/index.ts +7 -0
  55. package/src/mutations/config/envvars.ts +17 -0
  56. package/src/mutations/config/index.ts +3 -0
  57. package/src/utils/constants.ts +16 -0
  58. package/src/utils/dedupe-query-and-mutation-types.ts +74 -0
  59. package/src/utils/ensure-query-and-mutation-types.ts +52 -0
  60. package/src/utils/graphql-helpers.ts +3 -0
  61. package/src/utils/merge-helpers.ts +176 -0
  62. package/src/utils/set-files-in-sdl.ts +40 -0
  63. package/src/utils/strip-empty-queries-and-mutations.ts +43 -0
  64. package/src/validators/config-exists/index.ts +54 -0
  65. package/src/validators/index.ts +3 -0
@@ -0,0 +1,8 @@
1
+ import {DocumentNode, print} from 'graphql'
2
+ import * as prettier from 'prettier'
3
+
4
+ export default (ast: DocumentNode): string => {
5
+ const printed = print(ast)
6
+ const formatted = prettier.format(printed, {parser: 'graphql'})
7
+ return formatted
8
+ }
@@ -0,0 +1,105 @@
1
+ import {clone, cloneDeep} from 'lodash'
2
+ import {parse, print, visit} from 'graphql'
3
+ import * as fs from 'fs-extra'
4
+ import * as glob from 'glob'
5
+ import * as os from 'os'
6
+ import * as path from 'path'
7
+ import * as prettier from 'prettier'
8
+
9
+ import dedupeQueryAndMutationTypes from '../utils/dedupe-query-and-mutation-types'
10
+
11
+ export default (
12
+ source: string,
13
+ output: string = path.join(os.tmpdir(), `stepzen-tmp-${Date.now()}`),
14
+ ) => {
15
+ // Ensure source and output directories exist
16
+ if (!fs.existsSync(source))
17
+ throw new Error(`Cannot find source directory ${source}`)
18
+ fs.ensureDirSync(output)
19
+
20
+ // Get a list of files.
21
+ let ast: any
22
+ let files: string[] = []
23
+
24
+ // If there's an index.graphQL - get files argument in @sdl directive
25
+ const sourceIndex = path.join(source, 'index.graphql')
26
+
27
+ if (fs.existsSync(sourceIndex)) {
28
+ const index = fs.readFileSync(sourceIndex, 'utf8')
29
+ ast = parse(index)
30
+ ast = visit(ast, {
31
+ Directive(node) {
32
+ if (node.name.value === 'sdl') {
33
+ const list = node.arguments?.find(
34
+ (arg: any) => arg.name.value === 'files',
35
+ )
36
+ // If we find a 'files' argument, we copy the list, and remove the argument
37
+ if (list) {
38
+ const copy: any = clone(list.value)
39
+ for (const file of copy.values) {
40
+ files = files.concat(file.value)
41
+ }
42
+ const mutated: any = cloneDeep(node)
43
+ mutated.arguments = mutated.arguments.filter(
44
+ (arg: any) => arg.name.value !== 'files',
45
+ )
46
+ return mutated
47
+ }
48
+ }
49
+ },
50
+ })
51
+ } else {
52
+ const content = glob
53
+ .sync('**/*.graphql', {cwd: source})
54
+ .map((file: string) => {
55
+ const graphql = fs.readFileSync(`${source}/${file}`, 'utf8')
56
+ return graphql
57
+ })
58
+ ast = parse(content.join(os.EOL))
59
+ }
60
+
61
+ // Strip @sdl directive
62
+ ast = visit(ast, {
63
+ Directive(node) {
64
+ if (node.name.value === 'sdl') return null
65
+ },
66
+ })
67
+
68
+ // Check all the files exist
69
+ for (const file of files) {
70
+ const find = path.join(source, file)
71
+ if (!fs.existsSync(find)) {
72
+ throw new Error(`Cannot find file ${find}`)
73
+ }
74
+ }
75
+
76
+ // Get all the files and stitch
77
+ const printed = print(ast)
78
+ let stitched = `${printed}${os.EOL}`
79
+ for (const file of files) {
80
+ const find = path.join(source, file)
81
+ const content = fs.readFileSync(find, 'utf8')
82
+ stitched += `${content}${os.EOL}`
83
+ }
84
+
85
+ // Dedupe Query and Mutation types
86
+ stitched = dedupeQueryAndMutationTypes(stitched)
87
+
88
+ // Format
89
+ stitched = prettier.format(stitched, {parser: 'graphql'})
90
+
91
+ // Write to output folder
92
+ const outputIndex = path.join(output, 'index.graphql')
93
+ fs.writeFileSync(outputIndex, stitched)
94
+
95
+ // Copy config if exists, too
96
+ const sourceConfig = path.join(source, 'config.yaml')
97
+ const outputConfig = path.join(output, 'config.yaml')
98
+
99
+ if (fs.existsSync(sourceConfig)) {
100
+ fs.copyFileSync(sourceConfig, outputConfig)
101
+ }
102
+
103
+ // Return output folder
104
+ return output
105
+ }
@@ -0,0 +1,70 @@
1
+ import {DocumentNode, parse} from 'graphql'
2
+ import * as dotenv from 'dotenv'
3
+ import * as fs from 'fs'
4
+ import * as glob from 'glob'
5
+ import * as path from 'path'
6
+
7
+ import print from '../actions/print'
8
+ import stitch from '../actions/stitch'
9
+ import configure from './configure'
10
+
11
+ import configMutations from '../mutations/config'
12
+
13
+ export default async (source: string) => {
14
+ // Ensure source and output directories exist
15
+ if (!fs.existsSync(source)) {
16
+ throw new Error(`Cannot find source directory ${source}`)
17
+ }
18
+
19
+ // Load env vars, from working and source directories
20
+ dotenv.config()
21
+ dotenv.config({path: path.resolve(source, '.env')})
22
+
23
+ // State of whether we've transpiled or not
24
+ let transpiledConfig = false
25
+ let transpiledGraphQL = false
26
+
27
+ // See whether to transpile config
28
+ let config: any = await configure(source, true)
29
+ const configCopy = config
30
+
31
+ if (config) {
32
+ for await (const mutation of configMutations) {
33
+ config = await mutation(config)
34
+ }
35
+ }
36
+
37
+ if (configCopy !== config) {
38
+ transpiledConfig = true
39
+ }
40
+
41
+ // See whether to transpile GraphQL
42
+ const graphqlFiles = glob.sync('**/*.graphql', {cwd: source})
43
+ let original: any = ''
44
+ let mutated: any = ''
45
+
46
+ if (graphqlFiles.length > 0) {
47
+ const stitched = await stitch(source)
48
+
49
+ const index = path.join(stitched, 'index.graphql')
50
+
51
+ const graphql = fs.readFileSync(index, 'utf8')
52
+
53
+ let ast: DocumentNode = parse(graphql)
54
+ original = parse(graphql)
55
+
56
+ // you can transpile schema ast here
57
+
58
+ mutated = print(ast)
59
+
60
+ if (print(original) !== mutated) {
61
+ transpiledGraphQL = true
62
+ }
63
+ }
64
+
65
+ return {
66
+ config,
67
+ schema: mutated,
68
+ transpiled: transpiledConfig || transpiledGraphQL,
69
+ }
70
+ }
@@ -0,0 +1,54 @@
1
+ import {buildASTSchema, DocumentNode, parse, print} from 'graphql'
2
+ import * as fs from 'fs-extra'
3
+ import * as os from 'os'
4
+ import * as path from 'path'
5
+
6
+ import ensureQueryAndMutationTypes from '../utils/ensure-query-and-mutation-types'
7
+ import {EXPERIMENTAL_EXTENSIONS} from '../utils/constants'
8
+ import validators from '../validators'
9
+
10
+ export default (
11
+ source: string,
12
+ options: {
13
+ extensions: string
14
+ } = {
15
+ extensions: '',
16
+ },
17
+ ) => {
18
+ // Ensure source and output directories exist
19
+ if (!fs.existsSync(source)) {
20
+ throw new Error(`Cannot find source directory ${source}`)
21
+ }
22
+
23
+ // Ensure index.graphql exists
24
+ if (!fs.existsSync(`${source}/index.graphql`)) {
25
+ throw new Error(`Cannot find index.graphql in ${source}`)
26
+ }
27
+
28
+ // Get the index.graphql file
29
+ const file = path.join(source, 'index.graphql')
30
+ const index = fs.readFileSync(file, 'utf8')
31
+
32
+ // Parse
33
+ let ast: DocumentNode = parse(
34
+ `${EXPERIMENTAL_EXTENSIONS}${os.EOL}${options.extensions}${os.EOL}${index}`,
35
+ {
36
+ noLocation: true,
37
+ },
38
+ )
39
+
40
+ // We make an exception for 'no type Query' or 'no type Mutation'
41
+ ast = ensureQueryAndMutationTypes(ast)
42
+
43
+ // Build and print, to validate
44
+ buildASTSchema(ast)
45
+ print(ast)
46
+
47
+ // Custom validators
48
+ for (const validator of validators) {
49
+ validator(ast, source)
50
+ }
51
+
52
+ // Return true
53
+ return true
54
+ }
package/src/index.ts ADDED
@@ -0,0 +1,7 @@
1
+ export {default as configure} from './actions/configure'
2
+ export {default as lint} from './actions/lint'
3
+ export {default as merge} from './actions/merge'
4
+ export {default as print} from './actions/print'
5
+ export {default as stitch} from './actions/stitch'
6
+ export {default as transpile} from './actions/transpile'
7
+ export {default as validate} from './actions/validate'
@@ -0,0 +1,17 @@
1
+ export default async (config: string): Promise<string> => {
2
+ const envvars = Object.keys(process.env)
3
+ .filter(key => {
4
+ return key.startsWith(`STEPZEN_`)
5
+ })
6
+ .reduce((obj: any, key) => {
7
+ obj[key] = process.env[key]
8
+ return obj
9
+ }, {})
10
+
11
+ for (const [key, value] of Object.entries(envvars)) {
12
+ const regex = new RegExp(key, 'g')
13
+ config = config.replace(regex, `${value}`)
14
+ }
15
+
16
+ return config
17
+ }
@@ -0,0 +1,3 @@
1
+ import envvars from './envvars'
2
+
3
+ export default [envvars]
@@ -0,0 +1,16 @@
1
+ import * as dotenv from 'dotenv'
2
+
3
+ dotenv.config()
4
+
5
+ const {STEPZEN_DOMAIN: ENV_VAR_STEPZEN_DOMAIN} = process.env
6
+
7
+ export const EXPERIMENTAL_EXTENSIONS = `
8
+ directive @experimental(
9
+ debug: Boolean
10
+ function: String
11
+ mock: String
12
+ setter: String
13
+ ) on OBJECT | FIELD_DEFINITION
14
+ `
15
+
16
+ export const STEPZEN_DOMAIN = ENV_VAR_STEPZEN_DOMAIN || 'stepzen.io'
@@ -0,0 +1,74 @@
1
+ import {DocumentNode, parse, print, visit} from 'graphql'
2
+
3
+ import {cloneDeep} from '../utils/graphql-helpers'
4
+
5
+ export default (schema: string): string => {
6
+ let ast: DocumentNode = parse(schema)
7
+
8
+ let queries: any = []
9
+ let mutations: any = []
10
+
11
+ // Loop through the AST and find Query and Mutation types.
12
+ // Store their fields.
13
+ // Return null to remove it from the tree
14
+ ast = visit(ast, {
15
+ ObjectTypeDefinition: {
16
+ enter(node) {
17
+ if (node.name.kind === 'Name' && node.name.value === 'Query') {
18
+ queries = queries.concat(node.fields)
19
+ return null
20
+ }
21
+ if (node.name.kind === 'Name' && node.name.value === 'Mutation') {
22
+ mutations = mutations.concat(node.fields)
23
+ return null
24
+ }
25
+ },
26
+ },
27
+ })
28
+
29
+ // This is the template for the new Query type
30
+ const queryTemplate = {
31
+ kind: 'ObjectTypeDefinition',
32
+ description: undefined,
33
+ name: {kind: 'Name', value: 'Query'},
34
+ interfaces: [],
35
+ directives: [],
36
+ fields: [],
37
+ }
38
+
39
+ // This is the template for the new Mutation type
40
+ const mutationTemplate = {
41
+ kind: 'ObjectTypeDefinition',
42
+ description: undefined,
43
+ name: {kind: 'Name', value: 'Mutation'},
44
+ interfaces: [],
45
+ directives: [],
46
+ fields: [],
47
+ }
48
+
49
+ // If there are queries, add a single Query type
50
+ // with all the concatenated queries
51
+ if (queries.length > 0) {
52
+ const mutated: any = cloneDeep(ast)
53
+ const query = {
54
+ ...queryTemplate,
55
+ fields: queries,
56
+ }
57
+ mutated.definitions.push(query)
58
+ ast = mutated
59
+ }
60
+
61
+ // If there are mutations, add a single Query type
62
+ // with all the concatenated mutations
63
+ if (mutations.length > 0) {
64
+ const mutated: any = cloneDeep(ast)
65
+ const query = {
66
+ ...mutationTemplate,
67
+ fields: mutations,
68
+ }
69
+ mutated.definitions.push(query)
70
+ ast = mutated
71
+ }
72
+
73
+ return print(ast)
74
+ }
@@ -0,0 +1,52 @@
1
+ import {DocumentNode, visit} from 'graphql'
2
+
3
+ import {cloneDeep} from '../utils/graphql-helpers'
4
+
5
+ export default (ast: DocumentNode): DocumentNode => {
6
+ let queries: any = []
7
+ let mutations: any = []
8
+
9
+ // Loop through the AST and find Query and Mutation types.
10
+ ast = visit(ast, {
11
+ ObjectTypeDefinition: {
12
+ enter(node) {
13
+ if (node.name.kind === 'Name' && node.name.value === 'Query') {
14
+ queries = queries.concat(node.fields)
15
+ }
16
+ if (node.name.kind === 'Name' && node.name.value === 'Mutation') {
17
+ mutations = mutations.concat(node.fields)
18
+ }
19
+ },
20
+ },
21
+ })
22
+
23
+ // If there are no queries, add a single empty Query type
24
+ if (queries.length === 0) {
25
+ const mutated: any = cloneDeep(ast)
26
+ mutated.definitions.push({
27
+ kind: 'ObjectTypeDefinition',
28
+ description: undefined,
29
+ name: {kind: 'Name', value: 'Query'},
30
+ interfaces: [],
31
+ directives: [],
32
+ fields: [],
33
+ })
34
+ ast = mutated
35
+ }
36
+
37
+ // If there are mutations, add a single empty Mutation type
38
+ if (mutations.length === 0) {
39
+ const mutated: any = cloneDeep(ast)
40
+ mutated.definitions.push({
41
+ kind: 'ObjectTypeDefinition',
42
+ description: undefined,
43
+ name: {kind: 'Name', value: 'Mutation'},
44
+ interfaces: [],
45
+ directives: [],
46
+ fields: [],
47
+ })
48
+ ast = mutated
49
+ }
50
+
51
+ return ast
52
+ }
@@ -0,0 +1,3 @@
1
+ export const cloneDeep = (obj: any) => {
2
+ return JSON.parse(JSON.stringify(obj))
3
+ }
@@ -0,0 +1,176 @@
1
+ import {BREAK, GraphQLSchema, visit} from 'graphql'
2
+ import {buildSchema} from 'graphql/utilities'
3
+ import fetch from 'node-fetch'
4
+ import * as fs from 'fs-extra'
5
+ import * as glob from 'glob'
6
+ import * as os from 'os'
7
+ import * as path from 'path'
8
+ import {replace} from 'lodash'
9
+
10
+ import {cloneDeep} from '../utils/graphql-helpers'
11
+ import {STEPZEN_DOMAIN} from './constants'
12
+
13
+ import configure from '../actions/configure'
14
+ import transpile from '../actions/transpile'
15
+
16
+ export const dedupeTempFolder = (dirpath: string) => {
17
+ do {
18
+ dirpath = replace(dirpath, os.tmpdir(), '')
19
+ } while (dirpath.includes(os.tmpdir()))
20
+
21
+ dirpath = path.join(os.tmpdir(), dirpath)
22
+
23
+ return dirpath
24
+ }
25
+
26
+ export const findQueryMutationInSchema = (
27
+ name: string,
28
+ files: any,
29
+ ): Boolean => {
30
+ for (const file of files) {
31
+ let found = false
32
+ visit(file.ast, {
33
+ FieldDefinition(node) {
34
+ if (node.name.value === name) {
35
+ found = true
36
+ return BREAK
37
+ }
38
+ },
39
+ })
40
+ if (found) return true
41
+ }
42
+ return false
43
+ }
44
+
45
+ export const findTypeInSchema = (name: string, files: any): Boolean => {
46
+ for (const file of files) {
47
+ let found = false
48
+ visit(file.ast, {
49
+ ObjectTypeDefinition(node) {
50
+ if (node.name.value === name) {
51
+ found = true
52
+ return BREAK
53
+ }
54
+ },
55
+ })
56
+ if (found) return true
57
+ }
58
+ return false
59
+ }
60
+
61
+ export const getConfiguration = async (
62
+ directories: string[],
63
+ silent: boolean = false,
64
+ answers: any = {},
65
+ ): Promise<string | boolean> => {
66
+ const tmp = path.join(os.tmpdir(), `stepzen-tmp-config-${Date.now()}`)
67
+ fs.ensureDirSync(tmp)
68
+
69
+ for (const directory of directories) {
70
+ const configs = [
71
+ ...glob.sync('**/config.yaml', {cwd: directory}),
72
+ ...glob.sync('**/stepzen.config.json', {cwd: directory}),
73
+ ]
74
+
75
+ for (const config of configs) {
76
+ const configFolder = path.join(directory, config)
77
+
78
+ let writeFolder = path.join(tmp, directory, config)
79
+ writeFolder = dedupeTempFolder(writeFolder)
80
+
81
+ const content = fs.readFileSync(configFolder, 'utf8')
82
+
83
+ fs.ensureFileSync(writeFolder)
84
+ fs.writeFileSync(writeFolder, content)
85
+ }
86
+ }
87
+
88
+ const configuration = await configure(tmp, silent, answers)
89
+ fs.removeSync(tmp)
90
+ return configuration
91
+ }
92
+
93
+ export const getExtensions = async (): Promise<string> => {
94
+ const domain = STEPZEN_DOMAIN.replace('.io', '.net')
95
+ const response = await fetch(`https://www.${domain}/directives.graphql`)
96
+ const text = await response.text()
97
+ return text
98
+ }
99
+
100
+ export const getSchema = async (directory: string): Promise<GraphQLSchema> => {
101
+ const extensions = await getExtensions()
102
+ const transpiled = await transpile(directory)
103
+ return buildSchema(`${extensions}${os.EOL}${transpiled.schema}`)
104
+ }
105
+
106
+ export const mergeQueryMutationIntoSchema = (type: any, files: any) => {
107
+ files = files.map((file: any) => {
108
+ return {
109
+ ...file,
110
+ ast: visit(file.ast, {
111
+ FieldDefinition(node) {
112
+ if (node.name.value === type.name.value) {
113
+ const directives = cloneDeep(type.directives)
114
+ const mutated: any = cloneDeep(node)
115
+ mutated.directives = directives
116
+ return mutated
117
+ }
118
+ },
119
+ }),
120
+ }
121
+ })
122
+ return files
123
+ }
124
+
125
+ export const mergeTypeIntoSchema = (type: any, files: any) => {
126
+ files = files.map((file: any) => {
127
+ return {
128
+ ...file,
129
+ ast: visit(file.ast, {
130
+ ObjectTypeDefinition(node) {
131
+ if (node.name.value === type.name.value) {
132
+ const directives = cloneDeep(type.directives)
133
+ const fields = cloneDeep(type.fields)
134
+ const mutated: any = cloneDeep(node)
135
+ mutated.directives = directives
136
+ mutated.fields = fields
137
+ return mutated
138
+ }
139
+ },
140
+ }),
141
+ }
142
+ })
143
+ return files
144
+ }
145
+
146
+ export const removeQueryMutationFromSchema = (name: string, files: any) => {
147
+ files = files.map((file: any) => {
148
+ return {
149
+ ...file,
150
+ ast: visit(file.ast, {
151
+ FieldDefinition(node) {
152
+ if (node.name.value === name) {
153
+ return null
154
+ }
155
+ },
156
+ }),
157
+ }
158
+ })
159
+ return files
160
+ }
161
+
162
+ export const removeTypeFromSchema = (name: string, files: any) => {
163
+ files = files.map((file: any) => {
164
+ return {
165
+ ...file,
166
+ ast: visit(file.ast, {
167
+ ObjectTypeDefinition(node) {
168
+ if (node.name.value === name) {
169
+ return null
170
+ }
171
+ },
172
+ }),
173
+ }
174
+ })
175
+ return files
176
+ }
@@ -0,0 +1,40 @@
1
+ import * as fs from 'fs'
2
+ import * as glob from 'glob'
3
+ import {parse, visit} from 'graphql'
4
+ import * as path from 'path'
5
+
6
+ import {cloneDeep} from './graphql-helpers'
7
+ import print from '../actions/print'
8
+
9
+ export default (source: string) => {
10
+ const files = glob
11
+ .sync('**/*.graphql', {cwd: source})
12
+ .filter(file => file !== 'index.graphql')
13
+
14
+ const output = path.join(source, 'index.graphql')
15
+
16
+ const index = fs.readFileSync(output, 'utf8')
17
+
18
+ let ast = parse(index)
19
+ ast = visit(ast, {
20
+ Directive(node) {
21
+ if (node.name.value === 'sdl') {
22
+ const mutated: any = cloneDeep(node)
23
+
24
+ mutated.arguments = mutated.arguments.map((arg: any) => {
25
+ if (arg.name.value === 'files') {
26
+ arg.value.values = files.map(file => ({
27
+ kind: 'StringValue',
28
+ value: file,
29
+ }))
30
+ }
31
+ return arg
32
+ })
33
+
34
+ return mutated
35
+ }
36
+ },
37
+ })
38
+
39
+ fs.writeFileSync(output, print(ast))
40
+ }
@@ -0,0 +1,43 @@
1
+ import {DocumentNode, visit} from 'graphql'
2
+
3
+ import {cloneDeep} from './graphql-helpers'
4
+
5
+ export default (ast: DocumentNode): DocumentNode => {
6
+ // Loop through the AST and nuke `__query` and `__mutation` stubs
7
+ ast = visit(ast, {
8
+ ObjectTypeDefinition: {
9
+ enter(node) {
10
+ if (node.name.kind === 'Name' && node.name.value === 'Query') {
11
+ const mutated: any = cloneDeep(node)
12
+ mutated.fields = mutated.fields.filter((field: any) => {
13
+ return field.name.value !== '__query'
14
+ })
15
+ return mutated
16
+ }
17
+ if (node.name.kind === 'Name' && node.name.value === 'Mutation') {
18
+ const mutated: any = cloneDeep(node)
19
+ mutated.fields = mutated.fields.filter((field: any) => {
20
+ return field.name.value !== '__mutated'
21
+ })
22
+ return mutated
23
+ }
24
+ },
25
+ },
26
+ })
27
+
28
+ // Strip empty Queries and Mutations definitions
29
+ ast = visit(ast, {
30
+ ObjectTypeDefinition: {
31
+ enter(node) {
32
+ if (node.name.kind === 'Name' && node.name.value === 'Query') {
33
+ if (node.fields?.length === 0) return null
34
+ }
35
+ if (node.name.kind === 'Name' && node.name.value === 'Mutation') {
36
+ if (node.fields?.length === 0) return null
37
+ }
38
+ },
39
+ },
40
+ })
41
+
42
+ return ast
43
+ }