@graphql-codegen/cli 2.7.0-alpha-8791d9688.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.
Files changed (83) hide show
  1. package/cjs/bin.js +13 -0
  2. package/cjs/cli.js +60 -0
  3. package/cjs/codegen.js +344 -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 +50 -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/get-latest-version.js +15 -0
  23. package/cjs/utils/indentString.js +37 -0
  24. package/cjs/utils/listr-renderer.js +136 -0
  25. package/cjs/utils/logger.js +25 -0
  26. package/cjs/utils/watcher.js +140 -0
  27. package/esm/bin.js +11 -0
  28. package/esm/cli.js +32 -0
  29. package/esm/codegen.js +339 -0
  30. package/esm/config.js +290 -0
  31. package/esm/generate-and-save.js +105 -0
  32. package/esm/graphql-config.js +64 -0
  33. package/esm/hooks.js +83 -0
  34. package/esm/index.js +7 -0
  35. package/esm/init/helpers.js +55 -0
  36. package/esm/init/index.js +55 -0
  37. package/esm/init/plugins.js +160 -0
  38. package/esm/init/questions.js +140 -0
  39. package/esm/init/targets.js +40 -0
  40. package/esm/init/types.js +11 -0
  41. package/esm/load.js +88 -0
  42. package/esm/plugins.js +41 -0
  43. package/esm/presets.js +46 -0
  44. package/esm/utils/cli-error.js +20 -0
  45. package/esm/utils/debugging.js +21 -0
  46. package/esm/utils/file-system.js +19 -0
  47. package/esm/utils/get-latest-version.js +11 -0
  48. package/esm/utils/indentString.js +33 -0
  49. package/esm/utils/listr-renderer.js +130 -0
  50. package/esm/utils/logger.js +18 -0
  51. package/esm/utils/watcher.js +135 -0
  52. package/package.json +36 -28
  53. package/typings/bin.d.ts +2 -0
  54. package/{cli.d.ts → typings/cli.d.ts} +0 -0
  55. package/{codegen.d.ts → typings/codegen.d.ts} +1 -1
  56. package/{config.d.ts → typings/config.d.ts} +0 -0
  57. package/{generate-and-save.d.ts → typings/generate-and-save.d.ts} +1 -1
  58. package/{graphql-config.d.ts → typings/graphql-config.d.ts} +0 -0
  59. package/{hooks.d.ts → typings/hooks.d.ts} +0 -0
  60. package/typings/index.d.ts +7 -0
  61. package/{init → typings/init}/helpers.d.ts +1 -1
  62. package/{init → typings/init}/index.d.ts +0 -0
  63. package/{init → typings/init}/plugins.d.ts +1 -1
  64. package/{init → typings/init}/questions.d.ts +1 -1
  65. package/{init → typings/init}/targets.d.ts +1 -1
  66. package/{init → typings/init}/types.d.ts +0 -0
  67. package/{load.d.ts → typings/load.d.ts} +0 -0
  68. package/{plugins.d.ts → typings/plugins.d.ts} +0 -0
  69. package/{presets.d.ts → typings/presets.d.ts} +0 -0
  70. package/{utils → typings/utils}/cli-error.d.ts +0 -0
  71. package/{utils → typings/utils}/debugging.d.ts +0 -0
  72. package/{utils → typings/utils}/file-system.d.ts +0 -0
  73. package/typings/utils/get-latest-version.d.ts +6 -0
  74. package/{utils → typings/utils}/indentString.d.ts +0 -0
  75. package/{utils → typings/utils}/listr-renderer.d.ts +0 -0
  76. package/{utils → typings/utils}/logger.d.ts +0 -0
  77. package/{utils → typings/utils}/watcher.d.ts +1 -1
  78. package/bin.d.ts +0 -1
  79. package/bin.js +0 -1888
  80. package/index.d.ts +0 -7
  81. package/index.js +0 -1899
  82. package/index.mjs +0 -1855
  83. package/utils/try-to-build-schema.d.ts +0 -2
