fork of hey-api/openapi-ts because I need some additional things
1import path from 'node:path';
2import { fileURLToPath } from 'node:url';
3
4import { Logger } from '@hey-api/codegen-core';
5import type { Context } from '@hey-api/shared';
6import {
7 checkNodeVersion,
8 ConfigValidationError,
9 getLogs,
10 JobError,
11 logCrashReport,
12 openGitHubIssueWithCrashReport,
13 printCliIntro,
14 printCrashReport,
15 shouldReportCrash,
16} from '@hey-api/shared';
17import type { LazyOrAsync, MaybeArray } from '@hey-api/types';
18
19import type { Configs } from './config/init';
20import { resolveJobs } from './config/init';
21import type { UserConfig } from './config/types';
22import { createClient as pCreateClient } from './createClient';
23
24const __filename = fileURLToPath(import.meta.url);
25const __dirname = path.dirname(__filename);
26
27/**
28 * Generate a client from the provided configuration.
29 *
30 * @param userConfig User provided {@link UserConfig} configuration(s).
31 */
32export async function createClient(
33 userConfig?: LazyOrAsync<MaybeArray<UserConfig>>,
34 logger = new Logger(),
35): Promise<ReadonlyArray<Context>> {
36 const resolvedConfig = typeof userConfig === 'function' ? await userConfig() : userConfig;
37 const userConfigs = resolvedConfig
38 ? resolvedConfig instanceof Array
39 ? resolvedConfig
40 : [resolvedConfig]
41 : [];
42
43 let rawLogs = userConfigs.find((config) => getLogs(config.logs).level !== 'silent')?.logs;
44 if (typeof rawLogs === 'string') {
45 rawLogs = getLogs(rawLogs);
46 }
47
48 let jobs: Configs['jobs'] = [];
49
50 try {
51 checkNodeVersion();
52
53 const eventCreateClient = logger.timeEvent('createClient');
54
55 const eventConfig = logger.timeEvent('config');
56 const resolved = await resolveJobs({ logger, userConfigs });
57 const dependencies = resolved.dependencies;
58 jobs = resolved.jobs;
59 const printIntro = jobs.some((job) => job.config.logs.level !== 'silent');
60 if (printIntro) printCliIntro(__dirname);
61 eventConfig.timeEnd();
62
63 const configErrors = jobs.flatMap((job) =>
64 job.errors.map((error) => ({ error, jobIndex: job.index })),
65 );
66 if (configErrors.length > 0) {
67 throw new ConfigValidationError(configErrors);
68 }
69
70 const outputs = await Promise.all(
71 jobs.map(async (job) => {
72 try {
73 return await pCreateClient({
74 config: job.config,
75 dependencies,
76 jobIndex: job.index,
77 logger,
78 });
79 } catch (error) {
80 if (error instanceof Error) {
81 throw new JobError('', {
82 error,
83 jobIndex: job.index,
84 });
85 }
86 }
87 }),
88 );
89 const contexts = outputs.filter((ctx): ctx is Context => ctx !== undefined);
90
91 eventCreateClient.timeEnd();
92
93 logger.report(jobs.some((job) => job.config.logs.level === 'debug'));
94
95 return contexts;
96 } catch (error) {
97 const logs =
98 jobs.find((job) => job.config.logs.level !== 'silent')?.config.logs ??
99 jobs[0]?.config.logs ??
100 rawLogs;
101 const dryRun =
102 jobs.some((job) => job.config.dryRun) ?? userConfigs.some((config) => config.dryRun) ?? false;
103 const logPath = logs?.file && !dryRun ? logCrashReport(error, logs.path ?? '') : undefined;
104 if (!logs || logs.level !== 'silent') {
105 printCrashReport({ error, logPath });
106 const isInteractive =
107 jobs.some((job) => job.config.interactive) ??
108 userConfigs.some((config) => config.interactive) ??
109 false;
110 if (await shouldReportCrash({ error, isInteractive })) {
111 await openGitHubIssueWithCrashReport(error, __dirname);
112 }
113 }
114
115 throw error;
116 }
117}