@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/cjs/config.js ADDED
@@ -0,0 +1,370 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CodegenContext = void 0;
4
+ exports.generateSearchPlaces = generateSearchPlaces;
5
+ exports.loadCodegenConfig = loadCodegenConfig;
6
+ exports.loadContext = loadContext;
7
+ exports.buildOptions = buildOptions;
8
+ exports.parseArgv = parseArgv;
9
+ exports.createContext = createContext;
10
+ exports.updateContextWithCliFlags = updateContextWithCliFlags;
11
+ exports.ensureContext = ensureContext;
12
+ const tslib_1 = require("tslib");
13
+ const crypto_1 = require("crypto");
14
+ const fs_1 = require("fs");
15
+ const module_1 = require("module");
16
+ const path_1 = require("path");
17
+ const plugin_helpers_1 = require("@graphql-codegen/plugin-helpers");
18
+ const cosmiconfig_1 = require("cosmiconfig");
19
+ const jiti_1 = require("jiti");
20
+ const graphql_1 = require("graphql");
21
+ const string_env_interpolation_1 = require("string-env-interpolation");
22
+ const yaml_1 = tslib_1.__importDefault(require("yaml"));
23
+ const yargs_1 = tslib_1.__importDefault(require("yargs"));
24
+ const graphql_config_js_1 = require("./graphql-config.js");
25
+ const load_js_1 = require("./load.js");
26
+ const { lstat } = fs_1.promises;
27
+ function generateSearchPlaces(moduleName) {
28
+ const extensions = ['json', 'yaml', 'yml', 'js', 'ts', 'config.js'];
29
+ // gives codegen.json...
30
+ const regular = extensions.map(ext => `${moduleName}.${ext}`);
31
+ // gives .codegenrc.json... but no .codegenrc.config.js
32
+ const dot = extensions.filter(ext => ext !== 'config.js').map(ext => `.${moduleName}rc.${ext}`);
33
+ return [...regular.concat(dot), 'package.json'];
34
+ }
35
+ function customLoader(ext) {
36
+ return async function loader(filepath, content) {
37
+ if (typeof process !== 'undefined' && 'env' in process) {
38
+ content = (0, string_env_interpolation_1.env)(content);
39
+ }
40
+ if (ext === 'json') {
41
+ return cosmiconfig_1.defaultLoaders['.json'](filepath, content);
42
+ }
43
+ if (ext === 'yaml') {
44
+ try {
45
+ const result = yaml_1.default.parse(content, { prettyErrors: true, merge: true });
46
+ return result;
47
+ }
48
+ catch (error) {
49
+ error.message = `YAML Error in ${filepath}:\n${error.message}`;
50
+ throw error;
51
+ }
52
+ }
53
+ if (ext === 'js') {
54
+ return cosmiconfig_1.defaultLoaders['.js'](filepath, content);
55
+ }
56
+ if (ext === 'ts') {
57
+ const jitiLoader = (0, jiti_1.createJiti)('');
58
+ return jitiLoader.import(filepath, { default: true });
59
+ }
60
+ };
61
+ }
62
+ async function loadCodegenConfig({ configFilePath, moduleName, searchPlaces: additionalSearchPlaces, packageProp, loaders: customLoaders, }) {
63
+ configFilePath ||= process.cwd();
64
+ moduleName ||= 'codegen';
65
+ packageProp ||= moduleName;
66
+ const cosmi = (0, cosmiconfig_1.cosmiconfig)(moduleName, {
67
+ searchPlaces: generateSearchPlaces(moduleName).concat(additionalSearchPlaces || []),
68
+ packageProp,
69
+ loaders: {
70
+ '.json': customLoader('json'),
71
+ '.yaml': customLoader('yaml'),
72
+ '.yml': customLoader('yaml'),
73
+ '.js': customLoader('js'),
74
+ '.ts': customLoader('ts'),
75
+ '.mts': customLoader('ts'),
76
+ '.cts': customLoader('ts'),
77
+ noExt: customLoader('yaml'),
78
+ ...customLoaders,
79
+ },
80
+ });
81
+ const pathStats = await lstat(configFilePath);
82
+ return pathStats.isDirectory() ? cosmi.search(configFilePath) : cosmi.load(configFilePath);
83
+ }
84
+ async function loadContext(configFilePath) {
85
+ const graphqlConfig = await (0, graphql_config_js_1.findAndLoadGraphQLConfig)(configFilePath);
86
+ if (graphqlConfig) {
87
+ return new CodegenContext({ graphqlConfig });
88
+ }
89
+ const result = await loadCodegenConfig({ configFilePath });
90
+ if (!result) {
91
+ if (configFilePath) {
92
+ throw new Error(`
93
+ Config ${configFilePath} does not exist.
94
+
95
+ $ graphql-codegen --config ${configFilePath}
96
+
97
+ Please make sure the --config points to a correct file.
98
+ `);
99
+ }
100
+ throw new Error(`Unable to find Codegen config file! \n
101
+ Please make sure that you have a configuration file under the current directory!
102
+ `);
103
+ }
104
+ if (result.isEmpty) {
105
+ throw new Error(`Found Codegen config file but it was empty! \n
106
+ Please make sure that you have a valid configuration file under the current directory!
107
+ `);
108
+ }
109
+ return new CodegenContext({
110
+ filepath: result.filepath,
111
+ config: result.config,
112
+ });
113
+ }
114
+ function getCustomConfigPath(cliFlags) {
115
+ const configFile = cliFlags.config;
116
+ return configFile ? (0, path_1.resolve)(process.cwd(), configFile) : null;
117
+ }
118
+ function buildOptions() {
119
+ return {
120
+ c: {
121
+ alias: 'config',
122
+ type: 'string',
123
+ describe: 'Path to GraphQL codegen YAML config file, defaults to "codegen.yml" on the current directory',
124
+ },
125
+ w: {
126
+ alias: 'watch',
127
+ describe: 'Watch for changes and execute generation automatically. You can also specify a glob expression for custom watch list.',
128
+ coerce(watch) {
129
+ if (watch === 'false') {
130
+ return false;
131
+ }
132
+ if (typeof watch === 'string' || Array.isArray(watch)) {
133
+ return watch;
134
+ }
135
+ return !!watch;
136
+ },
137
+ },
138
+ r: {
139
+ alias: 'require',
140
+ describe: 'Loads specific require.extensions before running the codegen and reading the configuration',
141
+ type: 'array',
142
+ default: [],
143
+ },
144
+ o: {
145
+ alias: 'overwrite',
146
+ describe: 'Overwrites existing files',
147
+ type: 'boolean',
148
+ },
149
+ s: {
150
+ alias: 'silent',
151
+ describe: 'Suppresses printing errors',
152
+ type: 'boolean',
153
+ },
154
+ e: {
155
+ alias: 'errors-only',
156
+ describe: 'Only print errors',
157
+ type: 'boolean',
158
+ },
159
+ profile: {
160
+ describe: 'Use profiler to measure performance',
161
+ type: 'boolean',
162
+ },
163
+ p: {
164
+ alias: 'project',
165
+ describe: 'Name of a project in GraphQL Config',
166
+ type: 'string',
167
+ },
168
+ v: {
169
+ alias: 'verbose',
170
+ describe: 'output more detailed information about performed tasks',
171
+ type: 'boolean',
172
+ default: false,
173
+ },
174
+ d: {
175
+ alias: 'debug',
176
+ describe: 'Print debug logs to stdout',
177
+ type: 'boolean',
178
+ default: false,
179
+ },
180
+ 'emit-legacy-common-js-imports': {
181
+ describe: 'Emit legacy CommonJS imports (deprecated, use import-extension instead)',
182
+ type: 'boolean',
183
+ },
184
+ 'import-extension': {
185
+ describe: 'Extension to append to imports (e.g., .js, .mjs, or empty string for no extension)',
186
+ type: 'string',
187
+ },
188
+ 'ignore-no-documents': {
189
+ describe: 'Suppress errors for no documents',
190
+ type: 'boolean',
191
+ },
192
+ };
193
+ }
194
+ function parseArgv(argv = process.argv) {
195
+ return (0, yargs_1.default)(argv).options(buildOptions()).parse(argv);
196
+ }
197
+ async function createContext(cliFlags = parseArgv(process.argv)) {
198
+ if (cliFlags.require && cliFlags.require.length > 0) {
199
+ const relativeRequire = (0, module_1.createRequire)(process.cwd());
200
+ await Promise.all(cliFlags.require.map(mod => Promise.resolve(`${relativeRequire.resolve(mod, {
201
+ paths: [process.cwd()],
202
+ })}`).then(s => tslib_1.__importStar(require(s)))));
203
+ }
204
+ const customConfigPath = getCustomConfigPath(cliFlags);
205
+ const context = await loadContext(customConfigPath);
206
+ updateContextWithCliFlags(context, cliFlags);
207
+ return context;
208
+ }
209
+ function updateContextWithCliFlags(context, cliFlags) {
210
+ const config = {
211
+ configFilePath: context.filepath,
212
+ };
213
+ if (cliFlags.watch !== undefined) {
214
+ config.watch = cliFlags.watch;
215
+ }
216
+ if (cliFlags.overwrite === true) {
217
+ config.overwrite = cliFlags.overwrite;
218
+ }
219
+ if (cliFlags.silent === true) {
220
+ config.silent = cliFlags.silent;
221
+ }
222
+ if (cliFlags.verbose === true || process.env.VERBOSE) {
223
+ config.verbose = true;
224
+ }
225
+ if (cliFlags.debug === true || process.env.DEBUG) {
226
+ config.debug = true;
227
+ }
228
+ if (cliFlags.errorsOnly === true) {
229
+ config.errorsOnly = cliFlags.errorsOnly;
230
+ }
231
+ if (cliFlags['ignore-no-documents'] !== undefined) {
232
+ // for some reason parsed value is `'false'` string so this ensure it always is a boolean.
233
+ config.ignoreNoDocuments = cliFlags['ignore-no-documents'] === true;
234
+ }
235
+ if (cliFlags['emit-legacy-common-js-imports'] !== undefined) {
236
+ // for some reason parsed value is `'false'` string so this ensure it always is a boolean.
237
+ config.emitLegacyCommonJSImports = cliFlags['emit-legacy-common-js-imports'] === true;
238
+ }
239
+ if (cliFlags['import-extension'] !== undefined) {
240
+ config.importExtension = cliFlags['import-extension'];
241
+ }
242
+ if (cliFlags.project) {
243
+ context.useProject(cliFlags.project);
244
+ }
245
+ if (cliFlags.profile === true) {
246
+ context.useProfiler();
247
+ }
248
+ if (cliFlags.check === true) {
249
+ context.enableCheckMode();
250
+ }
251
+ context.updateConfig(config);
252
+ }
253
+ class CodegenContext {
254
+ _config;
255
+ _graphqlConfig;
256
+ config;
257
+ _project;
258
+ _checkMode = false;
259
+ _pluginContext = {};
260
+ cwd;
261
+ filepath;
262
+ profiler;
263
+ profilerOutput;
264
+ checkModeStaleFiles = [];
265
+ constructor({ config, graphqlConfig, filepath, }) {
266
+ this._config = config;
267
+ this._graphqlConfig = graphqlConfig;
268
+ this.filepath = this._graphqlConfig ? this._graphqlConfig.filepath : filepath;
269
+ this.cwd = this._graphqlConfig ? this._graphqlConfig.dirpath : process.cwd();
270
+ this.profiler = (0, plugin_helpers_1.createNoopProfiler)();
271
+ }
272
+ useProject(name) {
273
+ this._project = name;
274
+ }
275
+ getConfig(extraConfig) {
276
+ if (!this.config) {
277
+ if (this._graphqlConfig) {
278
+ const project = this._graphqlConfig.getProject(this._project);
279
+ this.config = {
280
+ ...project.extension('codegen'),
281
+ schema: project.schema,
282
+ documents: project.documents,
283
+ pluginContext: this._pluginContext,
284
+ };
285
+ }
286
+ else {
287
+ this.config = { ...this._config, pluginContext: this._pluginContext };
288
+ }
289
+ }
290
+ return {
291
+ ...extraConfig,
292
+ ...this.config,
293
+ };
294
+ }
295
+ updateConfig(config) {
296
+ this.config = {
297
+ ...this.getConfig(),
298
+ ...config,
299
+ };
300
+ }
301
+ enableCheckMode() {
302
+ this._checkMode = true;
303
+ }
304
+ get checkMode() {
305
+ return this._checkMode;
306
+ }
307
+ useProfiler() {
308
+ this.profiler = (0, plugin_helpers_1.createProfiler)();
309
+ const now = new Date(); // 2011-10-05T14:48:00.000Z
310
+ const datetime = now.toISOString().split('.')[0]; // 2011-10-05T14:48:00
311
+ const datetimeNormalized = datetime.replace(/-|:/g, ''); // 20111005T144800
312
+ this.profilerOutput = `codegen-${datetimeNormalized}.json`;
313
+ }
314
+ getPluginContext() {
315
+ return this._pluginContext;
316
+ }
317
+ async loadSchema(pointer) {
318
+ const config = this.getConfig(load_js_1.defaultSchemaLoadOptions);
319
+ if (this._graphqlConfig) {
320
+ // TODO: SchemaWithLoader won't work here
321
+ return addHashToSchema(this._graphqlConfig
322
+ .getProject(this._project)
323
+ .loadSchema(pointer, 'GraphQLSchema', { ...config, ...config.config }));
324
+ }
325
+ return addHashToSchema((0, load_js_1.loadSchema)(pointer, config));
326
+ }
327
+ async loadDocuments(pointer) {
328
+ const config = this.getConfig(load_js_1.defaultDocumentsLoadOptions);
329
+ if (this._graphqlConfig) {
330
+ // TODO: pointer won't work here
331
+ return addHashToDocumentFiles(this._graphqlConfig.getProject(this._project).loadDocuments(pointer, { ...config, ...config.config }));
332
+ }
333
+ return addHashToDocumentFiles((0, load_js_1.loadDocuments)(pointer, config));
334
+ }
335
+ }
336
+ exports.CodegenContext = CodegenContext;
337
+ function ensureContext(input) {
338
+ return input instanceof CodegenContext ? input : new CodegenContext({ config: input });
339
+ }
340
+ function hashContent(content, encoding = 'hex') {
341
+ return (0, crypto_1.createHash)('sha256').update(content).digest(encoding);
342
+ }
343
+ function hashSchema(schema) {
344
+ return hashContent((0, graphql_1.print)((0, plugin_helpers_1.getCachedDocumentNodeFromSchema)(schema)));
345
+ }
346
+ function addHashToSchema(schemaPromise) {
347
+ return schemaPromise.then(schema => {
348
+ // It's consumed later on. The general purpose is to use it for caching.
349
+ if (!schema.extensions) {
350
+ schema.extensions = {};
351
+ }
352
+ schema.extensions['hash'] = hashSchema(schema);
353
+ return schema;
354
+ });
355
+ }
356
+ function hashDocument(doc) {
357
+ if (doc.rawSDL) {
358
+ return hashContent(doc.rawSDL);
359
+ }
360
+ if (doc.document) {
361
+ return hashContent((0, graphql_1.print)(doc.document));
362
+ }
363
+ return null;
364
+ }
365
+ function addHashToDocumentFiles(documentFilesPromise) {
366
+ return documentFilesPromise.then(documentFiles => documentFiles.map(doc => {
367
+ doc.hash = hashDocument(doc);
368
+ return doc;
369
+ }));
370
+ }
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getDocumentTransform = getDocumentTransform;
4
+ exports.getDocumentTransformByName = getDocumentTransformByName;
5
+ const path_1 = require("path");
6
+ async function getDocumentTransform(documentTransform, loader, defaultName) {
7
+ if (typeof documentTransform === 'string') {
8
+ const transformObject = await getDocumentTransformByName(documentTransform, loader);
9
+ return { name: documentTransform, transformObject };
10
+ }
11
+ if (isTransformObject(documentTransform)) {
12
+ return { name: defaultName, transformObject: documentTransform };
13
+ }
14
+ if (isTransformFileConfig(documentTransform)) {
15
+ const name = Object.keys(documentTransform)[0];
16
+ const transformObject = await getDocumentTransformByName(name, loader);
17
+ return { name, transformObject, config: Object.values(documentTransform)[0] };
18
+ }
19
+ throw new Error(`
20
+ An unknown format document transform: '${defaultName}'.
21
+ `);
22
+ }
23
+ function isTransformObject(config) {
24
+ return typeof config === 'object' && config.transform && typeof config.transform === 'function';
25
+ }
26
+ function isTransformFileConfig(config) {
27
+ const keys = Object.keys(config);
28
+ return keys.length === 1 && typeof keys[0] === 'string';
29
+ }
30
+ async function getDocumentTransformByName(name, loader) {
31
+ const possibleNames = [
32
+ `@graphql-codegen/${name}`,
33
+ `@graphql-codegen/${name}-document-transform`,
34
+ name,
35
+ (0, path_1.resolve)(process.cwd(), name),
36
+ ];
37
+ const possibleModules = possibleNames.concat((0, path_1.resolve)(process.cwd(), name));
38
+ for (const moduleName of possibleModules) {
39
+ try {
40
+ return await loader(moduleName);
41
+ }
42
+ catch (err) {
43
+ if (err.code !== 'MODULE_NOT_FOUND' && err.code !== 'ERR_MODULE_NOT_FOUND') {
44
+ throw new Error(`
45
+ Unable to load document transform matching '${name}'.
46
+ Reason:
47
+ ${err.message}
48
+ `);
49
+ }
50
+ }
51
+ }
52
+ const possibleNamesMsg = possibleNames
53
+ .map(name => `
54
+ - ${name}
55
+ `.trimEnd())
56
+ .join('');
57
+ throw new Error(`
58
+ Unable to find document transform matching '${name}'
59
+ Install one of the following packages:
60
+
61
+ ${possibleNamesMsg}
62
+ `);
63
+ }
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generate = generate;
4
+ const tslib_1 = require("tslib");
5
+ const crypto_1 = require("crypto");
6
+ const path_1 = require("path");
7
+ const log_symbols_1 = tslib_1.__importDefault(require("log-symbols"));
8
+ const codegen_js_1 = require("./codegen.js");
9
+ const config_js_1 = require("./config.js");
10
+ const hooks_js_1 = require("./hooks.js");
11
+ const debugging_js_1 = require("./utils/debugging.js");
12
+ const file_system_js_1 = require("./utils/file-system.js");
13
+ const watcher_js_1 = require("./utils/watcher.js");
14
+ const logger_js_1 = require("./utils/logger.js");
15
+ const hash = (content) => (0, crypto_1.createHash)('sha1').update(content).digest('base64');
16
+ async function generate(input, saveToFile = true) {
17
+ const context = (0, config_js_1.ensureContext)(input);
18
+ const config = context.getConfig();
19
+ await context.profiler.run(() => (0, hooks_js_1.lifecycleHooks)(config.hooks).afterStart(), 'Lifecycle: afterStart');
20
+ let previouslyGeneratedFilenames = [];
21
+ function removeStaleFiles(config, generationResult) {
22
+ const filenames = generationResult.map(o => o.filename);
23
+ // find stale files from previous build which are not present in current build
24
+ const staleFilenames = previouslyGeneratedFilenames.filter(f => !filenames.includes(f));
25
+ for (const filename of staleFilenames) {
26
+ if (shouldOverwrite(config, filename)) {
27
+ (0, file_system_js_1.unlinkFile)(filename, err => {
28
+ const prettyFilename = filename.replace(`${input.cwd || process.cwd()}/`, '');
29
+ if (err) {
30
+ (0, debugging_js_1.debugLog)(`Cannot remove stale file: ${prettyFilename}\n${err}`);
31
+ }
32
+ else {
33
+ (0, debugging_js_1.debugLog)(`Removed stale file: ${prettyFilename}`);
34
+ }
35
+ });
36
+ }
37
+ }
38
+ previouslyGeneratedFilenames = filenames;
39
+ }
40
+ const recentOutputHash = new Map();
41
+ async function writeOutput(generationResult) {
42
+ if (!saveToFile) {
43
+ return generationResult;
44
+ }
45
+ if (config.watch) {
46
+ removeStaleFiles(config, generationResult);
47
+ }
48
+ await context.profiler.run(async () => {
49
+ await (0, hooks_js_1.lifecycleHooks)(config.hooks).beforeAllFileWrite(generationResult.map(r => r.filename));
50
+ }, 'Lifecycle: beforeAllFileWrite');
51
+ await context.profiler.run(() => Promise.all(generationResult.map(async (result) => {
52
+ const previousHash = recentOutputHash.get(result.filename) || (await hashFile(result.filename));
53
+ const exists = previousHash !== null;
54
+ // Store previous hash to avoid reading from disk again
55
+ if (previousHash) {
56
+ recentOutputHash.set(result.filename, previousHash);
57
+ }
58
+ if (!shouldOverwrite(config, result.filename) && exists) {
59
+ return;
60
+ }
61
+ let content = result.content || '';
62
+ const currentHash = hash(content);
63
+ if (previousHash && currentHash === previousHash) {
64
+ (0, debugging_js_1.debugLog)(`Skipping file (${result.filename}) writing due to indentical hash...`);
65
+ return;
66
+ }
67
+ // skip updating file in dry mode
68
+ if (context.checkMode) {
69
+ context.checkModeStaleFiles.push(result.filename);
70
+ return;
71
+ }
72
+ if (content.length === 0) {
73
+ return;
74
+ }
75
+ const absolutePath = (0, path_1.isAbsolute)(result.filename)
76
+ ? result.filename
77
+ : (0, path_1.join)(input.cwd || process.cwd(), result.filename);
78
+ const basedir = (0, path_1.dirname)(absolutePath);
79
+ await (0, file_system_js_1.mkdirp)(basedir);
80
+ content = await (0, hooks_js_1.lifecycleHooks)(result.hooks).beforeOneFileWrite(absolutePath, content);
81
+ content = await (0, hooks_js_1.lifecycleHooks)(config.hooks).beforeOneFileWrite(absolutePath, content);
82
+ if (content !== result.content) {
83
+ result.content = content;
84
+ // compare the prettified content with the previous hash
85
+ // to compare the content with an existing prettified file
86
+ if (hash(content) === previousHash) {
87
+ (0, debugging_js_1.debugLog)(`Skipping file (${result.filename}) writing due to indentical hash after prettier...`);
88
+ // the modified content is NOT stored in recentOutputHash
89
+ // so a diff can already be detected before executing the hook
90
+ return;
91
+ }
92
+ }
93
+ await (0, file_system_js_1.writeFile)(absolutePath, result.content);
94
+ recentOutputHash.set(result.filename, currentHash);
95
+ await (0, hooks_js_1.lifecycleHooks)(result.hooks).afterOneFileWrite(result.filename);
96
+ await (0, hooks_js_1.lifecycleHooks)(config.hooks).afterOneFileWrite(result.filename);
97
+ })), 'Write files');
98
+ await context.profiler.run(() => (0, hooks_js_1.lifecycleHooks)(config.hooks).afterAllFileWrite(generationResult.map(r => r.filename)), 'Lifecycle: afterAllFileWrite');
99
+ return generationResult;
100
+ }
101
+ // watch mode
102
+ if (config.watch) {
103
+ return (0, watcher_js_1.createWatcher)(context, writeOutput).runningWatcher;
104
+ }
105
+ const { result: outputFiles, error } = await context.profiler.run(() => (0, codegen_js_1.executeCodegen)(context), 'executeCodegen');
106
+ if (error) {
107
+ // If all generation failed, just throw to return non-zero code.
108
+ if (outputFiles.length === 0) {
109
+ throw error;
110
+ }
111
+ // If partial success, but partial output is not allowed, throw to return non-zero code.
112
+ if (!config.allowPartialOutputs) {
113
+ (0, logger_js_1.getLogger)().error(` ${log_symbols_1.default.error} One or more errors occurred, no files were generated. To allow output on errors, set config.allowPartialOutputs=true`);
114
+ throw error;
115
+ }
116
+ // If partial success, and partial output is allowed, warn and proceed to write to files.
117
+ (0, logger_js_1.getLogger)().warn(` ${log_symbols_1.default.warning} One or more errors occurred, some files were generated. To prevent any output on errors, set config.allowPartialOutputs=false`);
118
+ }
119
+ await context.profiler.run(() => writeOutput(outputFiles), 'writeOutput');
120
+ await context.profiler.run(() => (0, hooks_js_1.lifecycleHooks)(config.hooks).beforeDone(), 'Lifecycle: beforeDone');
121
+ if (context.profilerOutput) {
122
+ await (0, file_system_js_1.writeFile)((0, path_1.join)(context.cwd, context.profilerOutput), JSON.stringify(context.profiler.collect()));
123
+ }
124
+ return outputFiles;
125
+ }
126
+ function shouldOverwrite(config, outputPath) {
127
+ const globalValue = config.overwrite === undefined ? true : !!config.overwrite;
128
+ const outputConfig = config.generates[outputPath];
129
+ if (!outputConfig) {
130
+ (0, debugging_js_1.debugLog)(`Couldn't find a config of ${outputPath}`);
131
+ return globalValue;
132
+ }
133
+ if (isConfiguredOutput(outputConfig) && typeof outputConfig.overwrite === 'boolean') {
134
+ return outputConfig.overwrite;
135
+ }
136
+ return globalValue;
137
+ }
138
+ function isConfiguredOutput(output) {
139
+ return typeof output.plugins !== 'undefined';
140
+ }
141
+ async function hashFile(filePath) {
142
+ try {
143
+ return hash(await (0, file_system_js_1.readFile)(filePath));
144
+ }
145
+ catch (err) {
146
+ if (err && err.code === 'ENOENT') {
147
+ // return null if file does not exist
148
+ return null;
149
+ }
150
+ // rethrow unexpected errors
151
+ throw err;
152
+ }
153
+ }
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CodegenExtension = void 0;
4
+ exports.findAndLoadGraphQLConfig = findAndLoadGraphQLConfig;
5
+ const apollo_engine_loader_1 = require("@graphql-tools/apollo-engine-loader");
6
+ const code_file_loader_1 = require("@graphql-tools/code-file-loader");
7
+ const git_loader_1 = require("@graphql-tools/git-loader");
8
+ const github_loader_1 = require("@graphql-tools/github-loader");
9
+ const graphql_config_1 = require("graphql-config");
10
+ const CodegenExtension = (api) => {
11
+ // Schema
12
+ api.loaders.schema.register(new code_file_loader_1.CodeFileLoader({
13
+ pluckConfig: {
14
+ skipIndent: true,
15
+ },
16
+ }));
17
+ api.loaders.schema.register(new git_loader_1.GitLoader());
18
+ api.loaders.schema.register(new github_loader_1.GithubLoader());
19
+ api.loaders.schema.register(new apollo_engine_loader_1.ApolloEngineLoader());
20
+ // Documents
21
+ api.loaders.documents.register(new code_file_loader_1.CodeFileLoader({
22
+ pluckConfig: {
23
+ skipIndent: true,
24
+ },
25
+ }));
26
+ api.loaders.documents.register(new git_loader_1.GitLoader());
27
+ api.loaders.documents.register(new github_loader_1.GithubLoader());
28
+ return {
29
+ name: 'codegen',
30
+ };
31
+ };
32
+ exports.CodegenExtension = CodegenExtension;
33
+ async function findAndLoadGraphQLConfig(filepath) {
34
+ const config = await (0, graphql_config_1.loadConfig)({
35
+ filepath,
36
+ rootDir: process.cwd(),
37
+ extensions: [exports.CodegenExtension],
38
+ throwOnEmpty: false,
39
+ throwOnMissing: false,
40
+ });
41
+ if (isGraphQLConfig(config)) {
42
+ return config;
43
+ }
44
+ }
45
+ // Kamil: user might load a config that is not GraphQL Config
46
+ // so we need to check if it's a regular config or not
47
+ function isGraphQLConfig(config) {
48
+ if (!config) {
49
+ return false;
50
+ }
51
+ try {
52
+ return config.getDefault().hasExtension('codegen');
53
+ }
54
+ catch { }
55
+ try {
56
+ for (const projectName in config.projects) {
57
+ if (Object.prototype.hasOwnProperty.call(config.projects, projectName)) {
58
+ const project = config.projects[projectName];
59
+ if (project.hasExtension('codegen')) {
60
+ return true;
61
+ }
62
+ }
63
+ }
64
+ }
65
+ catch { }
66
+ return false;
67
+ }