UNPKG

4.62 kBPlain TextView Raw
1/**
2 * Copyright (c) 2016, John Hewson
3 * All rights reserved.
4 */
5
6/// <reference path="../typings/node.d.ts" />
7/// <reference path="../typings/request.d.ts" />
8/// <reference path="../typings/graphql-utilities.d.ts" />
9/// <reference path="../typings/command-line-args.d.ts" />
10
11import 'source-map-support/register';
12import * as fs from 'fs';
13import * as path from 'path';
14import * as child_process from 'child_process';
15import * as request from 'request';
16import * as commandLineArgs from 'command-line-args';
17import { introspectionQuery, buildClientSchema } from 'graphql/utilities';
18import { GraphQLSchema } from 'graphql/type';
19import { queryToElm } from './query-to-elm';
20
21// entry point
22
23let optionDefinitions = [
24 { name: 'init', type: Boolean },
25 { name: 'endpoint', type: String, defaultOption: true },
26 { name: 'schema', type: String },
27 { name: 'method', type: String },
28 { name: 'help', type: Boolean },
29];
30
31let options: any = commandLineArgs(optionDefinitions);
32console.log(options);
33
34// usage
35if (options.help) {
36 usage();
37 process.exit(1);
38}
39
40if (!options.endpoint) {
41 console.error('Need endpointURL');
42 process.exit(1);
43}
44
45// output config
46let verb = 'GET';
47let endpointUrl = options.endpoint;
48
49performIntrospectionQuery(body => {
50 let result = JSON.parse(body);
51 let schema = buildClientSchema(result.data);
52 processFiles(schema);
53});
54
55function performIntrospectionQuery(callback: (body: string) => void) {
56 // introspection query
57 let introspectionUrl = options.endpoint;
58 if (!introspectionUrl) {
59 console.log('Error: missing graphql endpoint in elm-package.json');
60 process.exit(1);
61 }
62
63 let method = 'GET';
64 let reqOpts = method == 'GET'
65 ? { url: introspectionUrl,
66 method,
67 qs: {
68 query: introspectionQuery.replace(/\n/g, '').replace(/\s+/g, ' ')
69 }
70 }
71 : { url: introspectionUrl,
72 method,
73 headers: [{ 'Content-Type': 'application/json' }],
74 body: JSON.stringify({ query: introspectionQuery })
75 };
76
77 request(reqOpts, function (err, res, body) {
78 if (err) {
79 throw new Error(err);
80 } else if (res.statusCode == 200) {
81 callback(body);
82 } else {
83 console.error('Error', res.statusCode, '-', res.statusMessage);
84 console.error('\n', res.headers);
85 console.error('\n', body.trim());
86 console.error('\nThe GraphQL server at ' + introspectionUrl + ' responded with an error.');
87 process.exit(1);
88 }
89 });
90}
91
92function capitalize(str: string) {
93 return str[0].toUpperCase() + str.substr(1);
94}
95
96function processFiles(schema: GraphQLSchema) {
97 let paths = scanDir('.', []);
98
99 for (let filePath of paths) {
100 let fullpath = path.join(...filePath);
101 let graphql = fs.readFileSync(fullpath, 'utf8');
102 let rootindex = fullpath.indexOf("src/elm/");
103 let rootpath = fullpath.substr(rootindex + 8);
104 let pathdirs = rootpath.split('/');
105 let filepath = pathdirs.map(capitalize).join('.');
106 let basename = path.basename(fullpath);
107 let extname = path.extname(fullpath);
108 let filename = basename.substr(0, basename.length - extname.length);
109 let moduleName = filepath.substr(0, filepath.length - extname.length);
110
111 let outPath = path.join(path.dirname(fullpath), filename + '.elm');
112
113 let elm = queryToElm(graphql, moduleName, endpointUrl, verb, schema);
114 fs.writeFileSync(outPath, elm);
115
116 // if elm-format is available then run it on the output
117 try {
118 child_process.execSync('elm-format "' + outPath + '" --yes');
119 } catch (e) {
120 // ignore
121 }
122 }
123
124 let plural = paths.length != 1 ? 's' : '';
125 console.log('Success! Generated ' + paths.length + ' module' + plural + '.')
126}
127
128function scanDir(dirpath: string, parts: Array<string>): Array<Array<string>> {
129 let filenames = fs.readdirSync(dirpath);
130 let found: Array<Array<string>> = [];
131 for (let filename of filenames) {
132 let fullPath = path.join(dirpath, filename);
133 if (fs.statSync(fullPath).isDirectory() && filename[0] != '.') {
134 found = found.concat(scanDir(fullPath, parts.concat([filename])));
135 } else {
136 if (path.extname(filename) == '.graphql') {
137 found.push(parts.concat(filename));
138 }
139 }
140 }
141 return found;
142}
143
144function usage() {
145 let version = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json'), 'utf8')).version;
146 console.error('elm-graphql ' + version);
147 console.error();
148 console.error('Usage: elm graphql --init ENDPOINT-URL');
149 console.error(' ');
150 console.error('Available options:');
151 console.error(' --schema URL URL of the schema endpoint, if different.');
152}