1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 | import 'source-map-support/register';
|
12 | import * as fs from 'fs';
|
13 | import * as path from 'path';
|
14 | import * as child_process from 'child_process';
|
15 | import * as request from 'request';
|
16 | import * as commandLineArgs from 'command-line-args';
|
17 | import { introspectionQuery, buildClientSchema } from 'graphql/utilities';
|
18 | import { GraphQLSchema } from 'graphql/type';
|
19 | import { queryToElm } from './query-to-elm';
|
20 |
|
21 |
|
22 |
|
23 | let 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 |
|
31 | let options: any = commandLineArgs(optionDefinitions);
|
32 | console.log(options);
|
33 |
|
34 |
|
35 | if (options.help) {
|
36 | usage();
|
37 | process.exit(1);
|
38 | }
|
39 |
|
40 | if (!options.endpoint) {
|
41 | console.error('Need endpointURL');
|
42 | process.exit(1);
|
43 | }
|
44 |
|
45 |
|
46 | let verb = 'GET';
|
47 | let endpointUrl = options.endpoint;
|
48 |
|
49 | performIntrospectionQuery(body => {
|
50 | let result = JSON.parse(body);
|
51 | let schema = buildClientSchema(result.data);
|
52 | processFiles(schema);
|
53 | });
|
54 |
|
55 | function performIntrospectionQuery(callback: (body: string) => void) {
|
56 |
|
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 |
|
92 | function capitalize(str: string) {
|
93 | return str[0].toUpperCase() + str.substr(1);
|
94 | }
|
95 |
|
96 | function 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 |
|
117 | try {
|
118 | child_process.execSync('elm-format "' + outPath + '" --yes');
|
119 | } catch (e) {
|
120 |
|
121 | }
|
122 | }
|
123 |
|
124 | let plural = paths.length != 1 ? 's' : '';
|
125 | console.log('Success! Generated ' + paths.length + ' module' + plural + '.')
|
126 | }
|
127 |
|
128 | function 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 |
|
144 | function 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 | }
|