@graphql-codegen/cli 2.7.1-alpha-223b75f49.0 → 2.7.1-alpha-23dfe4aea.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/cjs/codegen.js +186 -161
- package/cjs/init/helpers.js +4 -4
- package/cjs/utils/get-latest-version.js +15 -0
- package/cjs/utils/indentString.js +37 -0
- package/cjs/utils/listr-renderer.js +136 -0
- package/esm/codegen.js +186 -161
- package/esm/init/helpers.js +1 -1
- package/esm/utils/get-latest-version.js +11 -0
- package/esm/utils/indentString.js +33 -0
- package/esm/utils/listr-renderer.js +130 -0
- package/package.json +7 -3
- package/typings/utils/get-latest-version.d.ts +6 -0
- package/typings/utils/indentString.d.ts +26 -0
- package/typings/utils/listr-renderer.d.ts +18 -0
package/esm/codegen.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DetailedError, normalizeOutputParam, normalizeInstanceOrArray, normalizeConfig, getCachedDocumentNodeFromSchema, isDetailedError, } from '@graphql-codegen/plugin-helpers';
|
|
2
2
|
import { codegen } from '@graphql-codegen/core';
|
|
3
3
|
import { AggregateError } from '@graphql-tools/utils';
|
|
4
|
+
import { Renderer, ErrorRenderer } from './utils/listr-renderer.js';
|
|
4
5
|
import { GraphQLError } from 'graphql';
|
|
5
6
|
import { getPluginByName } from './plugins.js';
|
|
6
7
|
import { getPresetByName } from './presets.js';
|
|
@@ -10,7 +11,8 @@ import fs from 'fs';
|
|
|
10
11
|
import path from 'path';
|
|
11
12
|
import { cpus } from 'os';
|
|
12
13
|
import { createRequire } from 'module';
|
|
13
|
-
import
|
|
14
|
+
import Listr from 'listr';
|
|
15
|
+
import { isListrError } from './utils/cli-error.js';
|
|
14
16
|
/**
|
|
15
17
|
* Poor mans ESM detection.
|
|
16
18
|
* Looking at this and you have a better method?
|
|
@@ -51,12 +53,39 @@ export async function executeCodegen(input) {
|
|
|
51
53
|
const config = context.getConfig();
|
|
52
54
|
const pluginContext = context.getPluginContext();
|
|
53
55
|
const result = [];
|
|
56
|
+
const commonListrOptions = {
|
|
57
|
+
exitOnError: true,
|
|
58
|
+
};
|
|
59
|
+
let listr;
|
|
60
|
+
if (process.env.VERBOSE) {
|
|
61
|
+
listr = new Listr({
|
|
62
|
+
...commonListrOptions,
|
|
63
|
+
renderer: 'verbose',
|
|
64
|
+
nonTTYRenderer: 'verbose',
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
else if (process.env.NODE_ENV === 'test') {
|
|
68
|
+
listr = new Listr({
|
|
69
|
+
...commonListrOptions,
|
|
70
|
+
renderer: 'silent',
|
|
71
|
+
nonTTYRenderer: 'silent',
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
listr = new Listr({
|
|
76
|
+
...commonListrOptions,
|
|
77
|
+
renderer: config.silent ? 'silent' : config.errorsOnly ? ErrorRenderer : Renderer,
|
|
78
|
+
nonTTYRenderer: config.silent ? 'silent' : 'default',
|
|
79
|
+
collapse: true,
|
|
80
|
+
clearOutput: false,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
54
83
|
let rootConfig = {};
|
|
55
84
|
let rootSchemas;
|
|
56
85
|
let rootDocuments;
|
|
57
86
|
const generates = {};
|
|
58
87
|
const cache = createCache();
|
|
59
|
-
function wrapTask(task, source, taskName
|
|
88
|
+
function wrapTask(task, source, taskName) {
|
|
60
89
|
return () => {
|
|
61
90
|
return context.profiler.run(async () => {
|
|
62
91
|
try {
|
|
@@ -66,7 +95,6 @@ export async function executeCodegen(input) {
|
|
|
66
95
|
if (source && !(error instanceof GraphQLError)) {
|
|
67
96
|
error.source = source;
|
|
68
97
|
}
|
|
69
|
-
ctx.errors.push(error);
|
|
70
98
|
throw error;
|
|
71
99
|
}
|
|
72
100
|
}, taskName);
|
|
@@ -137,109 +165,123 @@ export async function executeCodegen(input) {
|
|
|
137
165
|
`);
|
|
138
166
|
}
|
|
139
167
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
{
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const title = hasPreset
|
|
168
|
+
listr.add({
|
|
169
|
+
title: 'Parse configuration',
|
|
170
|
+
task: () => normalize(),
|
|
171
|
+
});
|
|
172
|
+
listr.add({
|
|
173
|
+
title: 'Generate outputs',
|
|
174
|
+
task: () => {
|
|
175
|
+
return new Listr(Object.keys(generates).map(filename => {
|
|
176
|
+
const outputConfig = generates[filename];
|
|
177
|
+
const hasPreset = !!outputConfig.preset;
|
|
178
|
+
return {
|
|
179
|
+
title: hasPreset
|
|
153
180
|
? `Generate to ${filename} (using EXPERIMENTAL preset "${outputConfig.preset}")`
|
|
154
|
-
: `Generate ${filename}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
{
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if (typeof denormalizedPtr === 'string') {
|
|
173
|
-
schemaPointerMap[denormalizedPtr] = {};
|
|
174
|
-
}
|
|
175
|
-
else if (typeof denormalizedPtr === 'object') {
|
|
176
|
-
Object.assign(schemaPointerMap, denormalizedPtr);
|
|
177
|
-
}
|
|
181
|
+
: `Generate ${filename}`,
|
|
182
|
+
task: () => {
|
|
183
|
+
let outputSchemaAst;
|
|
184
|
+
let outputSchema;
|
|
185
|
+
const outputFileTemplateConfig = outputConfig.config || {};
|
|
186
|
+
let outputDocuments = [];
|
|
187
|
+
const outputSpecificSchemas = normalizeInstanceOrArray(outputConfig.schema);
|
|
188
|
+
const outputSpecificDocuments = normalizeInstanceOrArray(outputConfig.documents);
|
|
189
|
+
return new Listr([
|
|
190
|
+
{
|
|
191
|
+
title: 'Load GraphQL schemas',
|
|
192
|
+
task: wrapTask(async () => {
|
|
193
|
+
debugLog(`[CLI] Loading Schemas`);
|
|
194
|
+
const schemaPointerMap = {};
|
|
195
|
+
const allSchemaUnnormalizedPointers = [...rootSchemas, ...outputSpecificSchemas];
|
|
196
|
+
for (const unnormalizedPtr of allSchemaUnnormalizedPointers) {
|
|
197
|
+
if (typeof unnormalizedPtr === 'string') {
|
|
198
|
+
schemaPointerMap[unnormalizedPtr] = {};
|
|
178
199
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
const outputSchemaAst = await context.loadSchema(schemaPointerMap);
|
|
182
|
-
const outputSchema = getCachedDocumentNodeFromSchema(outputSchemaAst);
|
|
183
|
-
return {
|
|
184
|
-
outputSchemaAst,
|
|
185
|
-
outputSchema,
|
|
186
|
-
};
|
|
187
|
-
});
|
|
188
|
-
outputSchemaAst = result.outputSchemaAst;
|
|
189
|
-
outputSchema = result.outputSchema;
|
|
190
|
-
}, filename, `Load GraphQL schemas: ${filename}`, ctx),
|
|
191
|
-
},
|
|
192
|
-
{
|
|
193
|
-
title: 'Load GraphQL documents',
|
|
194
|
-
task: wrapTask(async () => {
|
|
195
|
-
debugLog(`[CLI] Loading Documents`);
|
|
196
|
-
const documentPointerMap = {};
|
|
197
|
-
const allDocumentsDenormalizedPointers = [...rootDocuments, ...outputSpecificDocuments];
|
|
198
|
-
for (const denormalizedPtr of allDocumentsDenormalizedPointers) {
|
|
199
|
-
if (typeof denormalizedPtr === 'string') {
|
|
200
|
-
documentPointerMap[denormalizedPtr] = {};
|
|
201
|
-
}
|
|
202
|
-
else if (typeof denormalizedPtr === 'object') {
|
|
203
|
-
Object.assign(documentPointerMap, denormalizedPtr);
|
|
204
|
-
}
|
|
200
|
+
else if (typeof unnormalizedPtr === 'object') {
|
|
201
|
+
Object.assign(schemaPointerMap, unnormalizedPtr);
|
|
205
202
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}, filename, `Load GraphQL documents: ${filename}`, ctx),
|
|
215
|
-
},
|
|
216
|
-
{
|
|
217
|
-
title: 'Generate',
|
|
218
|
-
task: wrapTask(async () => {
|
|
219
|
-
debugLog(`[CLI] Generating output`);
|
|
220
|
-
const normalizedPluginsArray = normalizeConfig(outputConfig.plugins);
|
|
221
|
-
const pluginLoader = config.pluginLoader || makeDefaultLoader(context.cwd);
|
|
222
|
-
const pluginPackages = await Promise.all(normalizedPluginsArray.map(plugin => getPluginByName(Object.keys(plugin)[0], pluginLoader)));
|
|
223
|
-
const preset = hasPreset
|
|
224
|
-
? typeof outputConfig.preset === 'string'
|
|
225
|
-
? await getPresetByName(outputConfig.preset, makeDefaultLoader(context.cwd))
|
|
226
|
-
: outputConfig.preset
|
|
227
|
-
: null;
|
|
228
|
-
const pluginMap = Object.fromEntries(pluginPackages.map((pkg, i) => {
|
|
229
|
-
const plugin = normalizedPluginsArray[i];
|
|
230
|
-
const name = Object.keys(plugin)[0];
|
|
231
|
-
return [name, pkg];
|
|
232
|
-
}));
|
|
233
|
-
const mergedConfig = {
|
|
234
|
-
...rootConfig,
|
|
235
|
-
...(typeof outputFileTemplateConfig === 'string'
|
|
236
|
-
? { value: outputFileTemplateConfig }
|
|
237
|
-
: outputFileTemplateConfig),
|
|
203
|
+
}
|
|
204
|
+
const hash = JSON.stringify(schemaPointerMap);
|
|
205
|
+
const result = await cache('schema', hash, async () => {
|
|
206
|
+
const outputSchemaAst = await context.loadSchema(schemaPointerMap);
|
|
207
|
+
const outputSchema = getCachedDocumentNodeFromSchema(outputSchemaAst);
|
|
208
|
+
return {
|
|
209
|
+
outputSchemaAst,
|
|
210
|
+
outputSchema,
|
|
238
211
|
};
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
212
|
+
});
|
|
213
|
+
outputSchemaAst = await result.outputSchemaAst;
|
|
214
|
+
outputSchema = result.outputSchema;
|
|
215
|
+
}, filename, `Load GraphQL schemas: ${filename}`),
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
title: 'Load GraphQL documents',
|
|
219
|
+
task: wrapTask(async () => {
|
|
220
|
+
debugLog(`[CLI] Loading Documents`);
|
|
221
|
+
// get different cache for shared docs and output specific docs
|
|
222
|
+
const documentPointerMap = {};
|
|
223
|
+
const allDocumentsUnnormalizedPointers = [...rootDocuments, ...outputSpecificDocuments];
|
|
224
|
+
for (const unnormalizedPtr of allDocumentsUnnormalizedPointers) {
|
|
225
|
+
if (typeof unnormalizedPtr === 'string') {
|
|
226
|
+
documentPointerMap[unnormalizedPtr] = {};
|
|
227
|
+
}
|
|
228
|
+
else if (typeof unnormalizedPtr === 'object') {
|
|
229
|
+
Object.assign(documentPointerMap, unnormalizedPtr);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
const hash = JSON.stringify(documentPointerMap);
|
|
233
|
+
const result = await cache('documents', hash, async () => {
|
|
234
|
+
const documents = await context.loadDocuments(documentPointerMap);
|
|
235
|
+
return {
|
|
236
|
+
documents,
|
|
237
|
+
};
|
|
238
|
+
});
|
|
239
|
+
outputDocuments = await result.documents;
|
|
240
|
+
}, filename, `Load GraphQL documents: ${filename}`),
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
title: 'Generate',
|
|
244
|
+
task: wrapTask(async () => {
|
|
245
|
+
debugLog(`[CLI] Generating output`);
|
|
246
|
+
const normalizedPluginsArray = normalizeConfig(outputConfig.plugins);
|
|
247
|
+
const pluginLoader = config.pluginLoader || makeDefaultLoader(context.cwd);
|
|
248
|
+
const pluginPackages = await Promise.all(normalizedPluginsArray.map(plugin => getPluginByName(Object.keys(plugin)[0], pluginLoader)));
|
|
249
|
+
const pluginMap = {};
|
|
250
|
+
const preset = hasPreset
|
|
251
|
+
? typeof outputConfig.preset === 'string'
|
|
252
|
+
? await getPresetByName(outputConfig.preset, makeDefaultLoader(context.cwd))
|
|
253
|
+
: outputConfig.preset
|
|
254
|
+
: null;
|
|
255
|
+
pluginPackages.forEach((pluginPackage, i) => {
|
|
256
|
+
const plugin = normalizedPluginsArray[i];
|
|
257
|
+
const name = Object.keys(plugin)[0];
|
|
258
|
+
pluginMap[name] = pluginPackage;
|
|
259
|
+
});
|
|
260
|
+
const mergedConfig = {
|
|
261
|
+
...rootConfig,
|
|
262
|
+
...(typeof outputFileTemplateConfig === 'string'
|
|
263
|
+
? { value: outputFileTemplateConfig }
|
|
264
|
+
: outputFileTemplateConfig),
|
|
265
|
+
};
|
|
266
|
+
let outputs = [];
|
|
267
|
+
if (hasPreset) {
|
|
268
|
+
outputs = await context.profiler.run(async () => preset.buildGeneratesSection({
|
|
269
|
+
baseOutputDir: filename,
|
|
270
|
+
presetConfig: outputConfig.presetConfig || {},
|
|
271
|
+
plugins: normalizedPluginsArray,
|
|
272
|
+
schema: outputSchema,
|
|
273
|
+
schemaAst: outputSchemaAst,
|
|
274
|
+
documents: outputDocuments,
|
|
275
|
+
config: mergedConfig,
|
|
276
|
+
pluginMap,
|
|
277
|
+
pluginContext,
|
|
278
|
+
profiler: context.profiler,
|
|
279
|
+
}), `Build Generates Section: ${filename}`);
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
outputs = [
|
|
283
|
+
{
|
|
284
|
+
filename,
|
|
243
285
|
plugins: normalizedPluginsArray,
|
|
244
286
|
schema: outputSchema,
|
|
245
287
|
schemaAst: outputSchemaAst,
|
|
@@ -248,67 +290,50 @@ export async function executeCodegen(input) {
|
|
|
248
290
|
pluginMap,
|
|
249
291
|
pluginContext,
|
|
250
292
|
profiler: context.profiler,
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
], {
|
|
280
|
-
// it stops when of the tasks failed
|
|
281
|
-
exitOnError: true,
|
|
282
|
-
});
|
|
283
|
-
},
|
|
284
|
-
// It doesn't stop when one of tasks failed, to finish at least some of outputs
|
|
285
|
-
exitOnError: false,
|
|
286
|
-
concurrent: cpus().length,
|
|
287
|
-
};
|
|
288
|
-
});
|
|
289
|
-
return task.newListr(generateTasks);
|
|
290
|
-
},
|
|
291
|
-
},
|
|
292
|
-
], {
|
|
293
|
-
rendererOptions: {
|
|
294
|
-
clearOutput: false,
|
|
295
|
-
collapse: true,
|
|
293
|
+
},
|
|
294
|
+
];
|
|
295
|
+
}
|
|
296
|
+
const process = async (outputArgs) => {
|
|
297
|
+
const output = await codegen({
|
|
298
|
+
...outputArgs,
|
|
299
|
+
cache,
|
|
300
|
+
});
|
|
301
|
+
result.push({
|
|
302
|
+
filename: outputArgs.filename,
|
|
303
|
+
content: output,
|
|
304
|
+
hooks: outputConfig.hooks || {},
|
|
305
|
+
});
|
|
306
|
+
};
|
|
307
|
+
await context.profiler.run(() => Promise.all(outputs.map(process)), `Codegen: ${filename}`);
|
|
308
|
+
}, filename, `Generate: ${filename}`),
|
|
309
|
+
},
|
|
310
|
+
], {
|
|
311
|
+
// it stops when one of tasks failed
|
|
312
|
+
exitOnError: true,
|
|
313
|
+
});
|
|
314
|
+
},
|
|
315
|
+
};
|
|
316
|
+
}), {
|
|
317
|
+
// it doesn't stop when one of tasks failed, to finish at least some of outputs
|
|
318
|
+
exitOnError: false,
|
|
319
|
+
concurrent: cpus().length,
|
|
320
|
+
});
|
|
296
321
|
},
|
|
297
|
-
ctx: { errors: [] },
|
|
298
|
-
rendererSilent: isTest || config.silent,
|
|
299
|
-
exitOnError: true,
|
|
300
322
|
});
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
323
|
+
try {
|
|
324
|
+
await listr.run();
|
|
325
|
+
}
|
|
326
|
+
catch (err) {
|
|
327
|
+
if (isListrError(err)) {
|
|
328
|
+
const allErrs = err.errors.map(subErr => isDetailedError(subErr)
|
|
329
|
+
? `${subErr.message} for "${subErr.source}"${subErr.details}`
|
|
330
|
+
: subErr.message || subErr.toString());
|
|
331
|
+
const newErr = new AggregateError(err.errors, `${err.message} ${allErrs.join('\n\n')}`);
|
|
332
|
+
// Best-effort to all stack traces for debugging
|
|
333
|
+
newErr.stack = `${newErr.stack}\n\n${err.errors.map(subErr => subErr.stack).join('\n\n')}`;
|
|
334
|
+
throw newErr;
|
|
335
|
+
}
|
|
336
|
+
throw err;
|
|
312
337
|
}
|
|
313
338
|
return result;
|
|
314
339
|
}
|
package/esm/init/helpers.js
CHANGED
|
@@ -2,7 +2,7 @@ import chalk from 'chalk';
|
|
|
2
2
|
import { resolve, relative } from 'path';
|
|
3
3
|
import { writeFileSync, readFileSync } from 'fs';
|
|
4
4
|
import detectIndent from 'detect-indent';
|
|
5
|
-
import getLatestVersion from 'latest-version';
|
|
5
|
+
import { getLatestVersion } from '../utils/get-latest-version.js';
|
|
6
6
|
// Parses config and writes it to a file
|
|
7
7
|
export async function writeConfig(answers, config) {
|
|
8
8
|
const YAML = await import('json-to-pretty-yaml').then(m => ('default' in m ? m.default : m));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { fetch } from 'cross-undici-fetch';
|
|
2
|
+
/**
|
|
3
|
+
* Fetches the version directly from the registry instead of depending on
|
|
4
|
+
* an ESM only module as latest-version does.
|
|
5
|
+
* @param packageName
|
|
6
|
+
*/
|
|
7
|
+
export async function getLatestVersion(packageName) {
|
|
8
|
+
return fetch(`https://unpkg.com/${packageName}/package.json`)
|
|
9
|
+
.then(res => res.json())
|
|
10
|
+
.then(pkg => pkg.version);
|
|
11
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Indent each line in a string.
|
|
3
|
+
@param string - The string to indent.
|
|
4
|
+
@param count - How many times you want `options.indent` repeated. Default: `1`.
|
|
5
|
+
@example
|
|
6
|
+
```
|
|
7
|
+
import indentString from 'indent-string';
|
|
8
|
+
indentString('Unicorns\nRainbows', 4);
|
|
9
|
+
//=> ' Unicorns\n Rainbows'
|
|
10
|
+
indentString('Unicorns\nRainbows', 4, {indent: '♥'});
|
|
11
|
+
//=> '♥♥♥♥Unicorns\n♥♥♥♥Rainbows'
|
|
12
|
+
```
|
|
13
|
+
*/
|
|
14
|
+
export function indentString(string, count = 1, options = {}) {
|
|
15
|
+
const { indent = ' ', includeEmptyLines = false } = options;
|
|
16
|
+
if (typeof string !== 'string') {
|
|
17
|
+
throw new TypeError(`Expected \`input\` to be a \`string\`, got \`${typeof string}\``);
|
|
18
|
+
}
|
|
19
|
+
if (typeof count !== 'number') {
|
|
20
|
+
throw new TypeError(`Expected \`count\` to be a \`number\`, got \`${typeof count}\``);
|
|
21
|
+
}
|
|
22
|
+
if (count < 0) {
|
|
23
|
+
throw new RangeError(`Expected \`count\` to be at least 0, got \`${count}\``);
|
|
24
|
+
}
|
|
25
|
+
if (typeof indent !== 'string') {
|
|
26
|
+
throw new TypeError(`Expected \`options.indent\` to be a \`string\`, got \`${typeof indent}\``);
|
|
27
|
+
}
|
|
28
|
+
if (count === 0) {
|
|
29
|
+
return string;
|
|
30
|
+
}
|
|
31
|
+
const regex = includeEmptyLines ? /^/gm : /^(?!\s*$)/gm;
|
|
32
|
+
return string.replace(regex, indent.repeat(count));
|
|
33
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { indentString } from './indentString.js';
|
|
3
|
+
import logSymbol from 'log-symbols';
|
|
4
|
+
import ansiEscapes from 'ansi-escapes';
|
|
5
|
+
import wrapAnsi from 'wrap-ansi';
|
|
6
|
+
import { stripIndent } from 'common-tags';
|
|
7
|
+
import { isDetailedError } from '@graphql-codegen/plugin-helpers';
|
|
8
|
+
import { debugLog, printLogs } from './debugging.js';
|
|
9
|
+
import UpdateRenderer from 'listr-update-renderer';
|
|
10
|
+
export class Renderer {
|
|
11
|
+
constructor(tasks, options) {
|
|
12
|
+
this.updateRenderer = new UpdateRenderer(tasks, options);
|
|
13
|
+
}
|
|
14
|
+
render() {
|
|
15
|
+
return this.updateRenderer.render();
|
|
16
|
+
}
|
|
17
|
+
end(err) {
|
|
18
|
+
this.updateRenderer.end(err);
|
|
19
|
+
if (typeof err === 'undefined') {
|
|
20
|
+
logUpdate.clear();
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
// persist the output
|
|
24
|
+
logUpdate.done();
|
|
25
|
+
// show errors
|
|
26
|
+
if (err) {
|
|
27
|
+
const errorCount = err.errors ? err.errors.length : 0;
|
|
28
|
+
if (errorCount > 0) {
|
|
29
|
+
const count = indentString(chalk.red.bold(`Found ${errorCount} error${errorCount > 1 ? 's' : ''}`), 1);
|
|
30
|
+
const details = err.errors
|
|
31
|
+
.map(error => {
|
|
32
|
+
debugLog(`[CLI] Exited with an error`, error);
|
|
33
|
+
return { msg: isDetailedError(error) ? error.details : null, rawError: error };
|
|
34
|
+
})
|
|
35
|
+
.map(({ msg, rawError }, i) => {
|
|
36
|
+
const source = err.errors[i].source;
|
|
37
|
+
msg = msg ? chalk.gray(indentString(stripIndent(`${msg}`), 4)) : null;
|
|
38
|
+
const stack = rawError.stack ? chalk.gray(indentString(stripIndent(rawError.stack), 4)) : null;
|
|
39
|
+
if (source) {
|
|
40
|
+
const sourceOfError = typeof source === 'string' ? source : source.name;
|
|
41
|
+
const title = indentString(`${logSymbol.error} ${sourceOfError}`, 2);
|
|
42
|
+
return [title, msg, stack, stack].filter(Boolean).join('\n');
|
|
43
|
+
}
|
|
44
|
+
return [msg, stack].filter(Boolean).join('\n');
|
|
45
|
+
})
|
|
46
|
+
.join('\n\n');
|
|
47
|
+
logUpdate.emit(['', count, details, ''].join('\n\n'));
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
const details = err.details ? err.details : '';
|
|
51
|
+
logUpdate.emit(`${chalk.red.bold(`${indentString(err.message, 2)}`)}\n${details}\n${chalk.grey(err.stack)}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
logUpdate.done();
|
|
55
|
+
printLogs();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const render = tasks => {
|
|
59
|
+
for (const task of tasks) {
|
|
60
|
+
task.subscribe(event => {
|
|
61
|
+
if (event.type === 'SUBTASKS') {
|
|
62
|
+
render(task.subtasks);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (event.type === 'DATA') {
|
|
66
|
+
logUpdate.emit(chalk.dim(`${event.data}`));
|
|
67
|
+
}
|
|
68
|
+
logUpdate.done();
|
|
69
|
+
}, err => {
|
|
70
|
+
logUpdate.emit(err);
|
|
71
|
+
logUpdate.done();
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
export class ErrorRenderer {
|
|
76
|
+
constructor(tasks, _options) {
|
|
77
|
+
this.tasks = tasks;
|
|
78
|
+
}
|
|
79
|
+
render() {
|
|
80
|
+
render(this.tasks);
|
|
81
|
+
}
|
|
82
|
+
static get nonTTY() {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
end() { }
|
|
86
|
+
}
|
|
87
|
+
class LogUpdate {
|
|
88
|
+
constructor() {
|
|
89
|
+
this.stream = process.stdout;
|
|
90
|
+
// state
|
|
91
|
+
this.previousLineCount = 0;
|
|
92
|
+
this.previousOutput = '';
|
|
93
|
+
this.previousWidth = this.getWidth();
|
|
94
|
+
}
|
|
95
|
+
emit(...args) {
|
|
96
|
+
let output = args.join(' ') + '\n';
|
|
97
|
+
const width = this.getWidth();
|
|
98
|
+
if (output === this.previousOutput && this.previousWidth === width) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
this.previousOutput = output;
|
|
102
|
+
this.previousWidth = width;
|
|
103
|
+
output = wrapAnsi(output, width, {
|
|
104
|
+
trim: false,
|
|
105
|
+
hard: true,
|
|
106
|
+
wordWrap: false,
|
|
107
|
+
});
|
|
108
|
+
this.stream.write(ansiEscapes.eraseLines(this.previousLineCount) + output);
|
|
109
|
+
this.previousLineCount = output.split('\n').length;
|
|
110
|
+
}
|
|
111
|
+
clear() {
|
|
112
|
+
this.stream.write(ansiEscapes.eraseLines(this.previousLineCount));
|
|
113
|
+
this.previousOutput = '';
|
|
114
|
+
this.previousWidth = this.getWidth();
|
|
115
|
+
this.previousLineCount = 0;
|
|
116
|
+
}
|
|
117
|
+
done() {
|
|
118
|
+
this.previousOutput = '';
|
|
119
|
+
this.previousWidth = this.getWidth();
|
|
120
|
+
this.previousLineCount = 0;
|
|
121
|
+
}
|
|
122
|
+
getWidth() {
|
|
123
|
+
const { columns } = this.stream;
|
|
124
|
+
if (!columns) {
|
|
125
|
+
return 80;
|
|
126
|
+
}
|
|
127
|
+
return columns;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const logUpdate = new LogUpdate();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphql-codegen/cli",
|
|
3
|
-
"version": "2.7.1-alpha-
|
|
3
|
+
"version": "2.7.1-alpha-23dfe4aea.0",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
|
|
6
6
|
},
|
|
@@ -19,20 +19,24 @@
|
|
|
19
19
|
"@graphql-tools/utils": "^8.8.0",
|
|
20
20
|
"ansi-escapes": "^4.3.1",
|
|
21
21
|
"chalk": "^4.1.0",
|
|
22
|
+
"change-case-all": "1.0.14",
|
|
22
23
|
"chokidar": "^3.5.2",
|
|
24
|
+
"common-tags": "^1.8.0",
|
|
23
25
|
"cosmiconfig": "^7.0.0",
|
|
26
|
+
"cross-undici-fetch": "^0.4.11",
|
|
24
27
|
"debounce": "^1.2.0",
|
|
25
28
|
"detect-indent": "^6.0.0",
|
|
26
29
|
"graphql-config": "^4.3.1",
|
|
27
30
|
"inquirer": "^8.0.0",
|
|
28
31
|
"is-glob": "^4.0.1",
|
|
29
32
|
"json-to-pretty-yaml": "^1.2.2",
|
|
30
|
-
"
|
|
31
|
-
"
|
|
33
|
+
"listr": "^0.14.3",
|
|
34
|
+
"listr-update-renderer": "^0.5.0",
|
|
32
35
|
"log-symbols": "^4.0.0",
|
|
33
36
|
"mkdirp": "^1.0.4",
|
|
34
37
|
"string-env-interpolation": "^1.0.1",
|
|
35
38
|
"ts-log": "^2.2.3",
|
|
39
|
+
"wrap-ansi": "^7.0.0",
|
|
36
40
|
"yaml": "^1.10.0",
|
|
37
41
|
"yargs": "^17.0.0"
|
|
38
42
|
},
|