1 | #!/usr/bin/env node
|
2 | 'use strict'
|
3 | const parseArgs = require('minimist')
|
4 | const resolveFrom = require('resolve-from')
|
5 | const { loadSchemaJSON, schemaToJSON } = require('./loadSchemaJSON')
|
6 | const renderSchema = require('./renderSchema')
|
7 | const updateSchema = require('./updateSchema')
|
8 | const diffSchema = require('./diffSchema')
|
9 |
|
10 | function safeExit(code) {
|
11 | process.on('exit', function() {
|
12 | process.exit(code)
|
13 | })
|
14 | }
|
15 |
|
16 | function printHelp(console) {
|
17 | const name = require('../package.json').name
|
18 | console.log(`
|
19 | Usage: ${name} [options] <schema>
|
20 |
|
21 | Output a Markdown document with rendered descriptions and links between types.
|
22 | The schema may be specified as:
|
23 |
|
24 | - a URL to the GraphQL endpoint (the introspection query will be run)
|
25 | - a GraphQL document containing the schema (.graphql or .gql)
|
26 | - a JSON document containing the schema (as returned by the introspection query)
|
27 | - an importable module with the schema as its default export (either an instance
|
28 | of GraphQLSchema or a JSON object)
|
29 |
|
30 | Options:
|
31 |
|
32 | --title <string> Change the top heading title (default: 'Schema Types')
|
33 | --no-title Do not print a default title
|
34 | --prologue <string> Include custom Markdown after the title
|
35 | --epilogue <string> Include custom Markdown after everything else
|
36 | --heading-level <num> Heading level to begin at, useful if you are embedding the
|
37 | output in a document with other sections (default: 1)
|
38 | --update-file <file> Markdown document to update (between comment markers) or
|
39 | create (if the file does not exist)
|
40 | --require <module> If importing the schema from a module, require the specified
|
41 | module first (useful for e.g. babel-register)
|
42 | --version Print version and exit
|
43 | `)
|
44 | }
|
45 |
|
46 | function run(
|
47 | argv = process.argv.slice(2),
|
48 | { console = global.console, exit = true } = {}
|
49 | ) {
|
50 | const args = parseArgs(argv)
|
51 |
|
52 | if (args.help) {
|
53 | printHelp(console)
|
54 | } else if (args.version) {
|
55 | console.log(require('../package.json').version)
|
56 | } else if (args._.length === 1) {
|
57 | if (args.require) {
|
58 | const requirePath = resolveFrom('.', args.require)
|
59 | if (requirePath) {
|
60 | require(requirePath)
|
61 | } else {
|
62 | throw new Error(`Could not resolve --require module: ${args.require}`)
|
63 | }
|
64 | }
|
65 | const schemaPath = args._[0]
|
66 | loadSchemaJSON(schemaPath).then(schema => {
|
67 | const options = {
|
68 | title: args.title,
|
69 | skipTitle: false,
|
70 | prologue: args.prologue,
|
71 | epilogue: args.epilogue,
|
72 | headingLevel: args['heading-level']
|
73 | }
|
74 | if (options.title === false) {
|
75 | options.title = ''
|
76 | options.skipTitle = true
|
77 | } else if (Array.isArray(options.title)) {
|
78 | options.title.forEach(value => {
|
79 | if (typeof value === 'string') {
|
80 | options.title = value
|
81 | } else if (value === false) {
|
82 | options.skipTitle = true
|
83 | }
|
84 | })
|
85 | }
|
86 | const updateFile = args['update-file']
|
87 | if (updateFile) {
|
88 | updateSchema(updateFile, schema, options)
|
89 | .then(() => {
|
90 | if (exit) {
|
91 | safeExit(0)
|
92 | }
|
93 | })
|
94 | .catch(err => {
|
95 | console.error(err)
|
96 | if (exit) {
|
97 | safeExit(1)
|
98 | }
|
99 | })
|
100 | } else {
|
101 | renderSchema(schema, options)
|
102 | if (exit) {
|
103 | safeExit(0)
|
104 | }
|
105 | }
|
106 | })
|
107 | } else {
|
108 | printHelp(console)
|
109 | if (exit) {
|
110 | safeExit(1)
|
111 | }
|
112 | }
|
113 | }
|
114 |
|
115 | module.exports = {
|
116 | run,
|
117 | loadSchemaJSON,
|
118 | schemaToJSON,
|
119 | renderSchema,
|
120 | updateSchema,
|
121 | diffSchema
|
122 | }
|
123 |
|
124 | if (require.main === module) {
|
125 | run()
|
126 | }
|