@depup/graphql-codegen__cli 6.2.1-depup.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 (112) hide show
  1. package/README.md +51 -0
  2. package/changes.json +90 -0
  3. package/cjs/bin.js +13 -0
  4. package/cjs/cli.js +64 -0
  5. package/cjs/codegen.js +388 -0
  6. package/cjs/config.js +370 -0
  7. package/cjs/documentTransforms.js +63 -0
  8. package/cjs/generate-and-save.js +153 -0
  9. package/cjs/graphql-config.js +67 -0
  10. package/cjs/hooks.js +93 -0
  11. package/cjs/index.js +13 -0
  12. package/cjs/init/helpers.js +90 -0
  13. package/cjs/init/index.js +62 -0
  14. package/cjs/init/plugins.js +136 -0
  15. package/cjs/init/questions.js +177 -0
  16. package/cjs/init/targets.js +45 -0
  17. package/cjs/init/types.js +15 -0
  18. package/cjs/load.js +102 -0
  19. package/cjs/package.json +1 -0
  20. package/cjs/plugins.js +43 -0
  21. package/cjs/presets.js +50 -0
  22. package/cjs/utils/abort-controller-polyfill.js +99 -0
  23. package/cjs/utils/cli-error.js +24 -0
  24. package/cjs/utils/debugging.js +22 -0
  25. package/cjs/utils/file-system.js +24 -0
  26. package/cjs/utils/get-latest-version.js +14 -0
  27. package/cjs/utils/helpers.js +12 -0
  28. package/cjs/utils/logger.js +24 -0
  29. package/cjs/utils/patterns.js +235 -0
  30. package/cjs/utils/watcher.js +244 -0
  31. package/esm/bin.js +11 -0
  32. package/esm/cli.js +37 -0
  33. package/esm/codegen.js +384 -0
  34. package/esm/config.js +357 -0
  35. package/esm/documentTransforms.js +59 -0
  36. package/esm/generate-and-save.js +149 -0
  37. package/esm/graphql-config.js +62 -0
  38. package/esm/hooks.js +89 -0
  39. package/esm/index.js +7 -0
  40. package/esm/init/helpers.js +82 -0
  41. package/esm/init/index.js +59 -0
  42. package/esm/init/plugins.js +133 -0
  43. package/esm/init/questions.js +172 -0
  44. package/esm/init/targets.js +42 -0
  45. package/esm/init/types.js +12 -0
  46. package/esm/load.js +97 -0
  47. package/esm/plugins.js +40 -0
  48. package/esm/presets.js +47 -0
  49. package/esm/utils/abort-controller-polyfill.js +96 -0
  50. package/esm/utils/cli-error.js +20 -0
  51. package/esm/utils/debugging.js +17 -0
  52. package/esm/utils/file-system.js +17 -0
  53. package/esm/utils/get-latest-version.js +11 -0
  54. package/esm/utils/helpers.js +9 -0
  55. package/esm/utils/logger.js +18 -0
  56. package/esm/utils/patterns.js +226 -0
  57. package/esm/utils/watcher.js +239 -0
  58. package/package.json +205 -0
  59. package/typings/bin.d.cts +2 -0
  60. package/typings/bin.d.ts +2 -0
  61. package/typings/cli.d.cts +2 -0
  62. package/typings/cli.d.ts +2 -0
  63. package/typings/codegen.d.cts +6 -0
  64. package/typings/codegen.d.ts +6 -0
  65. package/typings/config.d.cts +152 -0
  66. package/typings/config.d.ts +152 -0
  67. package/typings/documentTransforms.d.cts +3 -0
  68. package/typings/documentTransforms.d.ts +3 -0
  69. package/typings/generate-and-save.d.cts +10 -0
  70. package/typings/generate-and-save.d.ts +10 -0
  71. package/typings/graphql-config.d.cts +3 -0
  72. package/typings/graphql-config.d.ts +3 -0
  73. package/typings/hooks.d.cts +11 -0
  74. package/typings/hooks.d.ts +11 -0
  75. package/typings/index.d.cts +8 -0
  76. package/typings/index.d.ts +8 -0
  77. package/typings/init/helpers.d.cts +10 -0
  78. package/typings/init/helpers.d.ts +10 -0
  79. package/typings/init/index.d.cts +1 -0
  80. package/typings/init/index.d.ts +1 -0
  81. package/typings/init/plugins.d.cts +2 -0
  82. package/typings/init/plugins.d.ts +2 -0
  83. package/typings/init/questions.d.cts +13 -0
  84. package/typings/init/questions.d.ts +13 -0
  85. package/typings/init/targets.d.cts +2 -0
  86. package/typings/init/targets.d.ts +2 -0
  87. package/typings/init/types.d.cts +30 -0
  88. package/typings/init/types.d.ts +30 -0
  89. package/typings/load.d.cts +15 -0
  90. package/typings/load.d.ts +15 -0
  91. package/typings/plugins.d.cts +2 -0
  92. package/typings/plugins.d.ts +2 -0
  93. package/typings/presets.d.cts +5 -0
  94. package/typings/presets.d.ts +5 -0
  95. package/typings/utils/abort-controller-polyfill.d.cts +5 -0
  96. package/typings/utils/abort-controller-polyfill.d.ts +5 -0
  97. package/typings/utils/cli-error.d.cts +10 -0
  98. package/typings/utils/cli-error.d.ts +10 -0
  99. package/typings/utils/debugging.d.cts +3 -0
  100. package/typings/utils/debugging.d.ts +3 -0
  101. package/typings/utils/file-system.d.cts +8 -0
  102. package/typings/utils/file-system.d.ts +8 -0
  103. package/typings/utils/get-latest-version.d.cts +6 -0
  104. package/typings/utils/get-latest-version.d.ts +6 -0
  105. package/typings/utils/helpers.d.cts +1 -0
  106. package/typings/utils/helpers.d.ts +1 -0
  107. package/typings/utils/logger.d.cts +5 -0
  108. package/typings/utils/logger.d.ts +5 -0
  109. package/typings/utils/patterns.d.cts +91 -0
  110. package/typings/utils/patterns.d.ts +91 -0
  111. package/typings/utils/watcher.d.cts +16 -0
  112. package/typings/utils/watcher.d.ts +16 -0