package/esm/codegen.js ADDED
@@ -0,0 +1,339 @@
1
+ import { DetailedError, normalizeOutputParam, normalizeInstanceOrArray, normalizeConfig, getCachedDocumentNodeFromSchema, isDetailedError, } from '@graphql-codegen/plugin-helpers';
2
+ import { codegen } from '@graphql-codegen/core';
3
+ import { AggregateError } from '@graphql-tools/utils';
4
+ import { Renderer, ErrorRenderer } from './utils/listr-renderer.js';
5
+ import { GraphQLError } from 'graphql';
6
+ import { getPluginByName } from './plugins.js';
7
+ import { getPresetByName } from './presets.js';
8
+ import { debugLog } from './utils/debugging.js';
9
+ import { ensureContext } from './config.js';
10
+ import fs from 'fs';
11
+ import path from 'path';
12
+ import { cpus } from 'os';
13
+ import { createRequire } from 'module';
14
+ import Listr from 'listr';
15
+ import { isListrError } from './utils/cli-error.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
+ 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
+ }
83
+ let rootConfig = {};
84
+ let rootSchemas;
85
+ let rootDocuments;
86
+ const generates = {};
87
+ const cache = createCache();
88
+ function wrapTask(task, source, taskName) {
89
+ return () => {
90
+ return context.profiler.run(async () => {
91
+ try {
92
+ await Promise.resolve().then(() => task());
93
+ }
94
+ catch (error) {
95
+ if (source && !(error instanceof GraphQLError)) {
96
+ error.source = source;
97
+ }
98
+ throw error;
99
+ }
100
+ }, taskName);
101
+ };
102
+ }
103
+ async function normalize() {
104
+ /* Load Require extensions */
105
+ const requireExtensions = normalizeInstanceOrArray(config.require);
106
+ const loader = makeDefaultLoader(context.cwd);
107
+ for (const mod of requireExtensions) {
108
+ await loader(mod);
109
+ }
110
+ /* Root plugin config */
111
+ rootConfig = config.config || {};
112
+ /* Normalize root "schema" field */
113
+ rootSchemas = normalizeInstanceOrArray(config.schema);
114
+ /* Normalize root "documents" field */
115
+ rootDocuments = normalizeInstanceOrArray(config.documents);
116
+ /* Normalize "generators" field */
117
+ const generateKeys = Object.keys(config.generates || {});
118
+ if (generateKeys.length === 0) {
119
+ throw new DetailedError('Invalid Codegen Configuration!', `
120
+ Please make sure that your codegen config file contains the "generates" field, with a specification for the plugins you need.
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
+ for (const filename of generateKeys) {
134
+ const output = (generates[filename] = normalizeOutputParam(config.generates[filename]));
135
+ if (!output.preset && (!output.plugins || output.plugins.length === 0)) {
136
+ throw new DetailedError('Invalid Codegen Configuration!', `
137
+ Please make sure that your codegen config file has defined plugins list for output "${filename}".
138
+
139
+ It should looks like that:
140
+
141
+ schema:
142
+ - my-schema.graphql
143
+ generates:
144
+ my-file.ts:
145
+ - plugin1
146
+ - plugin2
147
+ - plugin3
148
+ `);
149
+ }
150
+ }
151
+ if (rootSchemas.length === 0 &&
152
+ Object.keys(generates).some(filename => !generates[filename].schema || generates[filename].schema.length === 0)) {
153
+ throw new DetailedError('Invalid Codegen Configuration!', `
154
+ Please make sure that your codegen config file contains either the "schema" field
155
+ or every generated file has its own "schema" field.
156
+
157
+ It should looks like that:
158
+ schema:
159
+ - my-schema.graphql
160
+
161
+ or:
162
+ generates:
163
+ path/to/output:
164
+ schema: my-schema.graphql
165
+ `);
166
+ }
167
+ }
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
180
+ ? `Generate to ${filename} (using EXPERIMENTAL preset "${outputConfig.preset}")`
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] = {};
199
+ }
200
+ else if (typeof unnormalizedPtr === 'object') {
201
+ Object.assign(schemaPointerMap, unnormalizedPtr);
202
+ }
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,
211
+ };
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,
285
+ plugins: normalizedPluginsArray,
286
+ schema: outputSchema,
287
+ schemaAst: outputSchemaAst,
288
+ documents: outputDocuments,
289
+ config: mergedConfig,
290
+ pluginMap,
291
+ pluginContext,
292
+ profiler: context.profiler,
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
+ });
321
+ },
322
+ });
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;
337
+ }
338
+ return result;
339
+ }
package/esm/config.js ADDED
@@ -0,0 +1,290 @@
1
+ import { cosmiconfig, defaultLoaders } from 'cosmiconfig';
2
+ import { resolve } from 'path';
3
+ import { DetailedError, createProfiler, createNoopProfiler, getCachedDocumentNodeFromSchema, } from '@graphql-codegen/plugin-helpers';
4
+ import { env } from 'string-env-interpolation';
5
+ import yargs from 'yargs';
6
+ import { findAndLoadGraphQLConfig } from './graphql-config.js';
7
+ import { loadSchema, loadDocuments, defaultSchemaLoadOptions, defaultDocumentsLoadOptions } from './load.js';
8
+ import { print } from 'graphql';
9
+ import yaml from 'yaml';
10
+ import { createRequire } from 'module';
11
+ import { promises } from 'fs';
12
+ import { createHash } from 'crypto';
13
+ const { lstat } = promises;
14
+ export function generateSearchPlaces(moduleName) {
15
+ const extensions = ['json', 'yaml', 'yml', 'js', 'config.js'];
16
+ // gives codegen.json...
17
+ const regular = extensions.map(ext => `${moduleName}.${ext}`);
18
+ // gives .codegenrc.json... but no .codegenrc.config.js
19
+ const dot = extensions.filter(ext => ext !== 'config.js').map(ext => `.${moduleName}rc.${ext}`);
20
+ return [...regular.concat(dot), 'package.json'];
21
+ }
22
+ function customLoader(ext) {
23
+ function loader(filepath, content) {
24
+ if (typeof process !== 'undefined' && 'env' in process) {
25
+ content = env(content);
26
+ }
27
+ if (ext === 'json') {
28
+ return defaultLoaders['.json'](filepath, content);
29
+ }
30
+ if (ext === 'yaml') {
31
+ try {
32
+ const result = yaml.parse(content, { prettyErrors: true, merge: true });
33
+ return result;
34
+ }
35
+ catch (error) {
36
+ error.message = `YAML Error in ${filepath}:\n${error.message}`;
37
+ throw error;
38
+ }
39
+ }
40
+ if (ext === 'js') {
41
+ return defaultLoaders['.js'](filepath, content);
42
+ }
43
+ }
44
+ return loader;
45
+ }
46
+ export async function loadCodegenConfig({ configFilePath, moduleName, searchPlaces: additionalSearchPlaces, packageProp, loaders: customLoaders, }) {
47
+ configFilePath = configFilePath || process.cwd();
48
+ moduleName = moduleName || 'codegen';
49
+ packageProp = packageProp || moduleName;
50
+ const cosmi = cosmiconfig(moduleName, {
51
+ searchPlaces: generateSearchPlaces(moduleName).concat(additionalSearchPlaces || []),
52
+ packageProp,
53
+ loaders: {
54
+ '.json': customLoader('json'),
55
+ '.yaml': customLoader('yaml'),
56
+ '.yml': customLoader('yaml'),
57
+ '.js': customLoader('js'),
58
+ noExt: customLoader('yaml'),
59
+ ...customLoaders,
60
+ },
61
+ });
62
+ const pathStats = await lstat(configFilePath);
63
+ return pathStats.isDirectory() ? cosmi.search(configFilePath) : cosmi.load(configFilePath);
64
+ }
65
+ export async function loadContext(configFilePath) {
66
+ const graphqlConfig = await findAndLoadGraphQLConfig(configFilePath);
67
+ if (graphqlConfig) {
68
+ return new CodegenContext({
69
+ graphqlConfig,
70
+ });
71
+ }
72
+ const result = await loadCodegenConfig({ configFilePath });
73
+ if (!result) {
74
+ if (configFilePath) {
75
+ throw new DetailedError(`Config ${configFilePath} does not exist`, `
76
+ Config ${configFilePath} does not exist.
77
+
78
+ $ graphql-codegen --config ${configFilePath}
79
+
80
+ Please make sure the --config points to a correct file.
81
+ `);
82
+ }
83
+ throw new DetailedError(`Unable to find Codegen config file!`, `
84
+ Please make sure that you have a configuration file under the current directory!
85
+ `);
86
+ }
87
+ if (result.isEmpty) {
88
+ throw new DetailedError(`Found Codegen config file but it was empty!`, `
89
+ Please make sure that you have a valid configuration file under the current directory!
90
+ `);
91
+ }
92
+ return new CodegenContext({
93
+ filepath: result.filepath,
94
+ config: result.config,
95
+ });
96
+ }
97
+ function getCustomConfigPath(cliFlags) {
98
+ const configFile = cliFlags.config;
99
+ return configFile ? resolve(process.cwd(), configFile) : null;
100
+ }
101
+ export function buildOptions() {
102
+ return {
103
+ c: {
104
+ alias: 'config',
105
+ type: 'string',
106
+ describe: 'Path to GraphQL codegen YAML config file, defaults to "codegen.yml" on the current directory',
107
+ },
108
+ w: {
109
+ alias: 'watch',
110
+ describe: 'Watch for changes and execute generation automatically. You can also specify a glob expreession for custom watch list.',
111
+ coerce: (watch) => {
112
+ if (watch === 'false') {
113
+ return false;
114
+ }
115
+ if (typeof watch === 'string' || Array.isArray(watch)) {
116
+ return watch;
117
+ }
118
+ return !!watch;
119
+ },
120
+ },
121
+ r: {
122
+ alias: 'require',
123
+ describe: 'Loads specific require.extensions before running the codegen and reading the configuration',
124
+ type: 'array',
125
+ default: [],
126
+ },
127
+ o: {
128
+ alias: 'overwrite',
129
+ describe: 'Overwrites existing files',
130
+ type: 'boolean',
131
+ },
132
+ s: {
133
+ alias: 'silent',
134
+ describe: 'Suppresses printing errors',
135
+ type: 'boolean',
136
+ },
137
+ e: {
138
+ alias: 'errors-only',
139
+ describe: 'Only print errors',
140
+ type: 'boolean',
141
+ },
142
+ profile: {
143
+ describe: 'Use profiler to measure performance',
144
+ type: 'boolean',
145
+ },
146
+ p: {
147
+ alias: 'project',
148
+ describe: 'Name of a project in GraphQL Config',
149
+ type: 'string',
150
+ },
151
+ };
152
+ }
153
+ export function parseArgv(argv = process.argv) {
154
+ return yargs(argv).options(buildOptions()).parse(argv);
155
+ }
156
+ export async function createContext(cliFlags = parseArgv(process.argv)) {
157
+ if (cliFlags.require && cliFlags.require.length > 0) {
158
+ const relativeRequire = createRequire(process.cwd());
159
+ await Promise.all(cliFlags.require.map(mod => import(relativeRequire.resolve(mod, {
160
+ paths: [process.cwd()],
161
+ }))));
162
+ }
163
+ const customConfigPath = getCustomConfigPath(cliFlags);
164
+ const context = await loadContext(customConfigPath);
165
+ updateContextWithCliFlags(context, cliFlags);
166
+ return context;
167
+ }
168
+ export function updateContextWithCliFlags(context, cliFlags) {
169
+ const config = {
170
+ configFilePath: context.filepath,
171
+ };
172
+ if (cliFlags.watch) {
173
+ config.watch = cliFlags.watch;
174
+ }
175
+ if (cliFlags.overwrite === true) {
176
+ config.overwrite = cliFlags.overwrite;
177
+ }
178
+ if (cliFlags.silent === true) {
179
+ config.silent = cliFlags.silent;
180
+ }
181
+ if (cliFlags.errorsOnly === true) {
182
+ config.errorsOnly = cliFlags.errorsOnly;
183
+ }
184
+ if (cliFlags.project) {
185
+ context.useProject(cliFlags.project);
186
+ }
187
+ if (cliFlags.profile === true) {
188
+ context.useProfiler();
189
+ }
190
+ context.updateConfig(config);
191
+ }
192
+ export class CodegenContext {
193
+ constructor({ config, graphqlConfig, filepath, }) {
194
+ this._pluginContext = {};
195
+ this._config = config;
196
+ this._graphqlConfig = graphqlConfig;
197
+ this.filepath = this._graphqlConfig ? this._graphqlConfig.filepath : filepath;
198
+ this.cwd = this._graphqlConfig ? this._graphqlConfig.dirpath : process.cwd();
199
+ this.profiler = createNoopProfiler();
200
+ }
201
+ useProject(name) {
202
+ this._project = name;
203
+ }
204
+ getConfig(extraConfig) {
205
+ if (!this.config) {
206
+ if (this._graphqlConfig) {
207
+ const project = this._graphqlConfig.getProject(this._project);
208
+ this.config = {
209
+ ...project.extension('codegen'),
210
+ schema: project.schema,
211
+ documents: project.documents,
212
+ pluginContext: this._pluginContext,
213
+ };
214
+ }
215
+ else {
216
+ this.config = { ...this._config, pluginContext: this._pluginContext };
217
+ }
218
+ }
219
+ return {
220
+ ...extraConfig,
221
+ ...this.config,
222
+ };
223
+ }
224
+ updateConfig(config) {
225
+ this.config = {
226
+ ...this.getConfig(),
227
+ ...config,
228
+ };
229
+ }
230
+ useProfiler() {
231
+ this.profiler = createProfiler();
232
+ const now = new Date(); // 2011-10-05T14:48:00.000Z
233
+ const datetime = now.toISOString().split('.')[0]; // 2011-10-05T14:48:00
234
+ const datetimeNormalized = datetime.replace(/-|:/g, ''); // 20111005T144800
235
+ this.profilerOutput = `codegen-${datetimeNormalized}.json`;
236
+ }
237
+ getPluginContext() {
238
+ return this._pluginContext;
239
+ }
240
+ async loadSchema(pointer) {
241
+ const config = this.getConfig(defaultSchemaLoadOptions);
242
+ if (this._graphqlConfig) {
243
+ // TODO: SchemaWithLoader won't work here
244
+ return addHashToSchema(this._graphqlConfig.getProject(this._project).loadSchema(pointer, 'GraphQLSchema', config));
245
+ }
246
+ return addHashToSchema(loadSchema(pointer, config));
247
+ }
248
+ async loadDocuments(pointer) {
249
+ const config = this.getConfig(defaultDocumentsLoadOptions);
250
+ if (this._graphqlConfig) {
251
+ // TODO: pointer won't work here
252
+ return addHashToDocumentFiles(this._graphqlConfig.getProject(this._project).loadDocuments(pointer, config));
253
+ }
254
+ return addHashToDocumentFiles(loadDocuments(pointer, config));
255
+ }
256
+ }
257
+ export function ensureContext(input) {
258
+ return input instanceof CodegenContext ? input : new CodegenContext({ config: input });
259
+ }
260
+ function hashContent(content) {
261
+ return createHash('sha256').update(content).digest('hex');
262
+ }
263
+ function hashSchema(schema) {
264
+ return hashContent(print(getCachedDocumentNodeFromSchema(schema)));
265
+ }
266
+ function addHashToSchema(schemaPromise) {
267
+ return schemaPromise.then(schema => {
268
+ // It's consumed later on. The general purpose is to use it for caching.
269
+ if (!schema.extensions) {
270
+ schema.extensions = {};
271
+ }
272
+ schema.extensions['hash'] = hashSchema(schema);
273
+ return schema;
274
+ });
275
+ }
276
+ function hashDocument(doc) {
277
+ if (doc.rawSDL) {
278
+ return hashContent(doc.rawSDL);
279
+ }
280
+ if (doc.document) {
281
+ return hashContent(print(doc.document));
282
+ }
283
+ return null;
284
+ }
285
+ function addHashToDocumentFiles(documentFilesPromise) {
286
+ return documentFilesPromise.then(documentFiles => documentFiles.map(doc => {
287
+ doc.hash = hashDocument(doc);
288
+ return doc;
289
+ }));
290
+ }