@graphql-codegen/cli 2.6.5-alpha-d6416b45e.0 → 2.6.5-alpha-11e1cf4aa.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.
- package/bin.js +403 -201
- package/index.js +419 -220
- package/index.mjs +420 -221
- package/package.json +10 -5
- package/utils/indentString.d.ts +26 -0
- package/utils/listr-renderer.d.ts +18 -0
- package/utils/try-to-build-schema.d.ts +0 -2
package/index.mjs
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
import { DetailedError, createNoopProfiler, createProfiler, getCachedDocumentNodeFromSchema, normalizeInstanceOrArray, normalizeConfig,
|
|
1
|
+
import { isDetailedError, DetailedError, createNoopProfiler, createProfiler, getCachedDocumentNodeFromSchema, normalizeInstanceOrArray, normalizeConfig, normalizeOutputParam } from '@graphql-codegen/plugin-helpers';
|
|
2
2
|
import { codegen } from '@graphql-codegen/core';
|
|
3
3
|
import { AggregateError, isValidPath } from '@graphql-tools/utils';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import logSymbols from 'log-symbols';
|
|
6
|
+
import ansiEscapes from 'ansi-escapes';
|
|
7
|
+
import wrapAnsi from 'wrap-ansi';
|
|
8
|
+
import { stripIndent } from 'common-tags';
|
|
9
|
+
import { dummyLogger } from 'ts-log';
|
|
10
|
+
import UpdateRenderer from 'listr-update-renderer';
|
|
4
11
|
import { print, GraphQLError } from 'graphql';
|
|
5
12
|
import path, { resolve, extname, join, delimiter, sep, dirname, isAbsolute, relative } from 'path';
|
|
6
|
-
import { dummyLogger } from 'ts-log';
|
|
7
13
|
import { cosmiconfig, defaultLoaders } from 'cosmiconfig';
|
|
8
14
|
import { env } from 'string-env-interpolation';
|
|
9
15
|
import yargs from 'yargs';
|
|
@@ -22,17 +28,204 @@ import { createRequire } from 'module';
|
|
|
22
28
|
import fs, { promises, unlink, writeFileSync, readFileSync } from 'fs';
|
|
23
29
|
import { createHash } from 'crypto';
|
|
24
30
|
import { cpus } from 'os';
|
|
25
|
-
import
|
|
31
|
+
import Listr from 'listr';
|
|
26
32
|
import { exec } from 'child_process';
|
|
27
33
|
import isGlob from 'is-glob';
|
|
28
34
|
import debounce from 'debounce';
|
|
29
|
-
import logSymbols from 'log-symbols';
|
|
30
35
|
import mkdirp from 'mkdirp';
|
|
31
36
|
import inquirer from 'inquirer';
|
|
32
|
-
import chalk from 'chalk';
|
|
33
37
|
import detectIndent from 'detect-indent';
|
|
34
38
|
import getLatestVersion from 'latest-version';
|
|
35
39
|
|
|
40
|
+
/**
|
|
41
|
+
Indent each line in a string.
|
|
42
|
+
@param string - The string to indent.
|
|
43
|
+
@param count - How many times you want `options.indent` repeated. Default: `1`.
|
|
44
|
+
@example
|
|
45
|
+
```
|
|
46
|
+
import indentString from 'indent-string';
|
|
47
|
+
indentString('Unicorns\nRainbows', 4);
|
|
48
|
+
//=> ' Unicorns\n Rainbows'
|
|
49
|
+
indentString('Unicorns\nRainbows', 4, {indent: '♥'});
|
|
50
|
+
//=> '♥♥♥♥Unicorns\n♥♥♥♥Rainbows'
|
|
51
|
+
```
|
|
52
|
+
*/
|
|
53
|
+
function indentString(string, count = 1, options = {}) {
|
|
54
|
+
const { indent = ' ', includeEmptyLines = false } = options;
|
|
55
|
+
if (typeof string !== 'string') {
|
|
56
|
+
throw new TypeError(`Expected \`input\` to be a \`string\`, got \`${typeof string}\``);
|
|
57
|
+
}
|
|
58
|
+
if (typeof count !== 'number') {
|
|
59
|
+
throw new TypeError(`Expected \`count\` to be a \`number\`, got \`${typeof count}\``);
|
|
60
|
+
}
|
|
61
|
+
if (count < 0) {
|
|
62
|
+
throw new RangeError(`Expected \`count\` to be at least 0, got \`${count}\``);
|
|
63
|
+
}
|
|
64
|
+
if (typeof indent !== 'string') {
|
|
65
|
+
throw new TypeError(`Expected \`options.indent\` to be a \`string\`, got \`${typeof indent}\``);
|
|
66
|
+
}
|
|
67
|
+
if (count === 0) {
|
|
68
|
+
return string;
|
|
69
|
+
}
|
|
70
|
+
const regex = includeEmptyLines ? /^/gm : /^(?!\s*$)/gm;
|
|
71
|
+
return string.replace(regex, indent.repeat(count));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let logger;
|
|
75
|
+
function getLogger() {
|
|
76
|
+
return logger || dummyLogger;
|
|
77
|
+
}
|
|
78
|
+
useWinstonLogger();
|
|
79
|
+
function useWinstonLogger() {
|
|
80
|
+
if (logger && logger.levels) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
logger = console;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
let queue = [];
|
|
87
|
+
function debugLog(message, ...meta) {
|
|
88
|
+
if (!process.env.GQL_CODEGEN_NODEBUG && process.env.DEBUG !== undefined) {
|
|
89
|
+
queue.push({
|
|
90
|
+
message,
|
|
91
|
+
meta,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function printLogs() {
|
|
96
|
+
if (!process.env.GQL_CODEGEN_NODEBUG && process.env.DEBUG !== undefined) {
|
|
97
|
+
queue.forEach(log => {
|
|
98
|
+
getLogger().info(log.message, ...log.meta);
|
|
99
|
+
});
|
|
100
|
+
resetLogs();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function resetLogs() {
|
|
104
|
+
queue = [];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
class Renderer {
|
|
108
|
+
constructor(tasks, options) {
|
|
109
|
+
this.updateRenderer = new UpdateRenderer(tasks, options);
|
|
110
|
+
}
|
|
111
|
+
render() {
|
|
112
|
+
return this.updateRenderer.render();
|
|
113
|
+
}
|
|
114
|
+
end(err) {
|
|
115
|
+
this.updateRenderer.end(err);
|
|
116
|
+
if (typeof err === 'undefined') {
|
|
117
|
+
logUpdate.clear();
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
// persist the output
|
|
121
|
+
logUpdate.done();
|
|
122
|
+
// show errors
|
|
123
|
+
if (err) {
|
|
124
|
+
const errorCount = err.errors ? err.errors.length : 0;
|
|
125
|
+
if (errorCount > 0) {
|
|
126
|
+
const count = indentString(chalk.red.bold(`Found ${errorCount} error${errorCount > 1 ? 's' : ''}`), 1);
|
|
127
|
+
const details = err.errors
|
|
128
|
+
.map(error => {
|
|
129
|
+
debugLog(`[CLI] Exited with an error`, error);
|
|
130
|
+
return { msg: isDetailedError(error) ? error.details : null, rawError: error };
|
|
131
|
+
})
|
|
132
|
+
.map(({ msg, rawError }, i) => {
|
|
133
|
+
const source = err.errors[i].source;
|
|
134
|
+
msg = msg ? chalk.gray(indentString(stripIndent(`${msg}`), 4)) : null;
|
|
135
|
+
const stack = rawError.stack ? chalk.gray(indentString(stripIndent(rawError.stack), 4)) : null;
|
|
136
|
+
if (source) {
|
|
137
|
+
const sourceOfError = typeof source === 'string' ? source : source.name;
|
|
138
|
+
const title = indentString(`${logSymbols.error} ${sourceOfError}`, 2);
|
|
139
|
+
return [title, msg, stack, stack].filter(Boolean).join('\n');
|
|
140
|
+
}
|
|
141
|
+
return [msg, stack].filter(Boolean).join('\n');
|
|
142
|
+
})
|
|
143
|
+
.join('\n\n');
|
|
144
|
+
logUpdate.emit(['', count, details, ''].join('\n\n'));
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
const details = err.details ? err.details : '';
|
|
148
|
+
logUpdate.emit(`${chalk.red.bold(`${indentString(err.message, 2)}`)}\n${details}\n${chalk.grey(err.stack)}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
logUpdate.done();
|
|
152
|
+
printLogs();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const render = tasks => {
|
|
156
|
+
for (const task of tasks) {
|
|
157
|
+
task.subscribe(event => {
|
|
158
|
+
if (event.type === 'SUBTASKS') {
|
|
159
|
+
render(task.subtasks);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
if (event.type === 'DATA') {
|
|
163
|
+
logUpdate.emit(chalk.dim(`${event.data}`));
|
|
164
|
+
}
|
|
165
|
+
logUpdate.done();
|
|
166
|
+
}, err => {
|
|
167
|
+
logUpdate.emit(err);
|
|
168
|
+
logUpdate.done();
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
class ErrorRenderer {
|
|
173
|
+
constructor(tasks, _options) {
|
|
174
|
+
this.tasks = tasks;
|
|
175
|
+
}
|
|
176
|
+
render() {
|
|
177
|
+
render(this.tasks);
|
|
178
|
+
}
|
|
179
|
+
static get nonTTY() {
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
end() { }
|
|
183
|
+
}
|
|
184
|
+
class LogUpdate {
|
|
185
|
+
constructor() {
|
|
186
|
+
this.stream = process.stdout;
|
|
187
|
+
// state
|
|
188
|
+
this.previousLineCount = 0;
|
|
189
|
+
this.previousOutput = '';
|
|
190
|
+
this.previousWidth = this.getWidth();
|
|
191
|
+
}
|
|
192
|
+
emit(...args) {
|
|
193
|
+
let output = args.join(' ') + '\n';
|
|
194
|
+
const width = this.getWidth();
|
|
195
|
+
if (output === this.previousOutput && this.previousWidth === width) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
this.previousOutput = output;
|
|
199
|
+
this.previousWidth = width;
|
|
200
|
+
output = wrapAnsi(output, width, {
|
|
201
|
+
trim: false,
|
|
202
|
+
hard: true,
|
|
203
|
+
wordWrap: false,
|
|
204
|
+
});
|
|
205
|
+
this.stream.write(ansiEscapes.eraseLines(this.previousLineCount) + output);
|
|
206
|
+
this.previousLineCount = output.split('\n').length;
|
|
207
|
+
}
|
|
208
|
+
clear() {
|
|
209
|
+
this.stream.write(ansiEscapes.eraseLines(this.previousLineCount));
|
|
210
|
+
this.previousOutput = '';
|
|
211
|
+
this.previousWidth = this.getWidth();
|
|
212
|
+
this.previousLineCount = 0;
|
|
213
|
+
}
|
|
214
|
+
done() {
|
|
215
|
+
this.previousOutput = '';
|
|
216
|
+
this.previousWidth = this.getWidth();
|
|
217
|
+
this.previousLineCount = 0;
|
|
218
|
+
}
|
|
219
|
+
getWidth() {
|
|
220
|
+
const { columns } = this.stream;
|
|
221
|
+
if (!columns) {
|
|
222
|
+
return 80;
|
|
223
|
+
}
|
|
224
|
+
return columns;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
const logUpdate = new LogUpdate();
|
|
228
|
+
|
|
36
229
|
async function getPluginByName(name, pluginLoader) {
|
|
37
230
|
const possibleNames = [
|
|
38
231
|
`@graphql-codegen/${name}`,
|
|
@@ -114,22 +307,6 @@ async function getPresetByName(name, loader) {
|
|
|
114
307
|
`);
|
|
115
308
|
}
|
|
116
309
|
|
|
117
|
-
let logger;
|
|
118
|
-
function getLogger() {
|
|
119
|
-
return logger || dummyLogger;
|
|
120
|
-
}
|
|
121
|
-
useWinstonLogger();
|
|
122
|
-
function useWinstonLogger() {
|
|
123
|
-
if (logger && logger.levels) {
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
logger = console;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function debugLog(message, ...meta) {
|
|
130
|
-
if (!process.env.GQL_CODEGEN_NODEBUG && process.env.DEBUG !== undefined) ;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
310
|
const CodegenExtension = (api) => {
|
|
134
311
|
// Schema
|
|
135
312
|
api.loaders.schema.register(new CodeFileLoader({
|
|
@@ -546,6 +723,27 @@ function addHashToDocumentFiles(documentFilesPromise) {
|
|
|
546
723
|
}));
|
|
547
724
|
}
|
|
548
725
|
|
|
726
|
+
function isListrError(err) {
|
|
727
|
+
return err.name === 'ListrError' && Array.isArray(err.errors) && err.errors.length > 0;
|
|
728
|
+
}
|
|
729
|
+
function cliError(err, exitOnError = true) {
|
|
730
|
+
let msg;
|
|
731
|
+
if (err instanceof Error) {
|
|
732
|
+
msg = err.message || err.toString();
|
|
733
|
+
}
|
|
734
|
+
else if (typeof err === 'string') {
|
|
735
|
+
msg = err;
|
|
736
|
+
}
|
|
737
|
+
else {
|
|
738
|
+
msg = JSON.stringify(err);
|
|
739
|
+
}
|
|
740
|
+
// eslint-disable-next-line no-console
|
|
741
|
+
console.error(msg);
|
|
742
|
+
if (exitOnError) {
|
|
743
|
+
process.exit(1);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
549
747
|
const makeDefaultLoader = (from) => {
|
|
550
748
|
if (fs.statSync(from).isDirectory()) {
|
|
551
749
|
from = path.join(from, '__fake.js');
|
|
@@ -573,12 +771,39 @@ async function executeCodegen(input) {
|
|
|
573
771
|
const config = context.getConfig();
|
|
574
772
|
const pluginContext = context.getPluginContext();
|
|
575
773
|
const result = [];
|
|
774
|
+
const commonListrOptions = {
|
|
775
|
+
exitOnError: true,
|
|
776
|
+
};
|
|
777
|
+
let listr;
|
|
778
|
+
if (process.env.VERBOSE) {
|
|
779
|
+
listr = new Listr({
|
|
780
|
+
...commonListrOptions,
|
|
781
|
+
renderer: 'verbose',
|
|
782
|
+
nonTTYRenderer: 'verbose',
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
else if (process.env.NODE_ENV === 'test') {
|
|
786
|
+
listr = new Listr({
|
|
787
|
+
...commonListrOptions,
|
|
788
|
+
renderer: 'silent',
|
|
789
|
+
nonTTYRenderer: 'silent',
|
|
790
|
+
});
|
|
791
|
+
}
|
|
792
|
+
else {
|
|
793
|
+
listr = new Listr({
|
|
794
|
+
...commonListrOptions,
|
|
795
|
+
renderer: config.silent ? 'silent' : config.errorsOnly ? ErrorRenderer : Renderer,
|
|
796
|
+
nonTTYRenderer: config.silent ? 'silent' : 'default',
|
|
797
|
+
collapse: true,
|
|
798
|
+
clearOutput: false,
|
|
799
|
+
});
|
|
800
|
+
}
|
|
576
801
|
let rootConfig = {};
|
|
577
802
|
let rootSchemas;
|
|
578
803
|
let rootDocuments;
|
|
579
804
|
const generates = {};
|
|
580
805
|
const cache = createCache();
|
|
581
|
-
function wrapTask(task, source, taskName
|
|
806
|
+
function wrapTask(task, source, taskName) {
|
|
582
807
|
return () => {
|
|
583
808
|
return context.profiler.run(async () => {
|
|
584
809
|
try {
|
|
@@ -588,7 +813,6 @@ async function executeCodegen(input) {
|
|
|
588
813
|
if (source && !(error instanceof GraphQLError)) {
|
|
589
814
|
error.source = source;
|
|
590
815
|
}
|
|
591
|
-
ctx.errors.push(error);
|
|
592
816
|
throw error;
|
|
593
817
|
}
|
|
594
818
|
}, taskName);
|
|
@@ -659,109 +883,123 @@ async function executeCodegen(input) {
|
|
|
659
883
|
`);
|
|
660
884
|
}
|
|
661
885
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
{
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
const
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
const title = hasPreset
|
|
886
|
+
listr.add({
|
|
887
|
+
title: 'Parse configuration',
|
|
888
|
+
task: () => normalize(),
|
|
889
|
+
});
|
|
890
|
+
listr.add({
|
|
891
|
+
title: 'Generate outputs',
|
|
892
|
+
task: () => {
|
|
893
|
+
return new Listr(Object.keys(generates).map(filename => {
|
|
894
|
+
const outputConfig = generates[filename];
|
|
895
|
+
const hasPreset = !!outputConfig.preset;
|
|
896
|
+
return {
|
|
897
|
+
title: hasPreset
|
|
675
898
|
? `Generate to ${filename} (using EXPERIMENTAL preset "${outputConfig.preset}")`
|
|
676
|
-
: `Generate ${filename}
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
{
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
if (typeof denormalizedPtr === 'string') {
|
|
695
|
-
schemaPointerMap[denormalizedPtr] = {};
|
|
696
|
-
}
|
|
697
|
-
else if (typeof denormalizedPtr === 'object') {
|
|
698
|
-
Object.assign(schemaPointerMap, denormalizedPtr);
|
|
699
|
-
}
|
|
899
|
+
: `Generate ${filename}`,
|
|
900
|
+
task: () => {
|
|
901
|
+
let outputSchemaAst;
|
|
902
|
+
let outputSchema;
|
|
903
|
+
const outputFileTemplateConfig = outputConfig.config || {};
|
|
904
|
+
let outputDocuments = [];
|
|
905
|
+
const outputSpecificSchemas = normalizeInstanceOrArray(outputConfig.schema);
|
|
906
|
+
const outputSpecificDocuments = normalizeInstanceOrArray(outputConfig.documents);
|
|
907
|
+
return new Listr([
|
|
908
|
+
{
|
|
909
|
+
title: 'Load GraphQL schemas',
|
|
910
|
+
task: wrapTask(async () => {
|
|
911
|
+
debugLog(`[CLI] Loading Schemas`);
|
|
912
|
+
const schemaPointerMap = {};
|
|
913
|
+
const allSchemaUnnormalizedPointers = [...rootSchemas, ...outputSpecificSchemas];
|
|
914
|
+
for (const unnormalizedPtr of allSchemaUnnormalizedPointers) {
|
|
915
|
+
if (typeof unnormalizedPtr === 'string') {
|
|
916
|
+
schemaPointerMap[unnormalizedPtr] = {};
|
|
700
917
|
}
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
const outputSchemaAst = await context.loadSchema(schemaPointerMap);
|
|
704
|
-
const outputSchema = getCachedDocumentNodeFromSchema(outputSchemaAst);
|
|
705
|
-
return {
|
|
706
|
-
outputSchemaAst,
|
|
707
|
-
outputSchema,
|
|
708
|
-
};
|
|
709
|
-
});
|
|
710
|
-
outputSchemaAst = result.outputSchemaAst;
|
|
711
|
-
outputSchema = result.outputSchema;
|
|
712
|
-
}, filename, `Load GraphQL schemas: ${filename}`, ctx),
|
|
713
|
-
},
|
|
714
|
-
{
|
|
715
|
-
title: 'Load GraphQL documents',
|
|
716
|
-
task: wrapTask(async () => {
|
|
717
|
-
debugLog(`[CLI] Loading Documents`);
|
|
718
|
-
const documentPointerMap = {};
|
|
719
|
-
const allDocumentsDenormalizedPointers = [...rootDocuments, ...outputSpecificDocuments];
|
|
720
|
-
for (const denormalizedPtr of allDocumentsDenormalizedPointers) {
|
|
721
|
-
if (typeof denormalizedPtr === 'string') {
|
|
722
|
-
documentPointerMap[denormalizedPtr] = {};
|
|
723
|
-
}
|
|
724
|
-
else if (typeof denormalizedPtr === 'object') {
|
|
725
|
-
Object.assign(documentPointerMap, denormalizedPtr);
|
|
726
|
-
}
|
|
918
|
+
else if (typeof unnormalizedPtr === 'object') {
|
|
919
|
+
Object.assign(schemaPointerMap, unnormalizedPtr);
|
|
727
920
|
}
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
921
|
+
}
|
|
922
|
+
const hash = JSON.stringify(schemaPointerMap);
|
|
923
|
+
const result = await cache('schema', hash, async () => {
|
|
924
|
+
const outputSchemaAst = await context.loadSchema(schemaPointerMap);
|
|
925
|
+
const outputSchema = getCachedDocumentNodeFromSchema(outputSchemaAst);
|
|
926
|
+
return {
|
|
927
|
+
outputSchemaAst,
|
|
928
|
+
outputSchema,
|
|
929
|
+
};
|
|
930
|
+
});
|
|
931
|
+
outputSchemaAst = await result.outputSchemaAst;
|
|
932
|
+
outputSchema = result.outputSchema;
|
|
933
|
+
}, filename, `Load GraphQL schemas: ${filename}`),
|
|
934
|
+
},
|
|
935
|
+
{
|
|
936
|
+
title: 'Load GraphQL documents',
|
|
937
|
+
task: wrapTask(async () => {
|
|
938
|
+
debugLog(`[CLI] Loading Documents`);
|
|
939
|
+
// get different cache for shared docs and output specific docs
|
|
940
|
+
const documentPointerMap = {};
|
|
941
|
+
const allDocumentsUnnormalizedPointers = [...rootDocuments, ...outputSpecificDocuments];
|
|
942
|
+
for (const unnormalizedPtr of allDocumentsUnnormalizedPointers) {
|
|
943
|
+
if (typeof unnormalizedPtr === 'string') {
|
|
944
|
+
documentPointerMap[unnormalizedPtr] = {};
|
|
945
|
+
}
|
|
946
|
+
else if (typeof unnormalizedPtr === 'object') {
|
|
947
|
+
Object.assign(documentPointerMap, unnormalizedPtr);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
const hash = JSON.stringify(documentPointerMap);
|
|
951
|
+
const result = await cache('documents', hash, async () => {
|
|
952
|
+
const documents = await context.loadDocuments(documentPointerMap);
|
|
953
|
+
return {
|
|
954
|
+
documents,
|
|
760
955
|
};
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
956
|
+
});
|
|
957
|
+
outputDocuments = await result.documents;
|
|
958
|
+
}, filename, `Load GraphQL documents: ${filename}`),
|
|
959
|
+
},
|
|
960
|
+
{
|
|
961
|
+
title: 'Generate',
|
|
962
|
+
task: wrapTask(async () => {
|
|
963
|
+
debugLog(`[CLI] Generating output`);
|
|
964
|
+
const normalizedPluginsArray = normalizeConfig(outputConfig.plugins);
|
|
965
|
+
const pluginLoader = config.pluginLoader || makeDefaultLoader(context.cwd);
|
|
966
|
+
const pluginPackages = await Promise.all(normalizedPluginsArray.map(plugin => getPluginByName(Object.keys(plugin)[0], pluginLoader)));
|
|
967
|
+
const pluginMap = {};
|
|
968
|
+
const preset = hasPreset
|
|
969
|
+
? typeof outputConfig.preset === 'string'
|
|
970
|
+
? await getPresetByName(outputConfig.preset, makeDefaultLoader(context.cwd))
|
|
971
|
+
: outputConfig.preset
|
|
972
|
+
: null;
|
|
973
|
+
pluginPackages.forEach((pluginPackage, i) => {
|
|
974
|
+
const plugin = normalizedPluginsArray[i];
|
|
975
|
+
const name = Object.keys(plugin)[0];
|
|
976
|
+
pluginMap[name] = pluginPackage;
|
|
977
|
+
});
|
|
978
|
+
const mergedConfig = {
|
|
979
|
+
...rootConfig,
|
|
980
|
+
...(typeof outputFileTemplateConfig === 'string'
|
|
981
|
+
? { value: outputFileTemplateConfig }
|
|
982
|
+
: outputFileTemplateConfig),
|
|
983
|
+
};
|
|
984
|
+
let outputs = [];
|
|
985
|
+
if (hasPreset) {
|
|
986
|
+
outputs = await context.profiler.run(async () => preset.buildGeneratesSection({
|
|
987
|
+
baseOutputDir: filename,
|
|
988
|
+
presetConfig: outputConfig.presetConfig || {},
|
|
989
|
+
plugins: normalizedPluginsArray,
|
|
990
|
+
schema: outputSchema,
|
|
991
|
+
schemaAst: outputSchemaAst,
|
|
992
|
+
documents: outputDocuments,
|
|
993
|
+
config: mergedConfig,
|
|
994
|
+
pluginMap,
|
|
995
|
+
pluginContext,
|
|
996
|
+
profiler: context.profiler,
|
|
997
|
+
}), `Build Generates Section: ${filename}`);
|
|
998
|
+
}
|
|
999
|
+
else {
|
|
1000
|
+
outputs = [
|
|
1001
|
+
{
|
|
1002
|
+
filename,
|
|
765
1003
|
plugins: normalizedPluginsArray,
|
|
766
1004
|
schema: outputSchema,
|
|
767
1005
|
schemaAst: outputSchemaAst,
|
|
@@ -770,67 +1008,50 @@ async function executeCodegen(input) {
|
|
|
770
1008
|
pluginMap,
|
|
771
1009
|
pluginContext,
|
|
772
1010
|
profiler: context.profiler,
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
], {
|
|
802
|
-
// it stops when of the tasks failed
|
|
803
|
-
exitOnError: true,
|
|
804
|
-
});
|
|
805
|
-
},
|
|
806
|
-
// It doesn't stop when one of tasks failed, to finish at least some of outputs
|
|
807
|
-
exitOnError: false,
|
|
808
|
-
concurrent: cpus().length,
|
|
809
|
-
};
|
|
810
|
-
});
|
|
811
|
-
return task.newListr(generateTasks);
|
|
812
|
-
},
|
|
813
|
-
},
|
|
814
|
-
], {
|
|
815
|
-
rendererOptions: {
|
|
816
|
-
clearOutput: false,
|
|
817
|
-
collapse: true,
|
|
1011
|
+
},
|
|
1012
|
+
];
|
|
1013
|
+
}
|
|
1014
|
+
const process = async (outputArgs) => {
|
|
1015
|
+
const output = await codegen({
|
|
1016
|
+
...outputArgs,
|
|
1017
|
+
cache,
|
|
1018
|
+
});
|
|
1019
|
+
result.push({
|
|
1020
|
+
filename: outputArgs.filename,
|
|
1021
|
+
content: output,
|
|
1022
|
+
hooks: outputConfig.hooks || {},
|
|
1023
|
+
});
|
|
1024
|
+
};
|
|
1025
|
+
await context.profiler.run(() => Promise.all(outputs.map(process)), `Codegen: ${filename}`);
|
|
1026
|
+
}, filename, `Generate: ${filename}`),
|
|
1027
|
+
},
|
|
1028
|
+
], {
|
|
1029
|
+
// it stops when one of tasks failed
|
|
1030
|
+
exitOnError: true,
|
|
1031
|
+
});
|
|
1032
|
+
},
|
|
1033
|
+
};
|
|
1034
|
+
}), {
|
|
1035
|
+
// it doesn't stop when one of tasks failed, to finish at least some of outputs
|
|
1036
|
+
exitOnError: false,
|
|
1037
|
+
concurrent: cpus().length,
|
|
1038
|
+
});
|
|
818
1039
|
},
|
|
819
|
-
ctx: { errors: [] },
|
|
820
|
-
rendererSilent: isTest || config.silent,
|
|
821
|
-
exitOnError: true,
|
|
822
1040
|
});
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
1041
|
+
try {
|
|
1042
|
+
await listr.run();
|
|
1043
|
+
}
|
|
1044
|
+
catch (err) {
|
|
1045
|
+
if (isListrError(err)) {
|
|
1046
|
+
const allErrs = err.errors.map(subErr => isDetailedError(subErr)
|
|
1047
|
+
? `${subErr.message} for "${subErr.source}"${subErr.details}`
|
|
1048
|
+
: subErr.message || subErr.toString());
|
|
1049
|
+
const newErr = new AggregateError(err.errors, `${err.message} ${allErrs.join('\n\n')}`);
|
|
1050
|
+
// Best-effort to all stack traces for debugging
|
|
1051
|
+
newErr.stack = `${newErr.stack}\n\n${err.errors.map(subErr => subErr.stack).join('\n\n')}`;
|
|
1052
|
+
throw newErr;
|
|
1053
|
+
}
|
|
1054
|
+
throw err;
|
|
834
1055
|
}
|
|
835
1056
|
return result;
|
|
836
1057
|
}
|
|
@@ -890,7 +1111,7 @@ function execShellCommand(cmd) {
|
|
|
890
1111
|
});
|
|
891
1112
|
}
|
|
892
1113
|
async function executeHooks(hookName, scripts = [], args = []) {
|
|
893
|
-
debugLog();
|
|
1114
|
+
debugLog(`Running lifecycle hook "${hookName}" scripts...`);
|
|
894
1115
|
for (const script of scripts) {
|
|
895
1116
|
if (typeof script === 'string') {
|
|
896
1117
|
debugLog(`Running lifecycle hook "${hookName}" script: ${script} with args: ${args.join(' ')}...`);
|
|
@@ -924,7 +1145,7 @@ function emitWatching() {
|
|
|
924
1145
|
log(`${logSymbols.info} Watching for changes...`);
|
|
925
1146
|
}
|
|
926
1147
|
const createWatcher = (initalContext, onNext) => {
|
|
927
|
-
debugLog();
|
|
1148
|
+
debugLog(`[Watcher] Starting watcher...`);
|
|
928
1149
|
let config = initalContext.getConfig();
|
|
929
1150
|
const files = [initalContext.filepath].filter(a => a);
|
|
930
1151
|
const documents = normalizeInstanceOrArray(config.documents);
|
|
@@ -995,10 +1216,10 @@ const createWatcher = (initalContext, onNext) => {
|
|
|
995
1216
|
atomic: true,
|
|
996
1217
|
ignored,
|
|
997
1218
|
});
|
|
998
|
-
debugLog();
|
|
1219
|
+
debugLog(`[Watcher] Started`);
|
|
999
1220
|
const shutdown = () => {
|
|
1000
1221
|
isShutdown = true;
|
|
1001
|
-
debugLog();
|
|
1222
|
+
debugLog(`[Watcher] Shutting down`);
|
|
1002
1223
|
log(`Shutting down watch...`);
|
|
1003
1224
|
watcher.close();
|
|
1004
1225
|
lifecycleHooks(config.hooks).beforeDone();
|
|
@@ -1006,7 +1227,7 @@ const createWatcher = (initalContext, onNext) => {
|
|
|
1006
1227
|
// it doesn't matter what has changed, need to run whole process anyway
|
|
1007
1228
|
watcher.on('all', async (eventName, path) => {
|
|
1008
1229
|
lifecycleHooks(config.hooks).onWatchTriggered(eventName, path);
|
|
1009
|
-
debugLog();
|
|
1230
|
+
debugLog(`[Watcher] triggered due to a file ${eventName} event: ${path}`);
|
|
1010
1231
|
const fullPath = join(process.cwd(), path);
|
|
1011
1232
|
// In ESM require is not defined
|
|
1012
1233
|
try {
|
|
@@ -1075,10 +1296,10 @@ async function generate(input, saveToFile = true) {
|
|
|
1075
1296
|
return unlinkFile(filename, err => {
|
|
1076
1297
|
const prettyFilename = filename.replace(`${input.cwd || process.cwd()}/`, '');
|
|
1077
1298
|
if (err) {
|
|
1078
|
-
debugLog();
|
|
1299
|
+
debugLog(`Cannot remove stale file: ${prettyFilename}\n${err}`);
|
|
1079
1300
|
}
|
|
1080
1301
|
else {
|
|
1081
|
-
debugLog();
|
|
1302
|
+
debugLog(`Removed stale file: ${prettyFilename}`);
|
|
1082
1303
|
}
|
|
1083
1304
|
});
|
|
1084
1305
|
}
|
|
@@ -1145,7 +1366,7 @@ function shouldOverwrite(config, outputPath) {
|
|
|
1145
1366
|
const globalValue = config.overwrite === undefined ? true : !!config.overwrite;
|
|
1146
1367
|
const outputConfig = config.generates[outputPath];
|
|
1147
1368
|
if (!outputConfig) {
|
|
1148
|
-
debugLog();
|
|
1369
|
+
debugLog(`Couldn't find a config of ${outputPath}`);
|
|
1149
1370
|
return globalValue;
|
|
1150
1371
|
}
|
|
1151
1372
|
if (isConfiguredOutput(outputConfig) && typeof outputConfig.overwrite === 'boolean') {
|
|
@@ -1606,40 +1827,18 @@ function addIntrospection(config) {
|
|
|
1606
1827
|
};
|
|
1607
1828
|
}
|
|
1608
1829
|
|
|
1609
|
-
function isListrError(err) {
|
|
1610
|
-
return err.name === 'ListrError' && Array.isArray(err.errors) && err.errors.length > 0;
|
|
1611
|
-
}
|
|
1612
|
-
function cliError(err, exitOnError = true) {
|
|
1613
|
-
let msg;
|
|
1614
|
-
if (err instanceof Error) {
|
|
1615
|
-
msg = err.message || err.toString();
|
|
1616
|
-
}
|
|
1617
|
-
else if (typeof err === 'string') {
|
|
1618
|
-
msg = err;
|
|
1619
|
-
}
|
|
1620
|
-
else {
|
|
1621
|
-
msg = JSON.stringify(err);
|
|
1622
|
-
}
|
|
1623
|
-
// eslint-disable-next-line no-console
|
|
1624
|
-
console.error(msg);
|
|
1625
|
-
if (exitOnError) {
|
|
1626
|
-
process.exit(1);
|
|
1627
|
-
}
|
|
1628
|
-
}
|
|
1629
|
-
|
|
1630
1830
|
async function runCli(cmd) {
|
|
1631
1831
|
await ensureGraphQlPackage();
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
}
|
|
1832
|
+
if (cmd === 'init') {
|
|
1833
|
+
return init();
|
|
1834
|
+
}
|
|
1835
|
+
const context = await createContext();
|
|
1836
|
+
try {
|
|
1837
|
+
return await generate(context);
|
|
1838
|
+
}
|
|
1839
|
+
catch (error) {
|
|
1840
|
+
await lifecycleHooks(context.getConfig().hooks).onError(error.toString());
|
|
1841
|
+
throw error;
|
|
1643
1842
|
}
|
|
1644
1843
|
}
|
|
1645
1844
|
async function ensureGraphQlPackage() {
|