@graphql-codegen/cli 2.7.0-alpha-8791d9688.0 → 2.8.0-alpha-4fa8b9f18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/cjs/bin.js +13 -0
  2. package/cjs/cli.js +60 -0
  3. package/cjs/codegen.js +332 -0
  4. package/cjs/config.js +303 -0
  5. package/cjs/generate-and-save.js +110 -0
  6. package/cjs/graphql-config.js +69 -0
  7. package/cjs/hooks.js +87 -0
  8. package/cjs/index.js +13 -0
  9. package/cjs/init/helpers.js +64 -0
  10. package/cjs/init/index.js +60 -0
  11. package/cjs/init/plugins.js +163 -0
  12. package/cjs/init/questions.js +147 -0
  13. package/cjs/init/targets.js +44 -0
  14. package/cjs/init/types.js +14 -0
  15. package/cjs/load.js +93 -0
  16. package/cjs/package.json +1 -0
  17. package/cjs/plugins.js +45 -0
  18. package/cjs/presets.js +46 -0
  19. package/cjs/utils/cli-error.js +25 -0
  20. package/cjs/utils/debugging.js +27 -0
  21. package/cjs/utils/file-system.js +26 -0
  22. package/cjs/utils/indentString.js +37 -0
  23. package/cjs/utils/listr-renderer.js +136 -0
  24. package/cjs/utils/logger.js +25 -0
  25. package/cjs/utils/watcher.js +140 -0
  26. package/esm/bin.js +11 -0
  27. package/esm/cli.js +32 -0
  28. package/esm/codegen.js +327 -0
  29. package/esm/config.js +290 -0
  30. package/esm/generate-and-save.js +105 -0
  31. package/esm/graphql-config.js +64 -0
  32. package/esm/hooks.js +83 -0
  33. package/esm/index.js +7 -0
  34. package/esm/init/helpers.js +55 -0
  35. package/esm/init/index.js +55 -0
  36. package/esm/init/plugins.js +160 -0
  37. package/esm/init/questions.js +140 -0
  38. package/esm/init/targets.js +40 -0
  39. package/esm/init/types.js +11 -0
  40. package/esm/load.js +88 -0
  41. package/esm/plugins.js +41 -0
  42. package/esm/presets.js +42 -0
  43. package/esm/utils/cli-error.js +20 -0
  44. package/esm/utils/debugging.js +21 -0
  45. package/esm/utils/file-system.js +19 -0
  46. package/esm/utils/indentString.js +33 -0
  47. package/esm/utils/listr-renderer.js +130 -0
  48. package/esm/utils/logger.js +18 -0
  49. package/esm/utils/watcher.js +135 -0
  50. package/package.json +34 -26
  51. package/typings/bin.d.ts +2 -0
  52. package/{cli.d.ts → typings/cli.d.ts} +0 -0
  53. package/{codegen.d.ts → typings/codegen.d.ts} +1 -1
  54. package/{config.d.ts → typings/config.d.ts} +0 -0
  55. package/{generate-and-save.d.ts → typings/generate-and-save.d.ts} +1 -1
  56. package/{graphql-config.d.ts → typings/graphql-config.d.ts} +0 -0
  57. package/{hooks.d.ts → typings/hooks.d.ts} +0 -0
  58. package/typings/index.d.ts +7 -0
  59. package/{init → typings/init}/helpers.d.ts +1 -1
  60. package/{init → typings/init}/index.d.ts +0 -0
  61. package/{init → typings/init}/plugins.d.ts +1 -1
  62. package/{init → typings/init}/questions.d.ts +1 -1
  63. package/{init → typings/init}/targets.d.ts +1 -1
  64. package/{init → typings/init}/types.d.ts +0 -0
  65. package/{load.d.ts → typings/load.d.ts} +0 -0
  66. package/{plugins.d.ts → typings/plugins.d.ts} +0 -0
  67. package/{presets.d.ts → typings/presets.d.ts} +0 -0
  68. package/{utils → typings/utils}/cli-error.d.ts +0 -0
  69. package/{utils → typings/utils}/debugging.d.ts +0 -0
  70. package/{utils → typings/utils}/file-system.d.ts +0 -0
  71. package/{utils → typings/utils}/indentString.d.ts +0 -0
  72. package/{utils → typings/utils}/listr-renderer.d.ts +0 -0
  73. package/{utils → typings/utils}/logger.d.ts +0 -0
  74. package/{utils → typings/utils}/watcher.d.ts +1 -1
  75. package/bin.d.ts +0 -1
  76. package/bin.js +0 -1888
  77. package/index.d.ts +0 -7
  78. package/index.js +0 -1899
  79. package/index.mjs +0 -1855
  80. package/utils/try-to-build-schema.d.ts +0 -2
