1 | import { Command } from 'commander';
|
2 | import { existsSync, readFileSync } from 'fs';
|
3 | import { join } from 'path';
|
4 | import { cliError } from './utils/cli-error';
|
5 | import YAML from 'json-to-pretty-yaml';
|
6 | import { isNode } from './utils/is-browser';
|
7 | function collect(val, memo) {
|
8 | memo.push(val);
|
9 | return memo;
|
10 | }
|
11 | export const initCLI = (args) => {
|
12 | const command = new Command()
|
13 | .usage('gql-gen [options]')
|
14 | .option('-s, --schema <path>', 'Path to GraphQL schema: local JSON file, GraphQL endpoint, local file that exports GraphQLSchema/AST/JSON')
|
15 | .option('-cs, --clientSchema <path>', 'Path to GraphQL client schema: local JSON file, local file that exports GraphQLSchema/AST/JSON')
|
16 | .option('-h, --header [header]', 'Header to add to the introspection HTTP request when using --url/--schema with url', collect, [])
|
17 | .option('-t, --template <template-name>', 'Language/platform name templates, or a name of NPM modules that `export default` GqlGenConfig object')
|
18 | .option('-p, --project <project-path>', 'Project path(s) to scan for custom template files')
|
19 | .option('--config <json-file>', 'Codegen configuration file, defaults to: ./gql-gen.json')
|
20 | .option('-m, --skip-schema', 'Generates only client side documents, without server side schema types')
|
21 | .option('-c, --skip-documents', 'Generates only server side schema types, without client side documents')
|
22 | .option('-o, --out <path>', 'Output file(s) path', String, './')
|
23 | .option('-r, --require [require]', 'module to preload (option can be repeated)', collect, [])
|
24 | .option('-ow, --no-overwrite', 'Skip file writing if the output file(s) already exists in path')
|
25 | .option('-w, --watch', 'Watch for changes and execute generation automatically')
|
26 | .option('--silent', 'Does not print anything to the console')
|
27 | .option('-ms, --merge-schema <merge-logic>', 'Merge schemas with custom logic')
|
28 | .arguments('<options> [documents...]')
|
29 | .parse(args);
|
30 | return command;
|
31 | };
|
32 | export const validateCliOptions = (options) => {
|
33 | const schema = options.schema;
|
34 | const template = options.template;
|
35 | const project = options.project;
|
36 | if (!schema && isNode) {
|
37 | const { getGraphQLProjectConfig, ConfigNotFoundError } = require('graphql-config');
|
38 | try {
|
39 | const graphqlProjectConfig = getGraphQLProjectConfig(project);
|
40 | options.schema = graphqlProjectConfig.schemaPath;
|
41 | }
|
42 | catch (e) {
|
43 | if (e instanceof ConfigNotFoundError) {
|
44 | cliError('Flag --schema is missing!');
|
45 | }
|
46 | }
|
47 | }
|
48 | if (!template && !project) {
|
49 | cliError('Please specify language/platform, using --template flag!');
|
50 | }
|
51 | };
|
52 | function transformTemplatesToPlugins(options, templateSpecificConfig = {}) {
|
53 | if (options.template === 'ts' ||
|
54 | options.template === 'typescript' ||
|
55 | options.template === 'graphql-codegen-typescript-template') {
|
56 | return {
|
57 | config: templateSpecificConfig,
|
58 | plugins: [
|
59 | templateSpecificConfig.printTime ? 'time' : null,
|
60 | 'typescript-common',
|
61 | options.skipDocuments ? null : 'typescript-client',
|
62 | options.skipSchema ? null : 'typescript-server'
|
63 | ].filter(s => s)
|
64 | };
|
65 | }
|
66 | else if (options.template === 'typescript-resolvers' ||
|
67 | options.template === 'graphql-codegen-typescript-resolvers-template') {
|
68 | return {
|
69 | config: templateSpecificConfig,
|
70 | plugins: [templateSpecificConfig.printTime ? 'time' : null, 'typescript-common', 'typescript-resolvers'].filter(s => s)
|
71 | };
|
72 | }
|
73 | else if (options.template === 'typescript-mongodb' ||
|
74 | options.template === 'graphql-codegen-typescript-mongodb-template') {
|
75 | return {
|
76 | config: templateSpecificConfig,
|
77 | plugins: [
|
78 | templateSpecificConfig.printTime ? 'time' : null,
|
79 | 'typescript-common',
|
80 | 'typescript-server',
|
81 | 'typescript-mongodb'
|
82 | ].filter(s => s)
|
83 | };
|
84 | }
|
85 | else if (options.template === 'apollo-angular' || options.template === 'graphql-codegen-apollo-angular-template') {
|
86 | return {
|
87 | config: templateSpecificConfig,
|
88 | plugins: [
|
89 | templateSpecificConfig.printTime ? 'time' : null,
|
90 | 'typescript-common',
|
91 | 'typescript-client',
|
92 | 'typescript-apollo-angular'
|
93 | ].filter(s => s)
|
94 | };
|
95 | }
|
96 | else if (options.template === 'react-apollo' ||
|
97 | options.template === 'graphql-codegen-typescript-react-apollo-template') {
|
98 | return {
|
99 | config: templateSpecificConfig,
|
100 | plugins: [
|
101 | templateSpecificConfig.printTime ? 'time' : null,
|
102 | 'typescript-common',
|
103 | 'typescript-client',
|
104 | 'typescript-react-apollo'
|
105 | ].filter(s => s)
|
106 | };
|
107 | }
|
108 | else if (options.template === 'introspection' || options.template === 'graphql-codegen-introspection-template') {
|
109 | return {
|
110 | config: templateSpecificConfig,
|
111 | plugins: ['introspection'].filter(s => s)
|
112 | };
|
113 | }
|
114 | else if (options.template === 'graphql-files-typescript' ||
|
115 | options.template === 'graphql-codegen-graphql-files-typescript-modules') {
|
116 | return {
|
117 | config: templateSpecificConfig,
|
118 | plugins: ['typescript-graphql-files-modules'].filter(s => s)
|
119 | };
|
120 | }
|
121 | return { plugins: [options.template].filter(a => a) };
|
122 | }
|
123 | function getConfigFromEnvVars() {
|
124 | return Object.keys(process.env)
|
125 | .filter(name => name.startsWith('CODEGEN_'))
|
126 | .reduce((prev, name) => {
|
127 | const cleanName = name
|
128 | .replace('CODEGEN_', '')
|
129 | .toLowerCase()
|
130 | .replace(/[-_]+/g, ' ')
|
131 | .replace(/[^\w\s]/g, '')
|
132 | .replace(/ (.)/g, res => res.toUpperCase())
|
133 | .replace(/ /g, '');
|
134 | let value = process.env[name];
|
135 | if (value === 'true') {
|
136 | value = true;
|
137 | }
|
138 | else if (value === 'false') {
|
139 | value = false;
|
140 | }
|
141 | prev[cleanName] = value;
|
142 | return prev;
|
143 | }, {});
|
144 | }
|
145 | export function createConfigFromOldCli(options) {
|
146 | validateCliOptions(options);
|
147 | let rootConfig = {};
|
148 | const configPath = options.config ? options.config : existsSync(join(process.cwd(), './gql-gen.json'));
|
149 | if (configPath && typeof configPath === 'string') {
|
150 | const rawObj = JSON.parse(readFileSync(configPath, 'utf-8'));
|
151 | rootConfig = (rawObj || {}).generatorConfig || {};
|
152 | }
|
153 | const envVarsConfig = getConfigFromEnvVars();
|
154 | rootConfig = Object.assign({}, rootConfig, envVarsConfig);
|
155 | let schema = options.schema;
|
156 | if (options.header && Array.isArray(options.header) && options.header.length > 0) {
|
157 | schema = {
|
158 | [options.schema]: {
|
159 | headers: options.header.reduce((prev, h) => {
|
160 | const splitted = h.split(':').map(p => p.trim());
|
161 | const name = splitted[0];
|
162 | const value = splitted[1];
|
163 | return Object.assign({}, prev, { [name]: value });
|
164 | }, {})
|
165 | }
|
166 | };
|
167 | }
|
168 | const configObject = {
|
169 | schema: [schema, options.clientSchema].filter(s => s),
|
170 | documents: options.args || [],
|
171 | config: rootConfig,
|
172 | generates: {
|
173 | [options.out]: transformTemplatesToPlugins(options, Object.assign({}, rootConfig, (options.templateConfig || {})))
|
174 | },
|
175 | silent: options.silent,
|
176 | watch: options.watch,
|
177 | require: options.require
|
178 | };
|
179 | console['warn'](`
|
180 | Note: You are using the old API of graphql-code-generator. You can easily migrate by creating "codegen.yml" file in your project with the following content:
|
181 |
|
182 | ${YAML.stringify(configObject)}
|
183 |
|
184 | Then, make sure that your script is executing just "gql-gen" (without any cli flags).
|
185 | `);
|
186 | return configObject;
|
187 | }
|
188 |
|
\ | No newline at end of file |