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