package/esm/codegen.js ADDED
@@ -0,0 +1,384 @@
1
+ import fs from 'fs';
2
+ import { createRequire } from 'module';
3
+ import { cpus } from 'os';
4
+ import path from 'path';
5
+ import { codegen } from '@graphql-codegen/core';
6
+ import { getCachedDocumentNodeFromSchema, normalizeConfig, normalizeImportExtension, normalizeInstanceOrArray, normalizeOutputParam, } from '@graphql-codegen/plugin-helpers';
7
+ import { NoTypeDefinitionsFound } from '@graphql-tools/load';
8
+ import { buildASTSchema, GraphQLError, isSchema } from 'graphql';
9
+ import { mergeTypeDefs } from '@graphql-tools/merge';
10
+ import { Listr } from 'listr2';
11
+ import { ensureContext } from './config.js';
12
+ import { getPluginByName } from './plugins.js';
13
+ import { getPresetByName } from './presets.js';
14
+ import { debugLog, printLogs } from './utils/debugging.js';
15
+ import { getDocumentTransform } from './documentTransforms.js';
16
+ /**
17
+ * Poor mans ESM detection.
18
+ * Looking at this and you have a better method?
19
+ * Send a PR.
20
+ */
21
+ const isESMModule = (typeof __dirname === 'string') === false;
22
+ const makeDefaultLoader = (from) => {
23
+ if (fs.statSync(from).isDirectory()) {
24
+ from = path.join(from, '__fake.js');
25
+ }
26
+ const relativeRequire = createRequire(from);
27
+ return async (mod) => {
28
+ return import(isESMModule
29
+ ? /**
30
+ * For ESM we currently have no "resolve path" solution
31
+ * as import.meta is unavailable in a CommonJS context
32
+ * and furthermore unavailable in stable Node.js.
33
+ **/
34
+ mod
35
+ : relativeRequire.resolve(mod));
36
+ };
37
+ };
38
+ function createCache() {
39
+ const cache = new Map();
40
+ return function ensure(namespace, key, factory) {
41
+ const cacheKey = `${namespace}:${key}`;
42
+ const cachedValue = cache.get(cacheKey);
43
+ if (cachedValue) {
44
+ return cachedValue;
45
+ }
46
+ const value = factory();
47
+ cache.set(cacheKey, value);
48
+ return value;
49
+ };
50
+ }
51
+ export async function executeCodegen(input) {
52
+ const context = ensureContext(input);
53
+ const config = context.getConfig();
54
+ const pluginContext = context.getPluginContext();
55
+ const result = [];
56
+ let rootConfig = {};
57
+ let rootSchemas;
58
+ let rootDocuments;
59
+ const generates = {};
60
+ const cache = createCache();
61
+ // We need a simple string to uniqually identify the provided GraphQLSchema objects for the above cache.
62
+ // Because JavaScript does not provide access to its internal object ids, we need a workaround.
63
+ // Below is a common way to get unique ids for objects in JavaScript,
64
+ // by using a WeakMap and autoincrementing the id.
65
+ const jsObjectIds = new WeakMap();
66
+ let jsObjectIdCounter = 0;
67
+ function getJsObjectId(schema) {
68
+ if (!jsObjectIds.has(schema)) {
69
+ jsObjectIds.set(schema, jsObjectIdCounter++);
70
+ }
71
+ return jsObjectIds.get(schema);
72
+ }
73
+ function wrapTask(task, source, taskName, ctx) {
74
+ return () => context.profiler.run(async () => {
75
+ try {
76
+ await Promise.resolve().then(() => task());
77
+ }
78
+ catch (error) {
79
+ if (source && !(error instanceof GraphQLError)) {
80
+ error.source = source;
81
+ }
82
+ ctx.errors.push(error);
83
+ throw error;
84
+ }
85
+ }, taskName);
86
+ }
87
+ async function normalize() {
88
+ /* Load Require extensions */
89
+ const requireExtensions = normalizeInstanceOrArray(config.require);
90
+ const loader = makeDefaultLoader(context.cwd);
91
+ for (const mod of requireExtensions) {
92
+ await loader(mod);
93
+ }
94
+ /* Root plugin config */
95
+ rootConfig = config.config || {};
96
+ /* Normalize root "schema" field */
97
+ rootSchemas = normalizeInstanceOrArray(config.schema);
98
+ /* Normalize root "documents" field */
99
+ rootDocuments = normalizeInstanceOrArray(config.documents);
100
+ /* Normalize "generators" field */
101
+ const generateKeys = Object.keys(config.generates || {});
102
+ if (generateKeys.length === 0) {
103
+ throw new Error(`Invalid Codegen Configuration! \n
104
+ Please make sure that your codegen config file contains the "generates" field, with a specification for the plugins you need.
105
+
106
+ It should looks like that:
107
+
108
+ schema:
109
+ - my-schema.graphql
110
+ generates:
111
+ my-file.ts:
112
+ - plugin1
113
+ - plugin2
114
+ - plugin3`);
115
+ }
116
+ for (const filename of generateKeys) {
117
+ const output = (generates[filename] = normalizeOutputParam(config.generates[filename]));
118
+ if (!output.preset && (!output.plugins || output.plugins.length === 0)) {
119
+ throw new Error(`Invalid Codegen Configuration! \n
120
+ Please make sure that your codegen config file has defined plugins list for output "${filename}".
121
+
122
+ It should looks like that:
123
+
124
+ schema:
125
+ - my-schema.graphql
126
+ generates:
127
+ my-file.ts:
128
+ - plugin1
129
+ - plugin2
130
+ - plugin3
131
+ `);
132
+ }
133
+ }
134
+ if (rootSchemas.length === 0 &&
135
+ Object.keys(generates).some(filename => !generates[filename].schema ||
136
+ (Array.isArray(generates[filename].schema === 'object') &&
137
+ generates[filename].schema.length === 0))) {
138
+ throw new Error(`Invalid Codegen Configuration! \n
139
+ Please make sure that your codegen config file contains either the "schema" field
140
+ or every generated file has its own "schema" field.
141
+
142
+ It should looks like that:
143
+ schema:
144
+ - my-schema.graphql
145
+
146
+ or:
147
+ generates:
148
+ path/to/output:
149
+ schema: my-schema.graphql
150
+ `);
151
+ }
152
+ }
153
+ const isTest = process.env.NODE_ENV === 'test';
154
+ const tasks = new Listr([
155
+ {
156
+ title: 'Parse Configuration',
157
+ task: () => normalize(),
158
+ },
159
+ {
160
+ title: 'Generate outputs',
161
+ task: (ctx, task) => {
162
+ const generateTasks = Object.keys(generates).map(filename => {
163
+ const outputConfig = generates[filename];
164
+ const hasPreset = !!outputConfig.preset;
165
+ const title = `Generate to ${filename}`;
166
+ return {
167
+ title,
168
+ async task(_, subTask) {
169
+ let outputSchemaAst;
170
+ let outputSchema;
171
+ const outputFileTemplateConfig = outputConfig.config || {};
172
+ let outputDocuments = [];
173
+ const outputSpecificSchemas = normalizeInstanceOrArray(outputConfig.schema);
174
+ let outputSpecificDocuments = normalizeInstanceOrArray(outputConfig.documents);
175
+ const preset = hasPreset
176
+ ? typeof outputConfig.preset === 'string'
177
+ ? await getPresetByName(outputConfig.preset, makeDefaultLoader(context.cwd))
178
+ : outputConfig.preset
179
+ : null;
180
+ if (preset?.prepareDocuments) {
181
+ outputSpecificDocuments = await preset.prepareDocuments(filename, outputSpecificDocuments);
182
+ }
183
+ return subTask.newListr([
184
+ {
185
+ title: 'Load GraphQL schemas',
186
+ task: wrapTask(async () => {
187
+ debugLog(`[CLI] Loading Schemas`);
188
+ const schemaPointerMap = {};
189
+ const parsedSchemas = [];
190
+ const allSchemaDenormalizedPointers = [...rootSchemas, ...outputSpecificSchemas];
191
+ for (const denormalizedPtr of allSchemaDenormalizedPointers) {
192
+ if (isSchema(denormalizedPtr)) {
193
+ parsedSchemas.push(denormalizedPtr);
194
+ }
195
+ else if (typeof denormalizedPtr === 'string') {
196
+ schemaPointerMap[denormalizedPtr] = {};
197
+ }
198
+ else if (typeof denormalizedPtr === 'object') {
199
+ Object.assign(schemaPointerMap, denormalizedPtr);
200
+ }
201
+ }
202
+ const hash = JSON.stringify(schemaPointerMap) + parsedSchemas.map(getJsObjectId).join(',');
203
+ const result = await cache('schema', hash, async () => {
204
+ // collect parsed schemas
205
+ const schemasToMerge = [...parsedSchemas];
206
+ // collect schemas, provided by pointers
207
+ if (Object.keys(schemaPointerMap).length) {
208
+ schemasToMerge.push(await context.loadSchema(schemaPointerMap));
209
+ }
210
+ // merge all collected schemas into one
211
+ const outputSchemaAst = schemasToMerge.length === 1
212
+ ? schemasToMerge[0]
213
+ : buildASTSchema(mergeTypeDefs(schemasToMerge));
214
+ const outputSchema = getCachedDocumentNodeFromSchema(outputSchemaAst);
215
+ return {
216
+ outputSchemaAst,
217
+ outputSchema,
218
+ };
219
+ });
220
+ outputSchemaAst = result.outputSchemaAst;
221
+ outputSchema = result.outputSchema;
222
+ }, filename, `Load GraphQL schemas: ${filename}`, ctx),
223
+ },
224
+ {
225
+ title: 'Load GraphQL documents',
226
+ task: wrapTask(async () => {
227
+ debugLog(`[CLI] Loading Documents`);
228
+ const documentPointerMap = {};
229
+ const allDocumentsDenormalizedPointers = [...rootDocuments, ...outputSpecificDocuments];
230
+ for (const denormalizedPtr of allDocumentsDenormalizedPointers) {
231
+ if (typeof denormalizedPtr === 'string') {
232
+ documentPointerMap[denormalizedPtr] = {};
233
+ }
234
+ else if (typeof denormalizedPtr === 'object') {
235
+ Object.assign(documentPointerMap, denormalizedPtr);
236
+ }
237
+ }
238
+ const hash = JSON.stringify(documentPointerMap);
239
+ const result = await cache('documents', hash, async () => {
240
+ try {
241
+ const documents = await context.loadDocuments(documentPointerMap);
242
+ return {
243
+ documents,
244
+ };
245
+ }
246
+ catch (error) {
247
+ if (error instanceof NoTypeDefinitionsFound && config.ignoreNoDocuments) {
248
+ return {
249
+ documents: [],
250
+ };
251
+ }
252
+ throw error;
253
+ }
254
+ });
255
+ outputDocuments = result.documents;
256
+ }, filename, `Load GraphQL documents: ${filename}`, ctx),
257
+ },
258
+ {
259
+ title: 'Generate',
260
+ task: wrapTask(async () => {
261
+ debugLog(`[CLI] Generating output`);
262
+ const normalizedPluginsArray = normalizeConfig(outputConfig.plugins);
263
+ const pluginLoader = config.pluginLoader || makeDefaultLoader(context.cwd);
264
+ const pluginPackages = await Promise.all(normalizedPluginsArray.map(plugin => getPluginByName(Object.keys(plugin)[0], pluginLoader)));
265
+ const pluginMap = Object.fromEntries(pluginPackages.map((pkg, i) => {
266
+ const plugin = normalizedPluginsArray[i];
267
+ const name = Object.keys(plugin)[0];
268
+ return [name, pkg];
269
+ }));
270
+ const rawMergedConfig = {
271
+ ...rootConfig,
272
+ emitLegacyCommonJSImports: config.emitLegacyCommonJSImports,
273
+ importExtension: config.importExtension,
274
+ ...(typeof outputFileTemplateConfig === 'string'
275
+ ? { value: outputFileTemplateConfig }
276
+ : outputFileTemplateConfig),
277
+ };
278
+ const importExtension = normalizeImportExtension({
279
+ emitLegacyCommonJSImports: rawMergedConfig.emitLegacyCommonJSImports,
280
+ importExtension: rawMergedConfig.importExtension,
281
+ });
282
+ const mergedConfig = {
283
+ ...rawMergedConfig,
284
+ importExtension,
285
+ emitLegacyCommonJSImports: rawMergedConfig.emitLegacyCommonJSImports ?? true,
286
+ };
287
+ const documentTransforms = Array.isArray(outputConfig.documentTransforms)
288
+ ? await Promise.all(outputConfig.documentTransforms.map(async (config, index) => {
289
+ return await getDocumentTransform(config, makeDefaultLoader(context.cwd), `the element at index ${index} of the documentTransforms`);
290
+ }))
291
+ : [];
292
+ const outputs = preset
293
+ ? await context.profiler.run(async () => preset.buildGeneratesSection({
294
+ baseOutputDir: filename,
295
+ presetConfig: outputConfig.presetConfig || {},
296
+ plugins: normalizedPluginsArray,
297
+ schema: outputSchema,
298
+ schemaAst: outputSchemaAst,
299
+ documents: outputDocuments,
300
+ config: mergedConfig,
301
+ pluginMap,
302
+ pluginContext,
303
+ profiler: context.profiler,
304
+ documentTransforms,
305
+ }), `Build Generates Section: ${filename}`)
306
+ : [
307
+ {
308
+ filename,
309
+ plugins: normalizedPluginsArray,
310
+ schema: outputSchema,
311
+ schemaAst: outputSchemaAst,
312
+ documents: outputDocuments,
313
+ config: mergedConfig,
314
+ pluginMap,
315
+ pluginContext,
316
+ profiler: context.profiler,
317
+ documentTransforms,
318
+ },
319
+ ];
320
+ const process = async (outputArgs) => {
321
+ const output = await codegen({
322
+ ...outputArgs,
323
+ importExtension,
324
+ emitLegacyCommonJSImports: rawMergedConfig.emitLegacyCommonJSImports ?? true,
325
+ cache,
326
+ });
327
+ result.push({
328
+ filename: outputArgs.filename,
329
+ content: output,
330
+ hooks: outputConfig.hooks || {},
331
+ });
332
+ };
333
+ await context.profiler.run(() => Promise.all(outputs.map(process)), `Codegen: ${filename}`);
334
+ }, filename, `Generate: ${filename}`, ctx),
335
+ },
336
+ ], {
337
+ /**
338
+ * For each `generates` task, we must do the following in order:
339
+ *
340
+ * 1. Load schema
341
+ * 2. Load documents
342
+ * 3. Generate based on the schema + documents
343
+ *
344
+ * This way, the 3rd step has all the schema and documents loaded in previous steps to work correctly
345
+ */
346
+ exitOnError: true,
347
+ concurrent: false,
348
+ });
349
+ },
350
+ // It doesn't stop when one of tasks failed, to finish at least some of outputs
351
+ exitOnError: false,
352
+ };
353
+ });
354
+ return task.newListr(generateTasks, { concurrent: cpus().length || 1 });
355
+ },
356
+ },
357
+ ], {
358
+ rendererOptions: {
359
+ clearOutput: false,
360
+ collapseSubtasks: true,
361
+ formatOutput: 'wrap',
362
+ removeEmptyLines: false,
363
+ },
364
+ renderer: config.verbose ? 'verbose' : 'default',
365
+ ctx: { errors: [] },
366
+ silentRendererCondition: isTest || config.silent,
367
+ exitOnError: true,
368
+ });
369
+ // All the errors throw in `listr2` are collected in context
370
+ // Running tasks doesn't throw anything
371
+ const executedContext = await tasks.run();
372
+ if (config.debug) {
373
+ // if we have debug logs, make sure to print them before throwing the errors
374
+ printLogs();
375
+ }
376
+ let error = null;
377
+ if (executedContext.errors.length > 0) {
378
+ const errors = executedContext.errors.map(subErr => subErr.message || subErr.toString());
379
+ error = new AggregateError(executedContext.errors, String(errors.join('\n\n')));
380
+ // Best-effort to all stack traces for debugging
381
+ error.stack = `${error.stack}\n\n${executedContext.errors.map(subErr => subErr.stack).join('\n\n')}`;
382
+ }
383
+ return { result, error };
384
+ }