1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.executeCodegen = void 0;
|
4 | const tslib_1 = require("tslib");
|
5 | const fs_1 = tslib_1.__importDefault(require("fs"));
|
6 | const module_1 = require("module");
|
7 | const os_1 = require("os");
|
8 | const path_1 = tslib_1.__importDefault(require("path"));
|
9 | const core_1 = require("@graphql-codegen/core");
|
10 | const plugin_helpers_1 = require("@graphql-codegen/plugin-helpers");
|
11 | const utils_1 = require("@graphql-tools/utils");
|
12 | const graphql_1 = require("graphql");
|
13 | const listr2_1 = require("listr2");
|
14 | const config_js_1 = require("./config.js");
|
15 | const plugins_js_1 = require("./plugins.js");
|
16 | const presets_js_1 = require("./presets.js");
|
17 | const debugging_js_1 = require("./utils/debugging.js");
|
18 | const documentTransforms_js_1 = require("./documentTransforms.js");
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 | const isESMModule = (typeof __dirname === 'string') === false;
|
25 | const makeDefaultLoader = (from) => {
|
26 | if (fs_1.default.statSync(from).isDirectory()) {
|
27 | from = path_1.default.join(from, '__fake.js');
|
28 | }
|
29 | const relativeRequire = (0, module_1.createRequire)(from);
|
30 | return async (mod) => {
|
31 | var _a;
|
32 | return _a = isESMModule
|
33 | ? |
34 |
|
35 |
|
36 |
|
37 |
|
38 | mod
|
39 | : relativeRequire.resolve(mod), Promise.resolve().then(() => tslib_1.__importStar(require(_a)));
|
40 | };
|
41 | };
|
42 | function createCache() {
|
43 | const cache = new Map();
|
44 | return function ensure(namespace, key, factory) {
|
45 | const cacheKey = `${namespace}:${key}`;
|
46 | const cachedValue = cache.get(cacheKey);
|
47 | if (cachedValue) {
|
48 | return cachedValue;
|
49 | }
|
50 | const value = factory();
|
51 | cache.set(cacheKey, value);
|
52 | return value;
|
53 | };
|
54 | }
|
55 | async function executeCodegen(input) {
|
56 | const context = (0, config_js_1.ensureContext)(input);
|
57 | const config = context.getConfig();
|
58 | const pluginContext = context.getPluginContext();
|
59 | const result = [];
|
60 | let rootConfig = {};
|
61 | let rootSchemas;
|
62 | let rootDocuments;
|
63 | const generates = {};
|
64 | const cache = createCache();
|
65 | function wrapTask(task, source, taskName, ctx) {
|
66 | return () => context.profiler.run(async () => {
|
67 | try {
|
68 | await Promise.resolve().then(() => task());
|
69 | }
|
70 | catch (error) {
|
71 | if (source && !(error instanceof graphql_1.GraphQLError)) {
|
72 | error.source = source;
|
73 | }
|
74 | ctx.errors.push(error);
|
75 | throw error;
|
76 | }
|
77 | }, taskName);
|
78 | }
|
79 | async function normalize() {
|
80 |
|
81 | const requireExtensions = (0, plugin_helpers_1.normalizeInstanceOrArray)(config.require);
|
82 | const loader = makeDefaultLoader(context.cwd);
|
83 | for (const mod of requireExtensions) {
|
84 | await loader(mod);
|
85 | }
|
86 |
|
87 | rootConfig = config.config || {};
|
88 |
|
89 | rootSchemas = (0, plugin_helpers_1.normalizeInstanceOrArray)(config.schema);
|
90 |
|
91 | rootDocuments = (0, plugin_helpers_1.normalizeInstanceOrArray)(config.documents);
|
92 |
|
93 | const generateKeys = Object.keys(config.generates || {});
|
94 | if (generateKeys.length === 0) {
|
95 | throw new Error(`Invalid Codegen Configuration! \n
|
96 | Please make sure that your codegen config file contains the "generates" field, with a specification for the plugins you need.
|
97 |
|
98 | It should looks like that:
|
99 |
|
100 | schema:
|
101 | - my-schema.graphql
|
102 | generates:
|
103 | my-file.ts:
|
104 | - plugin1
|
105 | - plugin2
|
106 | - plugin3`);
|
107 | }
|
108 | for (const filename of generateKeys) {
|
109 | const output = (generates[filename] = (0, plugin_helpers_1.normalizeOutputParam)(config.generates[filename]));
|
110 | if (!output.preset && (!output.plugins || output.plugins.length === 0)) {
|
111 | throw new Error(`Invalid Codegen Configuration! \n
|
112 | Please make sure that your codegen config file has defined plugins list for output "${filename}".
|
113 |
|
114 | It should looks like that:
|
115 |
|
116 | schema:
|
117 | - my-schema.graphql
|
118 | generates:
|
119 | my-file.ts:
|
120 | - plugin1
|
121 | - plugin2
|
122 | - plugin3
|
123 | `);
|
124 | }
|
125 | }
|
126 | if (rootSchemas.length === 0 &&
|
127 | Object.keys(generates).some(filename => !generates[filename].schema ||
|
128 | (Array.isArray(generates[filename].schema === 'object') &&
|
129 | generates[filename].schema.length === 0))) {
|
130 | throw new Error(`Invalid Codegen Configuration! \n
|
131 | Please make sure that your codegen config file contains either the "schema" field
|
132 | or every generated file has its own "schema" field.
|
133 |
|
134 | It should looks like that:
|
135 | schema:
|
136 | - my-schema.graphql
|
137 |
|
138 | or:
|
139 | generates:
|
140 | path/to/output:
|
141 | schema: my-schema.graphql
|
142 | `);
|
143 | }
|
144 | }
|
145 | const isTest = process.env.NODE_ENV === 'test';
|
146 | const tasks = new listr2_1.Listr([
|
147 | {
|
148 | title: 'Parse Configuration',
|
149 | task: () => normalize(),
|
150 | },
|
151 | {
|
152 | title: 'Generate outputs',
|
153 | task: (ctx, task) => {
|
154 | const generateTasks = Object.keys(generates).map(filename => {
|
155 | const outputConfig = generates[filename];
|
156 | const hasPreset = !!outputConfig.preset;
|
157 | const title = `Generate to ${filename}`;
|
158 | return {
|
159 | title,
|
160 | async task(_, subTask) {
|
161 | let outputSchemaAst;
|
162 | let outputSchema;
|
163 | const outputFileTemplateConfig = outputConfig.config || {};
|
164 | let outputDocuments = [];
|
165 | const outputSpecificSchemas = (0, plugin_helpers_1.normalizeInstanceOrArray)(outputConfig.schema);
|
166 | let outputSpecificDocuments = (0, plugin_helpers_1.normalizeInstanceOrArray)(outputConfig.documents);
|
167 | const preset = hasPreset
|
168 | ? typeof outputConfig.preset === 'string'
|
169 | ? await (0, presets_js_1.getPresetByName)(outputConfig.preset, makeDefaultLoader(context.cwd))
|
170 | : outputConfig.preset
|
171 | : null;
|
172 | if (preset === null || preset === void 0 ? void 0 : preset.prepareDocuments) {
|
173 | outputSpecificDocuments = await preset.prepareDocuments(filename, outputSpecificDocuments);
|
174 | }
|
175 | return subTask.newListr([
|
176 | {
|
177 | title: 'Load GraphQL schemas',
|
178 | task: wrapTask(async () => {
|
179 | (0, debugging_js_1.debugLog)(`[CLI] Loading Schemas`);
|
180 | const schemaPointerMap = {};
|
181 | const allSchemaDenormalizedPointers = [...rootSchemas, ...outputSpecificSchemas];
|
182 | for (const denormalizedPtr of allSchemaDenormalizedPointers) {
|
183 | if (typeof denormalizedPtr === 'string') {
|
184 | schemaPointerMap[denormalizedPtr] = {};
|
185 | }
|
186 | else if (typeof denormalizedPtr === 'object') {
|
187 | Object.assign(schemaPointerMap, denormalizedPtr);
|
188 | }
|
189 | }
|
190 | const hash = JSON.stringify(schemaPointerMap);
|
191 | const result = await cache('schema', hash, async () => {
|
192 | const outputSchemaAst = await context.loadSchema(schemaPointerMap);
|
193 | const outputSchema = (0, plugin_helpers_1.getCachedDocumentNodeFromSchema)(outputSchemaAst);
|
194 | return {
|
195 | outputSchemaAst,
|
196 | outputSchema,
|
197 | };
|
198 | });
|
199 | outputSchemaAst = result.outputSchemaAst;
|
200 | outputSchema = result.outputSchema;
|
201 | }, filename, `Load GraphQL schemas: ${filename}`, ctx),
|
202 | },
|
203 | {
|
204 | title: 'Load GraphQL documents',
|
205 | task: wrapTask(async () => {
|
206 | (0, debugging_js_1.debugLog)(`[CLI] Loading Documents`);
|
207 | const documentPointerMap = {};
|
208 | const allDocumentsDenormalizedPointers = [...rootDocuments, ...outputSpecificDocuments];
|
209 | for (const denormalizedPtr of allDocumentsDenormalizedPointers) {
|
210 | if (typeof denormalizedPtr === 'string') {
|
211 | documentPointerMap[denormalizedPtr] = {};
|
212 | }
|
213 | else if (typeof denormalizedPtr === 'object') {
|
214 | Object.assign(documentPointerMap, denormalizedPtr);
|
215 | }
|
216 | }
|
217 | const hash = JSON.stringify(documentPointerMap);
|
218 | const result = await cache('documents', hash, async () => {
|
219 | const documents = await context.loadDocuments(documentPointerMap);
|
220 | return {
|
221 | documents,
|
222 | };
|
223 | });
|
224 | outputDocuments = result.documents;
|
225 | }, filename, `Load GraphQL documents: ${filename}`, ctx),
|
226 | },
|
227 | {
|
228 | title: 'Generate',
|
229 | task: wrapTask(async () => {
|
230 | (0, debugging_js_1.debugLog)(`[CLI] Generating output`);
|
231 | const normalizedPluginsArray = (0, plugin_helpers_1.normalizeConfig)(outputConfig.plugins);
|
232 | const pluginLoader = config.pluginLoader || makeDefaultLoader(context.cwd);
|
233 | const pluginPackages = await Promise.all(normalizedPluginsArray.map(plugin => (0, plugins_js_1.getPluginByName)(Object.keys(plugin)[0], pluginLoader)));
|
234 | const pluginMap = Object.fromEntries(pluginPackages.map((pkg, i) => {
|
235 | const plugin = normalizedPluginsArray[i];
|
236 | const name = Object.keys(plugin)[0];
|
237 | return [name, pkg];
|
238 | }));
|
239 | const mergedConfig = {
|
240 | ...rootConfig,
|
241 | ...(typeof outputFileTemplateConfig === 'string'
|
242 | ? { value: outputFileTemplateConfig }
|
243 | : outputFileTemplateConfig),
|
244 | emitLegacyCommonJSImports: (0, config_js_1.shouldEmitLegacyCommonJSImports)(config),
|
245 | };
|
246 | const documentTransforms = Array.isArray(outputConfig.documentTransforms)
|
247 | ? await Promise.all(outputConfig.documentTransforms.map(async (config, index) => {
|
248 | return await (0, documentTransforms_js_1.getDocumentTransform)(config, makeDefaultLoader(context.cwd), `the element at index ${index} of the documentTransforms`);
|
249 | }))
|
250 | : [];
|
251 | const outputs = preset
|
252 | ? await context.profiler.run(async () => preset.buildGeneratesSection({
|
253 | baseOutputDir: filename,
|
254 | presetConfig: outputConfig.presetConfig || {},
|
255 | plugins: normalizedPluginsArray,
|
256 | schema: outputSchema,
|
257 | schemaAst: outputSchemaAst,
|
258 | documents: outputDocuments,
|
259 | config: mergedConfig,
|
260 | pluginMap,
|
261 | pluginContext,
|
262 | profiler: context.profiler,
|
263 | documentTransforms,
|
264 | }), `Build Generates Section: ${filename}`)
|
265 | : [
|
266 | {
|
267 | filename,
|
268 | plugins: normalizedPluginsArray,
|
269 | schema: outputSchema,
|
270 | schemaAst: outputSchemaAst,
|
271 | documents: outputDocuments,
|
272 | config: mergedConfig,
|
273 | pluginMap,
|
274 | pluginContext,
|
275 | profiler: context.profiler,
|
276 | documentTransforms,
|
277 | },
|
278 | ];
|
279 | const process = async (outputArgs) => {
|
280 | const output = await (0, core_1.codegen)({
|
281 | ...outputArgs,
|
282 |
|
283 | emitLegacyCommonJSImports: (0, config_js_1.shouldEmitLegacyCommonJSImports)(config, outputArgs.filename),
|
284 | cache,
|
285 | });
|
286 | result.push({
|
287 | filename: outputArgs.filename,
|
288 | content: output,
|
289 | hooks: outputConfig.hooks || {},
|
290 | });
|
291 | };
|
292 | await context.profiler.run(() => Promise.all(outputs.map(process)), `Codegen: ${filename}`);
|
293 | }, filename, `Generate: ${filename}`, ctx),
|
294 | },
|
295 | ], {
|
296 |
|
297 | exitOnError: true,
|
298 | });
|
299 | },
|
300 |
|
301 | exitOnError: false,
|
302 | };
|
303 | });
|
304 | return task.newListr(generateTasks, { concurrent: (0, os_1.cpus)().length });
|
305 | },
|
306 | },
|
307 | ], {
|
308 | rendererOptions: {
|
309 | clearOutput: false,
|
310 | collapse: true,
|
311 | },
|
312 | renderer: config.verbose ? 'verbose' : 'default',
|
313 | ctx: { errors: [] },
|
314 | rendererSilent: isTest || config.silent,
|
315 | exitOnError: true,
|
316 | });
|
317 |
|
318 |
|
319 | const executedContext = await tasks.run();
|
320 | if (config.debug) {
|
321 |
|
322 | (0, debugging_js_1.printLogs)();
|
323 | }
|
324 | if (executedContext.errors.length > 0) {
|
325 | const errors = executedContext.errors.map(subErr => subErr.message || subErr.toString());
|
326 | const newErr = new utils_1.AggregateError(executedContext.errors, String(errors.join('\n\n')));
|
327 |
|
328 | newErr.stack = `${newErr.stack}\n\n${executedContext.errors.map(subErr => subErr.stack).join('\n\n')}`;
|
329 | throw newErr;
|
330 | }
|
331 | return result;
|
332 | }
|
333 | exports.executeCodegen = executeCodegen;
|