package/bin.js DELETED
@@ -1,1888 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
5
-
6
- function _interopNamespace(e) {
7
- if (e && e.__esModule) { return e; } else {
8
- var n = {};
9
- if (e) {
10
- Object.keys(e).forEach(function (k) {
11
- var d = Object.getOwnPropertyDescriptor(e, k);
12
- Object.defineProperty(n, k, d.get ? d : {
13
- enumerable: true,
14
- get: function () {
15
- return e[k];
16
- }
17
- });
18
- });
19
- }
20
- n['default'] = e;
21
- return n;
22
- }
23
- }
24
-
25
- const tsLog = require('ts-log');
26
- const child_process = require('child_process');
27
- const path = require('path');
28
- const path__default = _interopDefault(path);
29
- const pluginHelpers = require('@graphql-codegen/plugin-helpers');
30
- const core = require('@graphql-codegen/core');
31
- const utils = require('@graphql-tools/utils');
32
- const chalk = _interopDefault(require('chalk'));
33
- const logSymbols = _interopDefault(require('log-symbols'));
34
- const ansiEscapes = _interopDefault(require('ansi-escapes'));
35
- const wrapAnsi = _interopDefault(require('wrap-ansi'));
36
- const commonTags = require('common-tags');
37
- const UpdateRenderer = _interopDefault(require('listr-update-renderer'));
38
- const graphql = require('graphql');
39
- const cosmiconfig = require('cosmiconfig');
40
- const stringEnvInterpolation = require('string-env-interpolation');
41
- const yargs = _interopDefault(require('yargs'));
42
- const graphqlConfig = require('graphql-config');
43
- const apolloEngineLoader = require('@graphql-tools/apollo-engine-loader');
44
- const codeFileLoader = require('@graphql-tools/code-file-loader');
45
- const gitLoader = require('@graphql-tools/git-loader');
46
- const githubLoader = require('@graphql-tools/github-loader');
47
- const prismaLoader = require('@graphql-tools/prisma-loader');
48
- const load = require('@graphql-tools/load');
49
- const graphqlFileLoader = require('@graphql-tools/graphql-file-loader');
50
- const jsonFileLoader = require('@graphql-tools/json-file-loader');
51
- const urlLoader = require('@graphql-tools/url-loader');
52
- const yaml = _interopDefault(require('yaml'));
53
- const module$1 = require('module');
54
- const fs = require('fs');
55
- const fs__default = _interopDefault(fs);
56
- const crypto = require('crypto');
57
- const os = require('os');
58
- const Listr = _interopDefault(require('listr'));
59
- const isGlob = _interopDefault(require('is-glob'));
60
- const debounce = _interopDefault(require('debounce'));
61
- const mkdirp = _interopDefault(require('mkdirp'));
62
- const inquirer = _interopDefault(require('inquirer'));
63
- const detectIndent = _interopDefault(require('detect-indent'));
64
- const getLatestVersion = _interopDefault(require('latest-version'));
65
-
66
- let logger;
67
- function getLogger() {
68
- return logger || tsLog.dummyLogger;
69
- }
70
- useWinstonLogger();
71
- function useWinstonLogger() {
72
- if (logger && logger.levels) {
73
- return;
74
- }
75
- logger = console;
76
- }
77
-
78
- let queue = [];
79
- function debugLog(message, ...meta) {
80
- if (!process.env.GQL_CODEGEN_NODEBUG && process.env.DEBUG !== undefined) {
81
- queue.push({
82
- message,
83
- meta,
84
- });
85
- }
86
- }
87
- function printLogs() {
88
- if (!process.env.GQL_CODEGEN_NODEBUG && process.env.DEBUG !== undefined) {
89
- queue.forEach(log => {
90
- getLogger().info(log.message, ...log.meta);
91
- });
92
- resetLogs();
93
- }
94
- }
95
- function resetLogs() {
96
- queue = [];
97
- }
98
-
99
- const DEFAULT_HOOKS = {
100
- afterStart: [],
101
- beforeDone: [],
102
- onWatchTriggered: [],
103
- onError: [],
104
- afterOneFileWrite: [],
105
- afterAllFileWrite: [],
106
- beforeOneFileWrite: [],
107
- beforeAllFileWrite: [],
108
- };
109
- function normalizeHooks(_hooks) {
110
- const keys = Object.keys({
111
- ...DEFAULT_HOOKS,
112
- ..._hooks,
113
- });
114
- return keys.reduce((prev, hookName) => {
115
- if (typeof _hooks[hookName] === 'string') {
116
- return {
117
- ...prev,
118
- [hookName]: [_hooks[hookName]],
119
- };
120
- }
121
- if (typeof _hooks[hookName] === 'function') {
122
- return {
123
- ...prev,
124
- [hookName]: [_hooks[hookName]],
125
- };
126
- }
127
- if (Array.isArray(_hooks[hookName])) {
128
- return {
129
- ...prev,
130
- [hookName]: _hooks[hookName],
131
- };
132
- }
133
- return prev;
134
- }, {});
135
- }
136
- function execShellCommand(cmd) {
137
- return new Promise((resolve, reject) => {
138
- child_process.exec(cmd, {
139
- env: {
140
- ...process.env,
141
- PATH: `${process.env.PATH}${path.delimiter}${process.cwd()}${path.sep}node_modules${path.sep}.bin`,
142
- },
143
- }, (error, stdout, stderr) => {
144
- if (error) {
145
- reject(error);
146
- }
147
- else {
148
- resolve(stdout || stderr);
149
- }
150
- });
151
- });
152
- }
153
- async function executeHooks(hookName, scripts = [], args = []) {
154
- debugLog(`Running lifecycle hook "${hookName}" scripts...`);
155
- for (const script of scripts) {
156
- if (typeof script === 'string') {
157
- debugLog(`Running lifecycle hook "${hookName}" script: ${script} with args: ${args.join(' ')}...`);
158
- await execShellCommand(`${script} ${args.join(' ')}`);
159
- }
160
- else {
161
- debugLog(`Running lifecycle hook "${hookName}" script: ${script.name} with args: ${args.join(' ')}...`);
162
- await script(...args);
163
- }
164
- }
165
- }
166
- const lifecycleHooks = (_hooks = {}) => {
167
- const hooks = normalizeHooks(_hooks);
168
- return {
169
- afterStart: async () => executeHooks('afterStart', hooks.afterStart),
170
- onWatchTriggered: async (event, path) => executeHooks('onWatchTriggered', hooks.onWatchTriggered, [event, path]),
171
- onError: async (error) => executeHooks('onError', hooks.onError, [`"${error}"`]),
172
- afterOneFileWrite: async (path) => executeHooks('afterOneFileWrite', hooks.afterOneFileWrite, [path]),
173
- afterAllFileWrite: async (paths) => executeHooks('afterAllFileWrite', hooks.afterAllFileWrite, paths),
174
- beforeOneFileWrite: async (path) => executeHooks('beforeOneFileWrite', hooks.beforeOneFileWrite, [path]),
175
- beforeAllFileWrite: async (paths) => executeHooks('beforeAllFileWrite', hooks.beforeAllFileWrite, paths),
176
- beforeDone: async () => executeHooks('beforeDone', hooks.beforeDone),
177
- };
178
- };
179
-
180
- /**
181
- Indent each line in a string.
182
- @param string - The string to indent.
183
- @param count - How many times you want `options.indent` repeated. Default: `1`.
184
- @example
185
- ```
186
- import indentString from 'indent-string';
187
- indentString('Unicorns\nRainbows', 4);
188
- //=> ' Unicorns\n Rainbows'
189
- indentString('Unicorns\nRainbows', 4, {indent: '♥'});
190
- //=> '♥♥♥♥Unicorns\n♥♥♥♥Rainbows'
191
- ```
192
- */
193
- function indentString(string, count = 1, options = {}) {
194
- const { indent = ' ', includeEmptyLines = false } = options;
195
- if (typeof string !== 'string') {
196
- throw new TypeError(`Expected \`input\` to be a \`string\`, got \`${typeof string}\``);
197
- }
198
- if (typeof count !== 'number') {
199
- throw new TypeError(`Expected \`count\` to be a \`number\`, got \`${typeof count}\``);
200
- }
201
- if (count < 0) {
202
- throw new RangeError(`Expected \`count\` to be at least 0, got \`${count}\``);
203
- }
204
- if (typeof indent !== 'string') {
205
- throw new TypeError(`Expected \`options.indent\` to be a \`string\`, got \`${typeof indent}\``);
206
- }
207
- if (count === 0) {
208
- return string;
209
- }
210
- const regex = includeEmptyLines ? /^/gm : /^(?!\s*$)/gm;
211
- return string.replace(regex, indent.repeat(count));
212
- }
213
-
214
- class Renderer {
215
- constructor(tasks, options) {
216
- this.updateRenderer = new UpdateRenderer(tasks, options);
217
- }
218
- render() {
219
- return this.updateRenderer.render();
220
- }
221
- end(err) {
222
- this.updateRenderer.end(err);
223
- if (typeof err === 'undefined') {
224
- logUpdate.clear();
225
- return;
226
- }
227
- // persist the output
228
- logUpdate.done();
229
- // show errors
230
- if (err) {
231
- const errorCount = err.errors ? err.errors.length : 0;
232
- if (errorCount > 0) {
233
- const count = indentString(chalk.red.bold(`Found ${errorCount} error${errorCount > 1 ? 's' : ''}`), 1);
234
- const details = err.errors
235
- .map(error => {
236
- debugLog(`[CLI] Exited with an error`, error);
237
- return { msg: pluginHelpers.isDetailedError(error) ? error.details : null, rawError: error };
238
- })
239
- .map(({ msg, rawError }, i) => {
240
- const source = err.errors[i].source;
241
- msg = msg ? chalk.gray(indentString(commonTags.stripIndent(`${msg}`), 4)) : null;
242
- const stack = rawError.stack ? chalk.gray(indentString(commonTags.stripIndent(rawError.stack), 4)) : null;
243
- if (source) {
244
- const sourceOfError = typeof source === 'string' ? source : source.name;
245
- const title = indentString(`${logSymbols.error} ${sourceOfError}`, 2);
246
- return [title, msg, stack, stack].filter(Boolean).join('\n');
247
- }
248
- return [msg, stack].filter(Boolean).join('\n');
249
- })
250
- .join('\n\n');
251
- logUpdate.emit(['', count, details, ''].join('\n\n'));
252
- }
253
- else {
254
- const details = err.details ? err.details : '';
255
- logUpdate.emit(`${chalk.red.bold(`${indentString(err.message, 2)}`)}\n${details}\n${chalk.grey(err.stack)}`);
256
- }
257
- }
258
- logUpdate.done();
259
- printLogs();
260
- }
261
- }
262
- const render = tasks => {
263
- for (const task of tasks) {
264
- task.subscribe(event => {
265
- if (event.type === 'SUBTASKS') {
266
- render(task.subtasks);
267
- return;
268
- }
269
- if (event.type === 'DATA') {
270
- logUpdate.emit(chalk.dim(`${event.data}`));
271
- }
272
- logUpdate.done();
273
- }, err => {
274
- logUpdate.emit(err);
275
- logUpdate.done();
276
- });
277
- }
278
- };
279
- class ErrorRenderer {
280
- constructor(tasks, _options) {
281
- this.tasks = tasks;
282
- }
283
- render() {
284
- render(this.tasks);
285
- }
286
- static get nonTTY() {
287
- return true;
288
- }
289
- end() { }
290
- }
291
- class LogUpdate {
292
- constructor() {
293
- this.stream = process.stdout;
294
- // state
295
- this.previousLineCount = 0;
296
- this.previousOutput = '';
297
- this.previousWidth = this.getWidth();
298
- }
299
- emit(...args) {
300
- let output = args.join(' ') + '\n';
301
- const width = this.getWidth();
302
- if (output === this.previousOutput && this.previousWidth === width) {
303
- return;
304
- }
305
- this.previousOutput = output;
306
- this.previousWidth = width;
307
- output = wrapAnsi(output, width, {
308
- trim: false,
309
- hard: true,
310
- wordWrap: false,
311
- });
312
- this.stream.write(ansiEscapes.eraseLines(this.previousLineCount) + output);
313
- this.previousLineCount = output.split('\n').length;
314
- }
315
- clear() {
316
- this.stream.write(ansiEscapes.eraseLines(this.previousLineCount));
317
- this.previousOutput = '';
318
- this.previousWidth = this.getWidth();
319
- this.previousLineCount = 0;
320
- }
321
- done() {
322
- this.previousOutput = '';
323
- this.previousWidth = this.getWidth();
324
- this.previousLineCount = 0;
325
- }
326
- getWidth() {
327
- const { columns } = this.stream;
328
- if (!columns) {
329
- return 80;
330
- }
331
- return columns;
332
- }
333
- }
334
- const logUpdate = new LogUpdate();
335
-
336
- async function getPluginByName(name, pluginLoader) {
337
- const possibleNames = [
338
- `@graphql-codegen/${name}`,
339
- `@graphql-codegen/${name}-template`,
340
- `@graphql-codegen/${name}-plugin`,
341
- `graphql-codegen-${name}`,
342
- `graphql-codegen-${name}-template`,
343
- `graphql-codegen-${name}-plugin`,
344
- `codegen-${name}`,
345
- `codegen-${name}-template`,
346
- name,
347
- ];
348
- const possibleModules = possibleNames.concat(path.resolve(process.cwd(), name));
349
- for (const moduleName of possibleModules) {
350
- try {
351
- return await pluginLoader(moduleName);
352
- }
353
- catch (err) {
354
- if (err.code !== 'MODULE_NOT_FOUND') {
355
- throw new pluginHelpers.DetailedError(`Unable to load template plugin matching ${name}`, `
356
- Unable to load template plugin matching '${name}'.
357
- Reason:
358
- ${err.message}
359
- `);
360
- }
361
- }
362
- }
363
- const possibleNamesMsg = possibleNames
364
- .map(name => `
365
- - ${name}
366
- `.trimRight())
367
- .join('');
368
- throw new pluginHelpers.DetailedError(`Unable to find template plugin matching ${name}`, `
369
- Unable to find template plugin matching '${name}'
370
- Install one of the following packages:
371
-
372
- ${possibleNamesMsg}
373
- `);
374
- }
375
-
376
- async function getPresetByName(name, loader) {
377
- const possibleNames = [
378
- `@graphql-codegen/${name}`,
379
- `@graphql-codegen/${name}-preset`,
380
- name,
381
- path.resolve(process.cwd(), name),
382
- ];
383
- for (const moduleName of possibleNames) {
384
- try {
385
- const loaded = await loader(moduleName);
386
- if (loaded && loaded.preset) {
387
- return loaded.preset;
388
- }
389
- if (loaded && loaded.default) {
390
- return loaded.default;
391
- }
392
- return loaded;
393
- }
394
- catch (err) {
395
- if (err.code !== 'MODULE_NOT_FOUND') {
396
- throw new pluginHelpers.DetailedError(`Unable to load preset matching ${name}`, `
397
- Unable to load preset matching '${name}'.
398
- Reason:
399
- ${err.message}
400
- `);
401
- }
402
- }
403
- }
404
- const possibleNamesMsg = possibleNames
405
- .map(name => `
406
- - ${name}
407
- `.trimRight())
408
- .join('');
409
- throw new pluginHelpers.DetailedError(`Unable to find preset matching ${name}`, `
410
- Unable to find preset matching '${name}'
411
- Install one of the following packages:
412
-
413
- ${possibleNamesMsg}
414
- `);
415
- }
416
-
417
- const CodegenExtension = (api) => {
418
- // Schema
419
- api.loaders.schema.register(new codeFileLoader.CodeFileLoader({
420
- pluckConfig: {
421
- skipIndent: true,
422
- },
423
- }));
424
- api.loaders.schema.register(new gitLoader.GitLoader());
425
- api.loaders.schema.register(new githubLoader.GithubLoader());
426
- api.loaders.schema.register(new apolloEngineLoader.ApolloEngineLoader());
427
- api.loaders.schema.register(new prismaLoader.PrismaLoader());
428
- // Documents
429
- api.loaders.documents.register(new codeFileLoader.CodeFileLoader({
430
- pluckConfig: {
431
- skipIndent: true,
432
- },
433
- }));
434
- api.loaders.documents.register(new gitLoader.GitLoader());
435
- api.loaders.documents.register(new githubLoader.GithubLoader());
436
- return {
437
- name: 'codegen',
438
- };
439
- };
440
- async function findAndLoadGraphQLConfig(filepath) {
441
- const config = await graphqlConfig.loadConfig({
442
- filepath,
443
- rootDir: process.cwd(),
444
- extensions: [CodegenExtension],
445
- throwOnEmpty: false,
446
- throwOnMissing: false,
447
- });
448
- if (isGraphQLConfig(config)) {
449
- return config;
450
- }
451
- }
452
- // Kamil: user might load a config that is not GraphQL Config
453
- // so we need to check if it's a regular config or not
454
- function isGraphQLConfig(config) {
455
- if (!config) {
456
- return false;
457
- }
458
- try {
459
- return config.getDefault().hasExtension('codegen');
460
- }
461
- catch (e) { }
462
- try {
463
- for (const projectName in config.projects) {
464
- if (config.projects.hasOwnProperty(projectName)) {
465
- const project = config.projects[projectName];
466
- if (project.hasExtension('codegen')) {
467
- return true;
468
- }
469
- }
470
- }
471
- }
472
- catch (e) { }
473
- return false;
474
- }
475
-
476
- const defaultSchemaLoadOptions = {
477
- assumeValidSDL: true,
478
- sort: true,
479
- convertExtensions: true,
480
- includeSources: true,
481
- };
482
- const defaultDocumentsLoadOptions = {
483
- sort: true,
484
- skipGraphQLImport: true,
485
- };
486
- async function loadSchema(schemaPointers, config) {
487
- try {
488
- const loaders = [
489
- new codeFileLoader.CodeFileLoader(),
490
- new gitLoader.GitLoader(),
491
- new githubLoader.GithubLoader(),
492
- new graphqlFileLoader.GraphQLFileLoader(),
493
- new jsonFileLoader.JsonFileLoader(),
494
- new urlLoader.UrlLoader(),
495
- new apolloEngineLoader.ApolloEngineLoader(),
496
- new prismaLoader.PrismaLoader(),
497
- ];
498
- const schema = await load.loadSchema(schemaPointers, {
499
- ...defaultSchemaLoadOptions,
500
- loaders,
501
- ...config,
502
- ...config.config,
503
- });
504
- return schema;
505
- }
506
- catch (e) {
507
- throw new pluginHelpers.DetailedError('Failed to load schema', `
508
- Failed to load schema from ${Object.keys(schemaPointers).join(',')}:
509
-
510
- ${e.message || e}
511
- ${e.stack || ''}
512
-
513
- GraphQL Code Generator supports:
514
- - ES Modules and CommonJS exports (export as default or named export "schema")
515
- - Introspection JSON File
516
- - URL of GraphQL endpoint
517
- - Multiple files with type definitions (glob expression)
518
- - String in config file
519
-
520
- Try to use one of above options and run codegen again.
521
-
522
- `);
523
- }
524
- }
525
- async function loadDocuments(documentPointers, config) {
526
- const loaders = [
527
- new codeFileLoader.CodeFileLoader({
528
- pluckConfig: {
529
- skipIndent: true,
530
- },
531
- }),
532
- new gitLoader.GitLoader(),
533
- new githubLoader.GithubLoader(),
534
- new graphqlFileLoader.GraphQLFileLoader(),
535
- ];
536
- const ignore = [];
537
- for (const generatePath of Object.keys(config.generates)) {
538
- if (path.extname(generatePath) === '') {
539
- // we omit paths that don't resolve to a specific file
540
- continue;
541
- }
542
- ignore.push(path.join(process.cwd(), generatePath));
543
- }
544
- const loadedFromToolkit = await load.loadDocuments(documentPointers, {
545
- ...defaultDocumentsLoadOptions,
546
- ignore,
547
- loaders,
548
- ...config,
549
- ...config.config,
550
- });
551
- return loadedFromToolkit;
552
- }
553
-
554
- const { lstat } = fs.promises;
555
- function generateSearchPlaces(moduleName) {
556
- const extensions = ['json', 'yaml', 'yml', 'js', 'config.js'];
557
- // gives codegen.json...
558
- const regular = extensions.map(ext => `${moduleName}.${ext}`);
559
- // gives .codegenrc.json... but no .codegenrc.config.js
560
- const dot = extensions.filter(ext => ext !== 'config.js').map(ext => `.${moduleName}rc.${ext}`);
561
- return [...regular.concat(dot), 'package.json'];
562
- }
563
- function customLoader(ext) {
564
- function loader(filepath, content) {
565
- if (typeof process !== 'undefined' && 'env' in process) {
566
- content = stringEnvInterpolation.env(content);
567
- }
568
- if (ext === 'json') {
569
- return cosmiconfig.defaultLoaders['.json'](filepath, content);
570
- }
571
- if (ext === 'yaml') {
572
- try {
573
- const result = yaml.parse(content, { prettyErrors: true, merge: true });
574
- return result;
575
- }
576
- catch (error) {
577
- error.message = `YAML Error in ${filepath}:\n${error.message}`;
578
- throw error;
579
- }
580
- }
581
- if (ext === 'js') {
582
- return cosmiconfig.defaultLoaders['.js'](filepath, content);
583
- }
584
- }
585
- return loader;
586
- }
587
- async function loadCodegenConfig({ configFilePath, moduleName, searchPlaces: additionalSearchPlaces, packageProp, loaders: customLoaders, }) {
588
- configFilePath = configFilePath || process.cwd();
589
- moduleName = moduleName || 'codegen';
590
- packageProp = packageProp || moduleName;
591
- const cosmi = cosmiconfig.cosmiconfig(moduleName, {
592
- searchPlaces: generateSearchPlaces(moduleName).concat(additionalSearchPlaces || []),
593
- packageProp,
594
- loaders: {
595
- '.json': customLoader('json'),
596
- '.yaml': customLoader('yaml'),
597
- '.yml': customLoader('yaml'),
598
- '.js': customLoader('js'),
599
- noExt: customLoader('yaml'),
600
- ...customLoaders,
601
- },
602
- });
603
- const pathStats = await lstat(configFilePath);
604
- return pathStats.isDirectory() ? cosmi.search(configFilePath) : cosmi.load(configFilePath);
605
- }
606
- async function loadContext(configFilePath) {
607
- const graphqlConfig = await findAndLoadGraphQLConfig(configFilePath);
608
- if (graphqlConfig) {
609
- return new CodegenContext({
610
- graphqlConfig,
611
- });
612
- }
613
- const result = await loadCodegenConfig({ configFilePath });
614
- if (!result) {
615
- if (configFilePath) {
616
- throw new pluginHelpers.DetailedError(`Config ${configFilePath} does not exist`, `
617
- Config ${configFilePath} does not exist.
618
-
619
- $ graphql-codegen --config ${configFilePath}
620
-
621
- Please make sure the --config points to a correct file.
622
- `);
623
- }
624
- throw new pluginHelpers.DetailedError(`Unable to find Codegen config file!`, `
625
- Please make sure that you have a configuration file under the current directory!
626
- `);
627
- }
628
- if (result.isEmpty) {
629
- throw new pluginHelpers.DetailedError(`Found Codegen config file but it was empty!`, `
630
- Please make sure that you have a valid configuration file under the current directory!
631
- `);
632
- }
633
- return new CodegenContext({
634
- filepath: result.filepath,
635
- config: result.config,
636
- });
637
- }
638
- function getCustomConfigPath(cliFlags) {
639
- const configFile = cliFlags.config;
640
- return configFile ? path.resolve(process.cwd(), configFile) : null;
641
- }
642
- function buildOptions() {
643
- return {
644
- c: {
645
- alias: 'config',
646
- type: 'string',
647
- describe: 'Path to GraphQL codegen YAML config file, defaults to "codegen.yml" on the current directory',
648
- },
649
- w: {
650
- alias: 'watch',
651
- describe: 'Watch for changes and execute generation automatically. You can also specify a glob expreession for custom watch list.',
652
- coerce: (watch) => {
653
- if (watch === 'false') {
654
- return false;
655
- }
656
- if (typeof watch === 'string' || Array.isArray(watch)) {
657
- return watch;
658
- }
659
- return !!watch;
660
- },
661
- },
662
- r: {
663
- alias: 'require',
664
- describe: 'Loads specific require.extensions before running the codegen and reading the configuration',
665
- type: 'array',
666
- default: [],
667
- },
668
- o: {
669
- alias: 'overwrite',
670
- describe: 'Overwrites existing files',
671
- type: 'boolean',
672
- },
673
- s: {
674
- alias: 'silent',
675
- describe: 'Suppresses printing errors',
676
- type: 'boolean',
677
- },
678
- e: {
679
- alias: 'errors-only',
680
- describe: 'Only print errors',
681
- type: 'boolean',
682
- },
683
- profile: {
684
- describe: 'Use profiler to measure performance',
685
- type: 'boolean',
686
- },
687
- p: {
688
- alias: 'project',
689
- describe: 'Name of a project in GraphQL Config',
690
- type: 'string',
691
- },
692
- };
693
- }
694
- function parseArgv(argv = process.argv) {
695
- return yargs.options(buildOptions()).parse(argv);
696
- }
697
- async function createContext(cliFlags = parseArgv(process.argv)) {
698
- if (cliFlags.require && cliFlags.require.length > 0) {
699
- const relativeRequire = module$1.createRequire(process.cwd());
700
- await Promise.all(cliFlags.require.map(mod => new Promise(function (resolve) { resolve(_interopNamespace(require(relativeRequire.resolve(mod, {
701
- paths: [process.cwd()],
702
- })))); })));
703
- }
704
- const customConfigPath = getCustomConfigPath(cliFlags);
705
- const context = await loadContext(customConfigPath);
706
- updateContextWithCliFlags(context, cliFlags);
707
- return context;
708
- }
709
- function updateContextWithCliFlags(context, cliFlags) {
710
- const config = {
711
- configFilePath: context.filepath,
712
- };
713
- if (cliFlags.watch) {
714
- config.watch = cliFlags.watch;
715
- }
716
- if (cliFlags.overwrite === true) {
717
- config.overwrite = cliFlags.overwrite;
718
- }
719
- if (cliFlags.silent === true) {
720
- config.silent = cliFlags.silent;
721
- }
722
- if (cliFlags.errorsOnly === true) {
723
- config.errorsOnly = cliFlags.errorsOnly;
724
- }
725
- if (cliFlags.project) {
726
- context.useProject(cliFlags.project);
727
- }
728
- if (cliFlags.profile === true) {
729
- context.useProfiler();
730
- }
731
- context.updateConfig(config);
732
- }
733
- class CodegenContext {
734
- constructor({ config, graphqlConfig, filepath, }) {
735
- this._pluginContext = {};
736
- this._config = config;
737
- this._graphqlConfig = graphqlConfig;
738
- this.filepath = this._graphqlConfig ? this._graphqlConfig.filepath : filepath;
739
- this.cwd = this._graphqlConfig ? this._graphqlConfig.dirpath : process.cwd();
740
- this.profiler = pluginHelpers.createNoopProfiler();
741
- }
742
- useProject(name) {
743
- this._project = name;
744
- }
745
- getConfig(extraConfig) {
746
- if (!this.config) {
747
- if (this._graphqlConfig) {
748
- const project = this._graphqlConfig.getProject(this._project);
749
- this.config = {
750
- ...project.extension('codegen'),
751
- schema: project.schema,
752
- documents: project.documents,
753
- pluginContext: this._pluginContext,
754
- };
755
- }
756
- else {
757
- this.config = { ...this._config, pluginContext: this._pluginContext };
758
- }
759
- }
760
- return {
761
- ...extraConfig,
762
- ...this.config,
763
- };
764
- }
765
- updateConfig(config) {
766
- this.config = {
767
- ...this.getConfig(),
768
- ...config,
769
- };
770
- }
771
- useProfiler() {
772
- this.profiler = pluginHelpers.createProfiler();
773
- const now = new Date(); // 2011-10-05T14:48:00.000Z
774
- const datetime = now.toISOString().split('.')[0]; // 2011-10-05T14:48:00
775
- const datetimeNormalized = datetime.replace(/-|:/g, ''); // 20111005T144800
776
- this.profilerOutput = `codegen-${datetimeNormalized}.json`;
777
- }
778
- getPluginContext() {
779
- return this._pluginContext;
780
- }
781
- async loadSchema(pointer) {
782
- const config = this.getConfig(defaultSchemaLoadOptions);
783
- if (this._graphqlConfig) {
784
- // TODO: SchemaWithLoader won't work here
785
- return addHashToSchema(this._graphqlConfig.getProject(this._project).loadSchema(pointer, 'GraphQLSchema', config));
786
- }
787
- return addHashToSchema(loadSchema(pointer, config));
788
- }
789
- async loadDocuments(pointer) {
790
- const config = this.getConfig(defaultDocumentsLoadOptions);
791
- if (this._graphqlConfig) {
792
- // TODO: pointer won't work here
793
- return addHashToDocumentFiles(this._graphqlConfig.getProject(this._project).loadDocuments(pointer, config));
794
- }
795
- return addHashToDocumentFiles(loadDocuments(pointer, config));
796
- }
797
- }
798
- function ensureContext(input) {
799
- return input instanceof CodegenContext ? input : new CodegenContext({ config: input });
800
- }
801
- function hashContent(content) {
802
- return crypto.createHash('sha256').update(content).digest('hex');
803
- }
804
- function hashSchema(schema) {
805
- return hashContent(graphql.print(pluginHelpers.getCachedDocumentNodeFromSchema(schema)));
806
- }
807
- function addHashToSchema(schemaPromise) {
808
- return schemaPromise.then(schema => {
809
- // It's consumed later on. The general purpose is to use it for caching.
810
- if (!schema.extensions) {
811
- schema.extensions = {};
812
- }
813
- schema.extensions['hash'] = hashSchema(schema);
814
- return schema;
815
- });
816
- }
817
- function hashDocument(doc) {
818
- if (doc.rawSDL) {
819
- return hashContent(doc.rawSDL);
820
- }
821
- if (doc.document) {
822
- return hashContent(graphql.print(doc.document));
823
- }
824
- return null;
825
- }
826
- function addHashToDocumentFiles(documentFilesPromise) {
827
- return documentFilesPromise.then(documentFiles => documentFiles.map(doc => {
828
- doc.hash = hashDocument(doc);
829
- return doc;
830
- }));
831
- }
832
-
833
- function isListrError(err) {
834
- return err.name === 'ListrError' && Array.isArray(err.errors) && err.errors.length > 0;
835
- }
836
- function cliError(err, exitOnError = true) {
837
- let msg;
838
- if (err instanceof Error) {
839
- msg = err.message || err.toString();
840
- }
841
- else if (typeof err === 'string') {
842
- msg = err;
843
- }
844
- else {
845
- msg = JSON.stringify(err);
846
- }
847
- // eslint-disable-next-line no-console
848
- console.error(msg);
849
- if (exitOnError) {
850
- process.exit(1);
851
- }
852
- }
853
-
854
- const makeDefaultLoader = (from) => {
855
- if (fs__default.statSync(from).isDirectory()) {
856
- from = path__default.join(from, '__fake.js');
857
- }
858
- const relativeRequire = module$1.createRequire(from);
859
- return (mod) => {
860
- return new Promise(function (resolve) { resolve(_interopNamespace(require(relativeRequire.resolve(mod)))); });
861
- };
862
- };
863
- function createCache() {
864
- const cache = new Map();
865
- return function ensure(namespace, key, factory) {
866
- const cacheKey = `${namespace}:${key}`;
867
- const cachedValue = cache.get(cacheKey);
868
- if (cachedValue) {
869
- return cachedValue;
870
- }
871
- const value = factory();
872
- cache.set(cacheKey, value);
873
- return value;
874
- };
875
- }
876
- async function executeCodegen(input) {
877
- const context = ensureContext(input);
878
- const config = context.getConfig();
879
- const pluginContext = context.getPluginContext();
880
- const result = [];
881
- const commonListrOptions = {
882
- exitOnError: true,
883
- };
884
- let listr;
885
- if (process.env.VERBOSE) {
886
- listr = new Listr({
887
- ...commonListrOptions,
888
- renderer: 'verbose',
889
- nonTTYRenderer: 'verbose',
890
- });
891
- }
892
- else if (process.env.NODE_ENV === 'test') {
893
- listr = new Listr({
894
- ...commonListrOptions,
895
- renderer: 'silent',
896
- nonTTYRenderer: 'silent',
897
- });
898
- }
899
- else {
900
- listr = new Listr({
901
- ...commonListrOptions,
902
- renderer: config.silent ? 'silent' : config.errorsOnly ? ErrorRenderer : Renderer,
903
- nonTTYRenderer: config.silent ? 'silent' : 'default',
904
- collapse: true,
905
- clearOutput: false,
906
- });
907
- }
908
- let rootConfig = {};
909
- let rootSchemas;
910
- let rootDocuments;
911
- const generates = {};
912
- const cache = createCache();
913
- function wrapTask(task, source, taskName) {
914
- return () => {
915
- return context.profiler.run(async () => {
916
- try {
917
- await Promise.resolve().then(() => task());
918
- }
919
- catch (error) {
920
- if (source && !(error instanceof graphql.GraphQLError)) {
921
- error.source = source;
922
- }
923
- throw error;
924
- }
925
- }, taskName);
926
- };
927
- }
928
- async function normalize() {
929
- /* Load Require extensions */
930
- const requireExtensions = pluginHelpers.normalizeInstanceOrArray(config.require);
931
- const loader = makeDefaultLoader(context.cwd);
932
- for (const mod of requireExtensions) {
933
- await loader(mod);
934
- }
935
- /* Root plugin config */
936
- rootConfig = config.config || {};
937
- /* Normalize root "schema" field */
938
- rootSchemas = pluginHelpers.normalizeInstanceOrArray(config.schema);
939
- /* Normalize root "documents" field */
940
- rootDocuments = pluginHelpers.normalizeInstanceOrArray(config.documents);
941
- /* Normalize "generators" field */
942
- const generateKeys = Object.keys(config.generates || {});
943
- if (generateKeys.length === 0) {
944
- throw new pluginHelpers.DetailedError('Invalid Codegen Configuration!', `
945
- Please make sure that your codegen config file contains the "generates" field, with a specification for the plugins you need.
946
-
947
- It should looks like that:
948
-
949
- schema:
950
- - my-schema.graphql
951
- generates:
952
- my-file.ts:
953
- - plugin1
954
- - plugin2
955
- - plugin3
956
- `);
957
- }
958
- for (const filename of generateKeys) {
959
- const output = (generates[filename] = pluginHelpers.normalizeOutputParam(config.generates[filename]));
960
- if (!output.preset && (!output.plugins || output.plugins.length === 0)) {
961
- throw new pluginHelpers.DetailedError('Invalid Codegen Configuration!', `
962
- Please make sure that your codegen config file has defined plugins list for output "${filename}".
963
-
964
- It should looks like that:
965
-
966
- schema:
967
- - my-schema.graphql
968
- generates:
969
- my-file.ts:
970
- - plugin1
971
- - plugin2
972
- - plugin3
973
- `);
974
- }
975
- }
976
- if (rootSchemas.length === 0 &&
977
- Object.keys(generates).some(filename => !generates[filename].schema || generates[filename].schema.length === 0)) {
978
- throw new pluginHelpers.DetailedError('Invalid Codegen Configuration!', `
979
- Please make sure that your codegen config file contains either the "schema" field
980
- or every generated file has its own "schema" field.
981
-
982
- It should looks like that:
983
- schema:
984
- - my-schema.graphql
985
-
986
- or:
987
- generates:
988
- path/to/output:
989
- schema: my-schema.graphql
990
- `);
991
- }
992
- }
993
- listr.add({
994
- title: 'Parse configuration',
995
- task: () => normalize(),
996
- });
997
- listr.add({
998
- title: 'Generate outputs',
999
- task: () => {
1000
- return new Listr(Object.keys(generates).map(filename => {
1001
- const outputConfig = generates[filename];
1002
- const hasPreset = !!outputConfig.preset;
1003
- return {
1004
- title: hasPreset
1005
- ? `Generate to ${filename} (using EXPERIMENTAL preset "${outputConfig.preset}")`
1006
- : `Generate ${filename}`,
1007
- task: () => {
1008
- let outputSchemaAst;
1009
- let outputSchema;
1010
- const outputFileTemplateConfig = outputConfig.config || {};
1011
- const outputDocuments = [];
1012
- const outputSpecificSchemas = pluginHelpers.normalizeInstanceOrArray(outputConfig.schema);
1013
- const outputSpecificDocuments = pluginHelpers.normalizeInstanceOrArray(outputConfig.documents);
1014
- return new Listr([
1015
- {
1016
- title: 'Load GraphQL schemas',
1017
- task: wrapTask(async () => {
1018
- debugLog(`[CLI] Loading Schemas`);
1019
- const schemaPointerMap = {};
1020
- const allSchemaUnnormalizedPointers = [...rootSchemas, ...outputSpecificSchemas];
1021
- for (const unnormalizedPtr of allSchemaUnnormalizedPointers) {
1022
- if (typeof unnormalizedPtr === 'string') {
1023
- schemaPointerMap[unnormalizedPtr] = {};
1024
- }
1025
- else if (typeof unnormalizedPtr === 'object') {
1026
- Object.assign(schemaPointerMap, unnormalizedPtr);
1027
- }
1028
- }
1029
- const hash = JSON.stringify(schemaPointerMap);
1030
- const result = await cache('schema', hash, async () => {
1031
- const outputSchemaAst = await context.loadSchema(schemaPointerMap);
1032
- const outputSchema = pluginHelpers.getCachedDocumentNodeFromSchema(outputSchemaAst);
1033
- return {
1034
- outputSchemaAst,
1035
- outputSchema,
1036
- };
1037
- });
1038
- outputSchemaAst = await result.outputSchemaAst;
1039
- outputSchema = result.outputSchema;
1040
- }, filename, `Load GraphQL schemas: ${filename}`),
1041
- },
1042
- {
1043
- title: 'Load GraphQL documents',
1044
- task: wrapTask(async () => {
1045
- debugLog(`[CLI] Loading Documents`);
1046
- // get different cache for shared docs and output specific docs
1047
- const results = await Promise.all([rootDocuments, outputSpecificDocuments].map(docs => {
1048
- const hash = JSON.stringify(docs);
1049
- return cache('documents', hash, async () => {
1050
- const documents = await context.loadDocuments(docs);
1051
- return {
1052
- documents,
1053
- };
1054
- });
1055
- }));
1056
- const documents = [];
1057
- results.forEach(source => documents.push(...source.documents));
1058
- if (documents.length > 0) {
1059
- outputDocuments.push(...documents);
1060
- }
1061
- }, filename, `Load GraphQL documents: ${filename}`),
1062
- },
1063
- {
1064
- title: 'Generate',
1065
- task: wrapTask(async () => {
1066
- debugLog(`[CLI] Generating output`);
1067
- const normalizedPluginsArray = pluginHelpers.normalizeConfig(outputConfig.plugins);
1068
- const pluginLoader = config.pluginLoader || makeDefaultLoader(context.cwd);
1069
- const pluginPackages = await Promise.all(normalizedPluginsArray.map(plugin => getPluginByName(Object.keys(plugin)[0], pluginLoader)));
1070
- const pluginMap = {};
1071
- const preset = hasPreset
1072
- ? typeof outputConfig.preset === 'string'
1073
- ? await getPresetByName(outputConfig.preset, makeDefaultLoader(context.cwd))
1074
- : outputConfig.preset
1075
- : null;
1076
- pluginPackages.forEach((pluginPackage, i) => {
1077
- const plugin = normalizedPluginsArray[i];
1078
- const name = Object.keys(plugin)[0];
1079
- pluginMap[name] = pluginPackage;
1080
- });
1081
- const mergedConfig = {
1082
- ...rootConfig,
1083
- ...(typeof outputFileTemplateConfig === 'string'
1084
- ? { value: outputFileTemplateConfig }
1085
- : outputFileTemplateConfig),
1086
- };
1087
- let outputs = [];
1088
- if (hasPreset) {
1089
- outputs = await context.profiler.run(async () => preset.buildGeneratesSection({
1090
- baseOutputDir: filename,
1091
- presetConfig: outputConfig.presetConfig || {},
1092
- plugins: normalizedPluginsArray,
1093
- schema: outputSchema,
1094
- schemaAst: outputSchemaAst,
1095
- documents: outputDocuments,
1096
- config: mergedConfig,
1097
- pluginMap,
1098
- pluginContext,
1099
- profiler: context.profiler,
1100
- }), `Build Generates Section: ${filename}`);
1101
- }
1102
- else {
1103
- outputs = [
1104
- {
1105
- filename,
1106
- plugins: normalizedPluginsArray,
1107
- schema: outputSchema,
1108
- schemaAst: outputSchemaAst,
1109
- documents: outputDocuments,
1110
- config: mergedConfig,
1111
- pluginMap,
1112
- pluginContext,
1113
- profiler: context.profiler,
1114
- },
1115
- ];
1116
- }
1117
- const process = async (outputArgs) => {
1118
- const output = await core.codegen({
1119
- ...outputArgs,
1120
- cache,
1121
- });
1122
- result.push({
1123
- filename: outputArgs.filename,
1124
- content: output,
1125
- hooks: outputConfig.hooks || {},
1126
- });
1127
- };
1128
- await context.profiler.run(() => Promise.all(outputs.map(process)), `Codegen: ${filename}`);
1129
- }, filename, `Generate: ${filename}`),
1130
- },
1131
- ], {
1132
- // it stops when one of tasks failed
1133
- exitOnError: true,
1134
- });
1135
- },
1136
- };
1137
- }), {
1138
- // it doesn't stop when one of tasks failed, to finish at least some of outputs
1139
- exitOnError: false,
1140
- concurrent: os.cpus().length,
1141
- });
1142
- },
1143
- });
1144
- try {
1145
- await listr.run();
1146
- }
1147
- catch (err) {
1148
- if (isListrError(err)) {
1149
- const allErrs = err.errors.map(subErr => pluginHelpers.isDetailedError(subErr)
1150
- ? `${subErr.message} for "${subErr.source}"${subErr.details}`
1151
- : subErr.message || subErr.toString());
1152
- const newErr = new utils.AggregateError(err.errors, `${err.message} ${allErrs.join('\n\n')}`);
1153
- // Best-effort to all stack traces for debugging
1154
- newErr.stack = `${newErr.stack}\n\n${err.errors.map(subErr => subErr.stack).join('\n\n')}`;
1155
- throw newErr;
1156
- }
1157
- throw err;
1158
- }
1159
- return result;
1160
- }
1161
-
1162
- function log(msg) {
1163
- // double spaces to inline the message with Listr
1164
- getLogger().info(` ${msg}`);
1165
- }
1166
- function emitWatching() {
1167
- log(`${logSymbols.info} Watching for changes...`);
1168
- }
1169
- const createWatcher = (initalContext, onNext) => {
1170
- debugLog(`[Watcher] Starting watcher...`);
1171
- let config = initalContext.getConfig();
1172
- const files = [initalContext.filepath].filter(a => a);
1173
- const documents = pluginHelpers.normalizeInstanceOrArray(config.documents);
1174
- const schemas = pluginHelpers.normalizeInstanceOrArray(config.schema);
1175
- // Add schemas and documents from "generates"
1176
- Object.keys(config.generates)
1177
- .map(filename => pluginHelpers.normalizeOutputParam(config.generates[filename]))
1178
- .forEach(conf => {
1179
- schemas.push(...pluginHelpers.normalizeInstanceOrArray(conf.schema));
1180
- documents.push(...pluginHelpers.normalizeInstanceOrArray(conf.documents));
1181
- });
1182
- if (documents) {
1183
- documents.forEach(doc => {
1184
- if (typeof doc === 'string') {
1185
- files.push(doc);
1186
- }
1187
- else {
1188
- files.push(...Object.keys(doc));
1189
- }
1190
- });
1191
- }
1192
- schemas.forEach((schema) => {
1193
- if (isGlob(schema) || utils.isValidPath(schema)) {
1194
- files.push(schema);
1195
- }
1196
- });
1197
- if (typeof config.watch !== 'boolean') {
1198
- files.push(...pluginHelpers.normalizeInstanceOrArray(config.watch));
1199
- }
1200
- let watcher;
1201
- const runWatcher = async () => {
1202
- var _a, _b;
1203
- const chokidar = await new Promise(function (resolve) { resolve(_interopNamespace(require('chokidar'))); });
1204
- let isShutdown = false;
1205
- const debouncedExec = debounce(() => {
1206
- if (!isShutdown) {
1207
- executeCodegen(initalContext)
1208
- .then(onNext, () => Promise.resolve())
1209
- .then(() => emitWatching());
1210
- }
1211
- }, 100);
1212
- emitWatching();
1213
- const ignored = [];
1214
- Object.keys(config.generates)
1215
- .map(filename => ({ filename, config: pluginHelpers.normalizeOutputParam(config.generates[filename]) }))
1216
- .forEach(entry => {
1217
- if (entry.config.preset) {
1218
- const extension = entry.config.presetConfig && entry.config.presetConfig.extension;
1219
- if (extension) {
1220
- ignored.push(path.join(entry.filename, '**', '*' + extension));
1221
- }
1222
- }
1223
- else {
1224
- ignored.push(entry.filename);
1225
- }
1226
- });
1227
- watcher = chokidar.watch(files, {
1228
- persistent: true,
1229
- ignoreInitial: true,
1230
- followSymlinks: true,
1231
- cwd: process.cwd(),
1232
- disableGlobbing: false,
1233
- usePolling: (_a = config.watchConfig) === null || _a === void 0 ? void 0 : _a.usePolling,
1234
- interval: (_b = config.watchConfig) === null || _b === void 0 ? void 0 : _b.interval,
1235
- depth: 99,
1236
- awaitWriteFinish: true,
1237
- ignorePermissionErrors: false,
1238
- atomic: true,
1239
- ignored,
1240
- });
1241
- debugLog(`[Watcher] Started`);
1242
- const shutdown = () => {
1243
- isShutdown = true;
1244
- debugLog(`[Watcher] Shutting down`);
1245
- log(`Shutting down watch...`);
1246
- watcher.close();
1247
- lifecycleHooks(config.hooks).beforeDone();
1248
- };
1249
- // it doesn't matter what has changed, need to run whole process anyway
1250
- watcher.on('all', async (eventName, path$1) => {
1251
- lifecycleHooks(config.hooks).onWatchTriggered(eventName, path$1);
1252
- debugLog(`[Watcher] triggered due to a file ${eventName} event: ${path$1}`);
1253
- const fullPath = path.join(process.cwd(), path$1);
1254
- // In ESM require is not defined
1255
- try {
1256
- delete require.cache[fullPath];
1257
- }
1258
- catch (err) { }
1259
- if (eventName === 'change' && config.configFilePath && fullPath === config.configFilePath) {
1260
- log(`${logSymbols.info} Config file has changed, reloading...`);
1261
- const context = await loadContext(config.configFilePath);
1262
- const newParsedConfig = context.getConfig();
1263
- newParsedConfig.watch = config.watch;
1264
- newParsedConfig.silent = config.silent;
1265
- newParsedConfig.overwrite = config.overwrite;
1266
- newParsedConfig.configFilePath = config.configFilePath;
1267
- config = newParsedConfig;
1268
- initalContext.updateConfig(config);
1269
- }
1270
- debouncedExec();
1271
- });
1272
- process.once('SIGINT', shutdown);
1273
- process.once('SIGTERM', shutdown);
1274
- };
1275
- // the promise never resolves to keep process running
1276
- return new Promise((resolve, reject) => {
1277
- executeCodegen(initalContext)
1278
- .then(onNext, () => Promise.resolve())
1279
- .then(runWatcher)
1280
- .catch(err => {
1281
- watcher.close();
1282
- reject(err);
1283
- });
1284
- });
1285
- };
1286
-
1287
- const { writeFile: fsWriteFile, readFile: fsReadFile, stat: fsStat } = fs.promises;
1288
- function writeFile(filepath, content) {
1289
- return fsWriteFile(filepath, content);
1290
- }
1291
- function readFile(filepath) {
1292
- return fsReadFile(filepath, 'utf-8');
1293
- }
1294
- async function fileExists(filePath) {
1295
- try {
1296
- return (await fsStat(filePath)).isFile();
1297
- }
1298
- catch (err) {
1299
- return false;
1300
- }
1301
- }
1302
- function unlinkFile(filePath, cb) {
1303
- fs.unlink(filePath, cb);
1304
- }
1305
-
1306
- const hash = (content) => crypto.createHash('sha1').update(content).digest('base64');
1307
- async function generate(input, saveToFile = true) {
1308
- const context = ensureContext(input);
1309
- const config = context.getConfig();
1310
- await context.profiler.run(() => lifecycleHooks(config.hooks).afterStart(), 'Lifecycle: afterStart');
1311
- let previouslyGeneratedFilenames = [];
1312
- function removeStaleFiles(config, generationResult) {
1313
- const filenames = generationResult.map(o => o.filename);
1314
- // find stale files from previous build which are not present in current build
1315
- const staleFilenames = previouslyGeneratedFilenames.filter(f => !filenames.includes(f));
1316
- staleFilenames.forEach(filename => {
1317
- if (shouldOverwrite(config, filename)) {
1318
- return unlinkFile(filename, err => {
1319
- const prettyFilename = filename.replace(`${input.cwd || process.cwd()}/`, '');
1320
- if (err) {
1321
- debugLog(`Cannot remove stale file: ${prettyFilename}\n${err}`);
1322
- }
1323
- else {
1324
- debugLog(`Removed stale file: ${prettyFilename}`);
1325
- }
1326
- });
1327
- }
1328
- });
1329
- previouslyGeneratedFilenames = filenames;
1330
- }
1331
- const recentOutputHash = new Map();
1332
- async function writeOutput(generationResult) {
1333
- if (!saveToFile) {
1334
- return generationResult;
1335
- }
1336
- if (config.watch) {
1337
- removeStaleFiles(config, generationResult);
1338
- }
1339
- await context.profiler.run(async () => {
1340
- await lifecycleHooks(config.hooks).beforeAllFileWrite(generationResult.map(r => r.filename));
1341
- }, 'Lifecycle: beforeAllFileWrite');
1342
- await context.profiler.run(() => Promise.all(generationResult.map(async (result) => {
1343
- const exists = await fileExists(result.filename);
1344
- if (!shouldOverwrite(config, result.filename) && exists) {
1345
- return;
1346
- }
1347
- const content = result.content || '';
1348
- const currentHash = hash(content);
1349
- let previousHash = recentOutputHash.get(result.filename);
1350
- if (!previousHash && exists) {
1351
- previousHash = hash(await readFile(result.filename));
1352
- }
1353
- if (previousHash && currentHash === previousHash) {
1354
- debugLog(`Skipping file (${result.filename}) writing due to indentical hash...`);
1355
- return;
1356
- }
1357
- if (content.length === 0) {
1358
- return;
1359
- }
1360
- recentOutputHash.set(result.filename, currentHash);
1361
- const basedir = path.dirname(result.filename);
1362
- await lifecycleHooks(result.hooks).beforeOneFileWrite(result.filename);
1363
- await lifecycleHooks(config.hooks).beforeOneFileWrite(result.filename);
1364
- await mkdirp(basedir);
1365
- const absolutePath = path.isAbsolute(result.filename)
1366
- ? result.filename
1367
- : path.join(input.cwd || process.cwd(), result.filename);
1368
- await writeFile(absolutePath, result.content);
1369
- await lifecycleHooks(result.hooks).afterOneFileWrite(result.filename);
1370
- await lifecycleHooks(config.hooks).afterOneFileWrite(result.filename);
1371
- })), 'Write files');
1372
- await context.profiler.run(() => lifecycleHooks(config.hooks).afterAllFileWrite(generationResult.map(r => r.filename)), 'Lifecycle: afterAllFileWrite');
1373
- return generationResult;
1374
- }
1375
- // watch mode
1376
- if (config.watch) {
1377
- return createWatcher(context, writeOutput);
1378
- }
1379
- const outputFiles = await context.profiler.run(() => executeCodegen(context), 'executeCodegen');
1380
- await context.profiler.run(() => writeOutput(outputFiles), 'writeOutput');
1381
- await context.profiler.run(() => lifecycleHooks(config.hooks).beforeDone(), 'Lifecycle: beforeDone');
1382
- if (context.profilerOutput) {
1383
- await writeFile(path.join(context.cwd, context.profilerOutput), JSON.stringify(context.profiler.collect()));
1384
- }
1385
- return outputFiles;
1386
- }
1387
- function shouldOverwrite(config, outputPath) {
1388
- const globalValue = config.overwrite === undefined ? true : !!config.overwrite;
1389
- const outputConfig = config.generates[outputPath];
1390
- if (!outputConfig) {
1391
- debugLog(`Couldn't find a config of ${outputPath}`);
1392
- return globalValue;
1393
- }
1394
- if (isConfiguredOutput(outputConfig) && typeof outputConfig.overwrite === 'boolean') {
1395
- return outputConfig.overwrite;
1396
- }
1397
- return globalValue;
1398
- }
1399
- function isConfiguredOutput(output) {
1400
- return typeof output.plugins !== 'undefined';
1401
- }
1402
-
1403
- // Parses config and writes it to a file
1404
- async function writeConfig(answers, config) {
1405
- const YAML = await new Promise(function (resolve) { resolve(_interopNamespace(require('json-to-pretty-yaml'))); }).then(m => ('default' in m ? m.default : m));
1406
- const ext = answers.config.toLocaleLowerCase().endsWith('.json') ? 'json' : 'yml';
1407
- const content = ext === 'json' ? JSON.stringify(config) : YAML.stringify(config);
1408
- const fullPath = path.resolve(process.cwd(), answers.config);
1409
- const relativePath = path.relative(process.cwd(), answers.config);
1410
- fs.writeFileSync(fullPath, content, {
1411
- encoding: 'utf-8',
1412
- });
1413
- return {
1414
- relativePath,
1415
- fullPath,
1416
- };
1417
- }
1418
- // Updates package.json (script and plugins as dependencies)
1419
- async function writePackage(answers, configLocation) {
1420
- // script
1421
- const pkgPath = path.resolve(process.cwd(), 'package.json');
1422
- const pkgContent = fs.readFileSync(pkgPath, {
1423
- encoding: 'utf-8',
1424
- });
1425
- const pkg = JSON.parse(pkgContent);
1426
- const { indent } = detectIndent(pkgContent);
1427
- if (!pkg.scripts) {
1428
- pkg.scripts = {};
1429
- }
1430
- pkg.scripts[answers.script] = `graphql-codegen --config ${configLocation}`;
1431
- // plugin
1432
- if (!pkg.devDependencies) {
1433
- pkg.devDependencies = {};
1434
- }
1435
- await Promise.all(answers.plugins.map(async (plugin) => {
1436
- pkg.devDependencies[plugin.package] = await getLatestVersion(plugin.package);
1437
- }));
1438
- if (answers.introspection) {
1439
- pkg.devDependencies['@graphql-codegen/introspection'] = await getLatestVersion('@graphql-codegen/introspection');
1440
- }
1441
- pkg.devDependencies['@graphql-codegen/cli'] = await getLatestVersion('@graphql-codegen/cli');
1442
- fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, indent));
1443
- }
1444
- function bold(str) {
1445
- return chalk.bold(str);
1446
- }
1447
- function grey(str) {
1448
- return chalk.grey(str);
1449
- }
1450
- function italic(str) {
1451
- return chalk.italic(str);
1452
- }
1453
-
1454
- var Tags;
1455
- (function (Tags) {
1456
- Tags["browser"] = "Browser";
1457
- Tags["node"] = "Node";
1458
- Tags["typescript"] = "TypeScript";
1459
- Tags["flow"] = "Flow";
1460
- Tags["angular"] = "Angular";
1461
- Tags["stencil"] = "Stencil";
1462
- Tags["react"] = "React";
1463
- Tags["vue"] = "Vue";
1464
- })(Tags || (Tags = {}));
1465
-
1466
- const plugins = [
1467
- {
1468
- name: `TypeScript ${italic('(required by other typescript plugins)')}`,
1469
- package: '@graphql-codegen/typescript',
1470
- value: 'typescript',
1471
- pathInRepo: 'typescript/typescript',
1472
- available: hasTag(Tags.typescript),
1473
- shouldBeSelected: tags => oneOf(tags, Tags.angular, Tags.stencil) || allOf(tags, Tags.typescript, Tags.react) || noneOf(tags, Tags.flow),
1474
- defaultExtension: '.ts',
1475
- },
1476
- {
1477
- name: `TypeScript Operations ${italic('(operations and fragments)')}`,
1478
- package: '@graphql-codegen/typescript-operations',
1479
- value: 'typescript-operations',
1480
- pathInRepo: 'typescript/operations',
1481
- available: tags => allOf(tags, Tags.browser, Tags.typescript),
1482
- shouldBeSelected: tags => oneOf(tags, Tags.angular, Tags.stencil) || allOf(tags, Tags.typescript, Tags.react),
1483
- defaultExtension: '.ts',
1484
- },
1485
- {
1486
- name: `TypeScript Resolvers ${italic('(strongly typed resolve functions)')}`,
1487
- package: '@graphql-codegen/typescript-resolvers',
1488
- value: 'typescript-resolvers',
1489
- pathInRepo: 'typescript/resolvers',
1490
- available: tags => allOf(tags, Tags.node, Tags.typescript),
1491
- shouldBeSelected: tags => noneOf(tags, Tags.flow),
1492
- defaultExtension: '.ts',
1493
- },
1494
- {
1495
- name: `Flow ${italic('(required by other flow plugins)')}`,
1496
- package: '@graphql-codegen/flow',
1497
- value: 'flow',
1498
- pathInRepo: 'flow/flow',
1499
- available: hasTag(Tags.flow),
1500
- shouldBeSelected: tags => noneOf(tags, Tags.typescript),
1501
- defaultExtension: '.js',
1502
- },
1503
- {
1504
- name: `Flow Operations ${italic('(operations and fragments)')}`,
1505
- package: '@graphql-codegen/flow-operations',
1506
- value: 'flow-operations',
1507
- pathInRepo: 'flow/operations',
1508
- available: tags => allOf(tags, Tags.browser, Tags.flow),
1509
- shouldBeSelected: tags => noneOf(tags, Tags.typescript),
1510
- defaultExtension: '.js',
1511
- },
1512
- {
1513
- name: `Flow Resolvers ${italic('(strongly typed resolve functions)')}`,
1514
- package: '@graphql-codegen/flow-resolvers',
1515
- value: 'flow-resolvers',
1516
- pathInRepo: 'flow/resolvers',
1517
- available: tags => allOf(tags, Tags.node, Tags.flow),
1518
- shouldBeSelected: tags => noneOf(tags, Tags.typescript),
1519
- defaultExtension: '.js',
1520
- },
1521
- {
1522
- name: `TypeScript Apollo Angular ${italic('(typed GQL services)')}`,
1523
- package: '@graphql-codegen/typescript-apollo-angular',
1524
- value: 'typescript-apollo-angular',
1525
- pathInRepo: 'typescript/apollo-angular',
1526
- available: hasTag(Tags.angular),
1527
- shouldBeSelected: () => true,
1528
- defaultExtension: '.js',
1529
- },
1530
- {
1531
- name: `TypeScript Vue Apollo Composition API ${italic('(typed functions)')}`,
1532
- package: '@graphql-codegen/typescript-vue-apollo',
1533
- value: 'typescript-vue-apollo',
1534
- pathInRepo: 'typescript/vue-apollo',
1535
- available: tags => allOf(tags, Tags.vue, Tags.typescript),
1536
- shouldBeSelected: () => true,
1537
- defaultExtension: '.ts',
1538
- },
1539
- {
1540
- name: `TypeScript Vue Apollo Smart Operations ${italic('(typed functions)')}`,
1541
- package: '@graphql-codegen/typescript-vue-apollo-smart-ops',
1542
- value: 'typescript-vue-apollo-smart-ops',
1543
- pathInRepo: 'typescript/vue-apollo-smart-ops',
1544
- available: tags => allOf(tags, Tags.vue, Tags.typescript),
1545
- shouldBeSelected: () => true,
1546
- defaultExtension: '.ts',
1547
- },
1548
- {
1549
- name: `TypeScript React Apollo ${italic('(typed components and HOCs)')}`,
1550
- package: '@graphql-codegen/typescript-react-apollo',
1551
- value: 'typescript-react-apollo',
1552
- pathInRepo: 'typescript/react-apollo',
1553
- available: tags => allOf(tags, Tags.react, Tags.typescript),
1554
- shouldBeSelected: () => true,
1555
- defaultExtension: '.tsx',
1556
- },
1557
- {
1558
- name: `TypeScript Stencil Apollo ${italic('(typed components)')}`,
1559
- package: '@graphql-codegen/typescript-stencil-apollo',
1560
- value: 'typescript-stencil-apollo',
1561
- pathInRepo: 'typescript/stencil-apollo',
1562
- available: hasTag(Tags.stencil),
1563
- shouldBeSelected: () => true,
1564
- defaultExtension: '.tsx',
1565
- },
1566
- {
1567
- name: `TypeScript MongoDB ${italic('(typed MongoDB objects)')}`,
1568
- package: '@graphql-codegen/typescript-mongodb',
1569
- value: 'typescript-mongodb',
1570
- pathInRepo: 'typescript/mongodb',
1571
- available: tags => allOf(tags, Tags.node, Tags.typescript),
1572
- shouldBeSelected: () => false,
1573
- defaultExtension: '.ts',
1574
- },
1575
- {
1576
- name: `TypeScript GraphQL files modules ${italic('(declarations for .graphql files)')}`,
1577
- package: '@graphql-codegen/typescript-graphql-files-modules',
1578
- value: 'typescript-graphql-files-modules',
1579
- pathInRepo: 'typescript/graphql-files-modules',
1580
- available: tags => allOf(tags, Tags.browser, Tags.typescript),
1581
- shouldBeSelected: () => false,
1582
- defaultExtension: '.ts',
1583
- },
1584
- {
1585
- name: `TypeScript GraphQL document nodes ${italic('(embedded GraphQL document)')}`,
1586
- package: '@graphql-codegen/typescript-document-nodes',
1587
- value: 'typescript-document-nodes',
1588
- pathInRepo: 'typescript/document-nodes',
1589
- available: tags => allOf(tags, Tags.typescript),
1590
- shouldBeSelected: () => false,
1591
- defaultExtension: '.ts',
1592
- },
1593
- {
1594
- name: `Introspection Fragment Matcher ${italic('(for Apollo Client)')}`,
1595
- package: '@graphql-codegen/fragment-matcher',
1596
- value: 'fragment-matcher',
1597
- pathInRepo: 'other/fragment-matcher',
1598
- available: hasTag(Tags.browser),
1599
- shouldBeSelected: () => false,
1600
- defaultExtension: '.ts',
1601
- },
1602
- {
1603
- name: `Urql Introspection ${italic('(for Urql Client)')}`,
1604
- package: '@graphql-codegen/urql-introspection',
1605
- value: 'urql-introspection',
1606
- pathInRepo: 'other/urql-introspection',
1607
- available: hasTag(Tags.browser),
1608
- shouldBeSelected: () => false,
1609
- defaultExtension: '.ts',
1610
- },
1611
- ];
1612
- function hasTag(tag) {
1613
- return (tags) => tags.includes(tag);
1614
- }
1615
- function oneOf(list, ...items) {
1616
- return list.some(i => items.includes(i));
1617
- }
1618
- function noneOf(list, ...items) {
1619
- return !list.some(i => items.includes(i));
1620
- }
1621
- function allOf(list, ...items) {
1622
- return items.every(i => list.includes(i));
1623
- }
1624
-
1625
- function getQuestions(possibleTargets) {
1626
- return [
1627
- {
1628
- type: 'checkbox',
1629
- name: 'targets',
1630
- message: `What type of application are you building?`,
1631
- choices: getApplicationTypeChoices(possibleTargets),
1632
- validate: ((targets) => targets.length > 0),
1633
- },
1634
- {
1635
- type: 'input',
1636
- name: 'schema',
1637
- message: 'Where is your schema?:',
1638
- suffix: grey(' (path or url)'),
1639
- default: 'http://localhost:4000',
1640
- validate: (str) => str.length > 0,
1641
- },
1642
- {
1643
- type: 'input',
1644
- name: 'documents',
1645
- message: 'Where are your operations and fragments?:',
1646
- when: answers => {
1647
- // flatten targets
1648
- // I can't find an API in Inquirer that would do that
1649
- answers.targets = normalizeTargets(answers.targets);
1650
- return answers.targets.includes(Tags.browser);
1651
- },
1652
- default: 'src/**/*.graphql',
1653
- validate: (str) => str.length > 0,
1654
- },
1655
- {
1656
- type: 'checkbox',
1657
- name: 'plugins',
1658
- message: 'Pick plugins:',
1659
- choices: getPluginChoices,
1660
- validate: ((plugins) => plugins.length > 0),
1661
- },
1662
- {
1663
- type: 'input',
1664
- name: 'output',
1665
- message: 'Where to write the output:',
1666
- default: getOutputDefaultValue,
1667
- validate: (str) => str.length > 0,
1668
- },
1669
- {
1670
- type: 'confirm',
1671
- name: 'introspection',
1672
- message: 'Do you want to generate an introspection file?',
1673
- },
1674
- {
1675
- type: 'input',
1676
- name: 'config',
1677
- message: 'How to name the config file?',
1678
- default: 'codegen.yml',
1679
- validate: (str) => {
1680
- const isNotEmpty = str.length > 0;
1681
- const hasCorrectExtension = ['json', 'yml', 'yaml'].some(ext => str.toLocaleLowerCase().endsWith(`.${ext}`));
1682
- return isNotEmpty && hasCorrectExtension;
1683
- },
1684
- },
1685
- {
1686
- type: 'input',
1687
- name: 'script',
1688
- message: 'What script in package.json should run the codegen?',
1689
- validate: (str) => str.length > 0,
1690
- },
1691
- ];
1692
- }
1693
- function getApplicationTypeChoices(possibleTargets) {
1694
- function withFlowOrTypescript(tags) {
1695
- if (possibleTargets.TypeScript) {
1696
- tags.push(Tags.typescript);
1697
- }
1698
- else if (possibleTargets.Flow) {
1699
- tags.push(Tags.flow);
1700
- }
1701
- else {
1702
- tags.push(Tags.flow, Tags.typescript);
1703
- }
1704
- return tags;
1705
- }
1706
- return [
1707
- {
1708
- name: 'Backend - API or server',
1709
- key: 'backend',
1710
- value: withFlowOrTypescript([Tags.node]),
1711
- checked: possibleTargets.Node,
1712
- },
1713
- {
1714
- name: 'Application built with Angular',
1715
- key: 'angular',
1716
- value: [Tags.angular, Tags.browser, Tags.typescript],
1717
- checked: possibleTargets.Angular,
1718
- },
1719
- {
1720
- name: 'Application built with React',
1721
- key: 'react',
1722
- value: withFlowOrTypescript([Tags.react, Tags.browser]),
1723
- checked: possibleTargets.React,
1724
- },
1725
- {
1726
- name: 'Application built with Stencil',
1727
- key: 'stencil',
1728
- value: [Tags.stencil, Tags.browser, Tags.typescript],
1729
- checked: possibleTargets.Stencil,
1730
- },
1731
- {
1732
- name: 'Application built with other framework or vanilla JS',
1733
- key: 'client',
1734
- value: [Tags.browser, Tags.typescript, Tags.flow],
1735
- checked: possibleTargets.Browser && !possibleTargets.Angular && !possibleTargets.React && !possibleTargets.Stencil,
1736
- },
1737
- ];
1738
- }
1739
- function getPluginChoices(answers) {
1740
- return plugins
1741
- .filter(p => p.available(answers.targets))
1742
- .map(p => {
1743
- return {
1744
- name: p.name,
1745
- value: p,
1746
- checked: p.shouldBeSelected(answers.targets),
1747
- };
1748
- });
1749
- }
1750
- function normalizeTargets(targets) {
1751
- return [].concat(...targets);
1752
- }
1753
- function getOutputDefaultValue(answers) {
1754
- if (answers.plugins.some(plugin => plugin.defaultExtension === '.tsx')) {
1755
- return 'src/generated/graphql.tsx';
1756
- }
1757
- if (answers.plugins.some(plugin => plugin.defaultExtension === '.ts')) {
1758
- return 'src/generated/graphql.ts';
1759
- }
1760
- return 'src/generated/graphql.js';
1761
- }
1762
-
1763
- async function guessTargets() {
1764
- const pkg = JSON.parse(fs.readFileSync(path.resolve(process.cwd(), 'package.json'), {
1765
- encoding: 'utf-8',
1766
- }));
1767
- const dependencies = Object.keys({
1768
- ...pkg.dependencies,
1769
- ...pkg.devDependencies,
1770
- });
1771
- return {
1772
- [Tags.angular]: isAngular(dependencies),
1773
- [Tags.react]: isReact(dependencies),
1774
- [Tags.stencil]: isStencil(dependencies),
1775
- [Tags.vue]: isVue(dependencies),
1776
- [Tags.browser]: false,
1777
- [Tags.node]: false,
1778
- [Tags.typescript]: isTypescript(dependencies),
1779
- [Tags.flow]: isFlow(dependencies),
1780
- };
1781
- }
1782
- function isAngular(dependencies) {
1783
- return dependencies.includes('@angular/core');
1784
- }
1785
- function isReact(dependencies) {
1786
- return dependencies.includes('react');
1787
- }
1788
- function isStencil(dependencies) {
1789
- return dependencies.includes('@stencil/core');
1790
- }
1791
- function isVue(dependencies) {
1792
- return dependencies.includes('vue') || dependencies.includes('nuxt');
1793
- }
1794
- function isTypescript(dependencies) {
1795
- return dependencies.includes('typescript');
1796
- }
1797
- function isFlow(dependencies) {
1798
- return dependencies.includes('flow');
1799
- }
1800
-
1801
- function log$1(...msgs) {
1802
- // eslint-disable-next-line no-console
1803
- console.log(...msgs);
1804
- }
1805
- async function init() {
1806
- log$1(`
1807
- Welcome to ${bold('GraphQL Code Generator')}!
1808
- Answer few questions and we will setup everything for you.
1809
- `);
1810
- const possibleTargets = await guessTargets();
1811
- const answers = await inquirer.prompt(getQuestions(possibleTargets));
1812
- // define config
1813
- const config = {
1814
- overwrite: true,
1815
- schema: answers.schema,
1816
- documents: answers.targets.includes(Tags.browser) ? answers.documents : null,
1817
- generates: {
1818
- [answers.output]: {
1819
- plugins: answers.plugins.map(p => p.value),
1820
- },
1821
- },
1822
- };
1823
- // introspection
1824
- if (answers.introspection) {
1825
- addIntrospection(config);
1826
- }
1827
- // config file
1828
- const { relativePath } = await writeConfig(answers, config);
1829
- log$1(`Fetching latest versions of selected plugins...`);
1830
- // write package.json
1831
- await writePackage(answers, relativePath);
1832
- // Emit status to the terminal
1833
- log$1(`
1834
- Config file generated at ${bold(relativePath)}
1835
-
1836
- ${bold('$ npm install')}
1837
-
1838
- To install the plugins.
1839
-
1840
- ${bold(`$ npm run ${answers.script}`)}
1841
-
1842
- To run GraphQL Code Generator.
1843
- `);
1844
- }
1845
- // adds an introspection to `generates`
1846
- function addIntrospection(config) {
1847
- config.generates['./graphql.schema.json'] = {
1848
- plugins: ['introspection'],
1849
- };
1850
- }
1851
-
1852
- async function runCli(cmd) {
1853
- await ensureGraphQlPackage();
1854
- switch (cmd) {
1855
- case 'init':
1856
- return init();
1857
- default: {
1858
- return createContext().then(context => {
1859
- return generate(context).catch(async (error) => {
1860
- await lifecycleHooks(context.getConfig().hooks).onError(error.toString());
1861
- throw error;
1862
- });
1863
- });
1864
- }
1865
- }
1866
- }
1867
- async function ensureGraphQlPackage() {
1868
- try {
1869
- await new Promise(function (resolve) { resolve(_interopNamespace(require('graphql'))); });
1870
- }
1871
- catch (e) {
1872
- throw new pluginHelpers.DetailedError(`Unable to load "graphql" package. Please make sure to install "graphql" as a dependency!`, `
1873
- To install "graphql", run:
1874
- yarn add graphql
1875
- Or, with NPM:
1876
- npm install --save graphql
1877
- `);
1878
- }
1879
- }
1880
-
1881
- const [, , cmd] = process.argv;
1882
- runCli(cmd)
1883
- .then(() => {
1884
- process.exit(0);
1885
- })
1886
- .catch(error => {
1887
- cliError(error);
1888
- });