-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
executable file
·110 lines (103 loc) · 2.76 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#!/usr/bin/env node
const fs = require('fs')
const path = require('path')
const getStdin = require('get-stdin')
const { buildASTSchema, graphql, parse } = require('graphql')
const { introspectionQuery } = require('graphql/utilities')
const log = x => (console.trace(x), x)
// Turns an array of objects into an object indexed by a given field.
function index(array, field) {
const index = {}
array.forEach(item => {
index[item[field]] = item
})
return index
}
function indentedLine(level) {
let line = '\n'
for (let i = 0; i < level; i++) {
line += ' '
}
return line
}
async function introspect(schemaContents) {
const schema = buildASTSchema(parse(schemaContents))
return await graphql(schema, introspectionQuery)
}
function makeFragments(schemaContents) {
const schema = schemaContents.data.__schema
const types = schema.types.filter(
({ kind, name }) =>
kind === 'OBJECT' &&
!name.startsWith('__') &&
name !== schema.queryType.name &&
name !== schema.mutationType.name,
)
const typesByName = index(types, 'name')
const definitions = types
.filter(
({ kind, name }) =>
kind === 'OBJECT' &&
!name.startsWith('__') &&
name !== schema.queryType.name,
)
.map(type => {
const { name, fields } = type
return {
name,
fragment: `fragment ${name} on ${name} {
${fields
.map(field => printField(field, typesByName))
// Some fields should not be printed, ie. fields with arguments.
// Remove those from the output by returning null from printField.
.filter(field => field != null)
.join(indentedLine(1))}
}
`,
}
})
return `// This file was auto-generated by graphql-fragment-codegen. Do not edit it by hand.
${definitions
.map(
({ name, fragment }) => `
export const ${name} = \`${fragment}\`
`,
)
.join('')}`
}
function printField(field, typesByName, indent = 1) {
const { name, type } = field
if ('args' in field && field.args.length > 0) {
return null
}
if (type.kind === 'SCALAR') {
return name
}
if (type.kind === 'OBJECT') {
return (
name +
' {' +
indentedLine(indent + 1) +
typesByName[type.name].fields
.map(field => printField(field, typesByName, indent + 1))
.filter(field => field != null)
.join(indentedLine(indent + 1)) +
indentedLine(indent) +
'}'
)
}
if (type.kind === 'LIST') {
return printField({ ...field, type: type.ofType }, typesByName)
}
console.error('unmatched type kind: ', type.kind)
return null
}
async function main() {
const stdin = await getStdin()
if (stdin === '') {
process.exit(1)
}
const schemaContents = await introspect(stdin)
process.stdout.write(makeFragments(schemaContents))
}
main()