@openapi-qraft/plugin 2.14.0 → 2.15.0-beta.1

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 (80) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/lib/QraftCommand.d.ts +8 -62
  3. package/dist/lib/QraftCommand.d.ts.map +1 -1
  4. package/dist/lib/QraftCommand.js +30 -193
  5. package/dist/lib/QraftCommand.js.map +1 -1
  6. package/dist/lib/QraftCommandPlugin.d.ts +2 -6
  7. package/dist/lib/QraftCommandPlugin.d.ts.map +1 -1
  8. package/dist/packageVersion.d.ts +1 -1
  9. package/dist/packageVersion.d.ts.map +1 -1
  10. package/dist/packageVersion.js +1 -1
  11. package/dist/packageVersion.js.map +1 -1
  12. package/package.json +4 -3
  13. package/src/lib/QraftCommand.ts +58 -381
  14. package/src/lib/QraftCommandPlugin.ts +2 -11
  15. package/src/packageVersion.ts +1 -1
  16. package/dist/lib/GeneratorFile.d.ts +0 -9
  17. package/dist/lib/GeneratorFile.d.ts.map +0 -1
  18. package/dist/lib/GeneratorFile.js +0 -2
  19. package/dist/lib/GeneratorFile.js.map +0 -1
  20. package/dist/lib/OutputOptions.d.ts +0 -6
  21. package/dist/lib/OutputOptions.d.ts.map +0 -1
  22. package/dist/lib/OutputOptions.js +0 -2
  23. package/dist/lib/OutputOptions.js.map +0 -1
  24. package/dist/lib/RedoclyConfigCommand.d.ts +0 -22
  25. package/dist/lib/RedoclyConfigCommand.d.ts.map +0 -1
  26. package/dist/lib/RedoclyConfigCommand.js +0 -133
  27. package/dist/lib/RedoclyConfigCommand.js.map +0 -1
  28. package/dist/lib/fileHeader.d.ts +0 -2
  29. package/dist/lib/fileHeader.d.ts.map +0 -1
  30. package/dist/lib/fileHeader.js +0 -7
  31. package/dist/lib/fileHeader.js.map +0 -1
  32. package/dist/lib/formatFileHeader.d.ts +0 -2
  33. package/dist/lib/formatFileHeader.d.ts.map +0 -1
  34. package/dist/lib/formatFileHeader.js +0 -6
  35. package/dist/lib/formatFileHeader.js.map +0 -1
  36. package/dist/lib/getRedocAPIsToQraft.d.ts +0 -16
  37. package/dist/lib/getRedocAPIsToQraft.d.ts.map +0 -1
  38. package/dist/lib/getRedocAPIsToQraft.js +0 -45
  39. package/dist/lib/getRedocAPIsToQraft.js.map +0 -1
  40. package/dist/lib/handleSchemaInput.d.ts +0 -10
  41. package/dist/lib/handleSchemaInput.d.ts.map +0 -1
  42. package/dist/lib/handleSchemaInput.js +0 -40
  43. package/dist/lib/handleSchemaInput.js.map +0 -1
  44. package/dist/lib/loadRedoclyConfig.d.ts +0 -12
  45. package/dist/lib/loadRedoclyConfig.d.ts.map +0 -1
  46. package/dist/lib/loadRedoclyConfig.js +0 -17
  47. package/dist/lib/loadRedoclyConfig.js.map +0 -1
  48. package/dist/lib/maybeEscapeShellArg.d.ts +0 -2
  49. package/dist/lib/maybeEscapeShellArg.d.ts.map +0 -1
  50. package/dist/lib/maybeEscapeShellArg.js +0 -9
  51. package/dist/lib/maybeEscapeShellArg.js.map +0 -1
  52. package/dist/lib/parseConfigToArgs.d.ts +0 -7
  53. package/dist/lib/parseConfigToArgs.d.ts.map +0 -1
  54. package/dist/lib/parseConfigToArgs.js +0 -130
  55. package/dist/lib/parseConfigToArgs.js.map +0 -1
  56. package/dist/lib/shouldQuoteCommandLineArg.d.ts +0 -11
  57. package/dist/lib/shouldQuoteCommandLineArg.d.ts.map +0 -1
  58. package/dist/lib/shouldQuoteCommandLineArg.js +0 -33
  59. package/dist/lib/shouldQuoteCommandLineArg.js.map +0 -1
  60. package/dist/lib/vitestFsMock.d.ts +0 -2
  61. package/dist/lib/vitestFsMock.d.ts.map +0 -1
  62. package/dist/lib/vitestFsMock.js +0 -16
  63. package/dist/lib/vitestFsMock.js.map +0 -1
  64. package/dist/lib/writeGeneratorFiles.d.ts +0 -7
  65. package/dist/lib/writeGeneratorFiles.d.ts.map +0 -1
  66. package/dist/lib/writeGeneratorFiles.js +0 -51
  67. package/dist/lib/writeGeneratorFiles.js.map +0 -1
  68. package/src/lib/GeneratorFile.ts +0 -5
  69. package/src/lib/OutputOptions.ts +0 -6
  70. package/src/lib/RedoclyConfigCommand.ts +0 -232
  71. package/src/lib/fileHeader.ts +0 -6
  72. package/src/lib/formatFileHeader.ts +0 -4
  73. package/src/lib/getRedocAPIsToQraft.ts +0 -87
  74. package/src/lib/handleSchemaInput.ts +0 -53
  75. package/src/lib/loadRedoclyConfig.ts +0 -47
  76. package/src/lib/maybeEscapeShellArg.ts +0 -10
  77. package/src/lib/parseConfigToArgs.ts +0 -134
  78. package/src/lib/shouldQuoteCommandLineArg.ts +0 -32
  79. package/src/lib/vitestFsMock.ts +0 -23
  80. package/src/lib/writeGeneratorFiles.ts +0 -82
@@ -1,7 +0,0 @@
1
- import { Ora } from 'ora';
2
- import { GeneratorFile } from './GeneratorFile.js';
3
- export declare const writeGeneratorFiles: ({ spinner, fileItems, }: {
4
- spinner: Ora;
5
- fileItems: GeneratorFile[];
6
- }) => Promise<void>;
7
- //# sourceMappingURL=writeGeneratorFiles.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"writeGeneratorFiles.d.ts","sourceRoot":"","sources":["../../src/lib/writeGeneratorFiles.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,eAAO,MAAM,mBAAmB,4BAG7B;IACD,OAAO,EAAE,GAAG,CAAC;IACb,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B,kBAGA,CAAC"}
@@ -1,51 +0,0 @@
1
- import fs from 'node:fs';
2
- import c from 'ansi-colors';
3
- export const writeGeneratorFiles = async ({ spinner, fileItems, }) => {
4
- await setupDirectories(spinner, fileItems);
5
- await writeFiles(spinner, fileItems);
6
- };
7
- const setupDirectories = async (spinner, fileItems) => {
8
- for (const fileItem of fileItems) {
9
- if (!('directory' in fileItem))
10
- continue;
11
- if (fileItem.clean) {
12
- spinner.text = `Cleaning ${c.magenta(fileItem.directory.pathname)}`;
13
- try {
14
- await fs.promises.rm(fileItem.directory, {
15
- recursive: true,
16
- force: true,
17
- });
18
- }
19
- catch (error) {
20
- spinner.fail(c.redBright(`Error occurred during ${c.magenta(fileItem.directory.pathname)} directory cleaning`));
21
- throw error;
22
- }
23
- }
24
- try {
25
- spinner.text = `Creating directory ${c.magenta(fileItem.directory.pathname)}`;
26
- await fs.promises.mkdir(fileItem.directory, { recursive: true });
27
- }
28
- catch (error) {
29
- spinner.fail(c.redBright(`Error occurred during ${c.magenta(fileItem.directory.pathname)} directory creation`));
30
- throw error;
31
- }
32
- }
33
- };
34
- const writeFiles = async (spinner, fileItems) => {
35
- for (const fileItem of fileItems) {
36
- if ('directory' in fileItem)
37
- continue;
38
- const { file, code } = fileItem;
39
- spinner.text = `Writing ${c.magenta(file.pathname)}`;
40
- try {
41
- await fs.promises.writeFile(file, code, {
42
- encoding: 'utf-8',
43
- });
44
- }
45
- catch (error) {
46
- spinner.fail(c.redBright(`Error occurred during ${c.magenta(file.pathname)} file writing`));
47
- throw error;
48
- }
49
- }
50
- };
51
- //# sourceMappingURL=writeGeneratorFiles.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"writeGeneratorFiles.js","sourceRoot":"","sources":["../../src/lib/writeGeneratorFiles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,CAAC,MAAM,aAAa,CAAC;AAI5B,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EAAE,EACxC,OAAO,EACP,SAAS,GAIV,EAAE,EAAE;IACH,MAAM,gBAAgB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAC3C,MAAM,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;AACvC,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,KAAK,EAAE,OAAY,EAAE,SAA0B,EAAE,EAAE;IAC1E,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,CAAC,CAAC,WAAW,IAAI,QAAQ,CAAC;YAAE,SAAS;QAEzC,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,GAAG,YAAY,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;YAEpE,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,SAAS,EAAE;oBACvC,SAAS,EAAE,IAAI;oBACf,KAAK,EAAE,IAAI;iBACZ,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CACV,CAAC,CAAC,SAAS,CACT,yBAAyB,CAAC,CAAC,OAAO,CAChC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAC5B,qBAAqB,CACvB,CACF,CAAC;gBAEF,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;QAED,IAAI,CAAC;YACH,OAAO,CAAC,IAAI,GAAG,sBAAsB,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;YAE9E,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CACV,CAAC,CAAC,SAAS,CACT,yBAAyB,CAAC,CAAC,OAAO,CAChC,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAC5B,qBAAqB,CACvB,CACF,CAAC;YAEF,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,KAAK,EAAE,OAAY,EAAE,SAA0B,EAAE,EAAE;IACpE,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,WAAW,IAAI,QAAQ;YAAE,SAAS;QAEtC,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC;QAEhC,OAAO,CAAC,IAAI,GAAG,WAAW,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAErD,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE;gBACtC,QAAQ,EAAE,OAAO;aAClB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CACV,CAAC,CAAC,SAAS,CACT,yBAAyB,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,CACjE,CACF,CAAC;YAEF,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;AACH,CAAC,CAAC"}
@@ -1,5 +0,0 @@
1
- import type { URL } from 'node:url';
2
-
3
- export type GeneratorFile =
4
- | { file: URL; code: string }
5
- | { directory: URL; clean: boolean };
@@ -1,6 +0,0 @@
1
- import { URL } from 'node:url';
2
-
3
- export interface OutputOptions {
4
- dir: URL;
5
- clean: boolean;
6
- }
@@ -1,232 +0,0 @@
1
- import { relative } from 'node:path';
2
- import { fileURLToPath, pathToFileURL, URL } from 'node:url';
3
- import { CONFIG_FILE_NAMES } from '@redocly/openapi-core';
4
- import c from 'ansi-colors';
5
- import { Command, CommanderError, Option, ParseOptions } from 'commander';
6
- import { getRedocAPIsToQraft } from './getRedocAPIsToQraft.js';
7
- import { loadRedoclyConfig } from './loadRedoclyConfig.js';
8
- import { maybeEscapeShellArg } from './maybeEscapeShellArg.js';
9
- import { parseConfigToArgs } from './parseConfigToArgs.js';
10
- import { QraftCommand } from './QraftCommand.js';
11
-
12
- export const redoclyOption = (() => {
13
- const bin = c.gray.underline('bin');
14
- const __redocly = c.yellow('--redocly');
15
-
16
- const examples = [
17
- `${bin} ${__redocly}`,
18
- `${bin} ${c.green('my-api')} ${__redocly}`,
19
- `${bin} ${c.green('my-api@v1 my-api@v2')} ${__redocly}`,
20
- `${bin} ${__redocly} ${c.yellow.underline('./my-redocly-config.yaml')}`,
21
- ].map((example) => `${c.italic.yellow(example)}`);
22
-
23
- return new Option(
24
- '--redocly [config]',
25
- [
26
- c.bold(`Use the Redocly configuration to generate multiple API clients`),
27
- `If the [config] parameter is not specified, the default Redocly configuration will be used: [${CONFIG_FILE_NAMES.join(' | ')}].`,
28
- `For more information about this option, use the command: ${c.yellow.italic('--redocly-help')}`,
29
- `${c.underline('Examples:')}`,
30
- ...examples.map((example) => `${c.gray('$')} ${example}`),
31
- ].join('\n')
32
- );
33
- })();
34
- /**
35
- * @param name - not used
36
- */
37
- export class RedoclyConfigCommand extends Command {
38
- protected readonly cwd: URL;
39
-
40
- /**
41
- * Redocly API item and QraftCommand arguments
42
- */
43
- protected parsedAPIs: RedoclyQraftAPIs = {};
44
-
45
- constructor(name?: string) {
46
- super(name);
47
- this.cwd = pathToFileURL(`${process.cwd()}/`);
48
-
49
- this.usage(c.green('[apis...] --redocly <config>'))
50
- .argument(
51
- '[apis...]',
52
- 'Optional list of Redocly APIs for which to generate API clients. If not specified, clients for all APIs will be generated.'
53
- )
54
- .allowUnknownOption(true)
55
- .helpOption('--redocly-help', 'Display help for the `--redocly` option')
56
- .addOption(redoclyOption)
57
- .action(async (apis = [], args) => {
58
- const redocly = args.redocly;
59
-
60
- if (!redocly) return;
61
-
62
- const spinner = QraftCommand.spinner;
63
-
64
- spinner.start('Loading Redocly configuration ⚙︎');
65
-
66
- const redoc = await loadRedoclyConfig(redocly || true, this.cwd);
67
-
68
- const redocConfigFile = redoc.configFile;
69
-
70
- if (!redocConfigFile) {
71
- spinner.fail(
72
- 'No "configFile" found in the Redocly configuration. Please specify the correct path to the Redocly configuration file.'
73
- );
74
- process.exit(1);
75
- }
76
-
77
- const redocAPIsToQraftEntries = Object.entries(
78
- getRedocAPIsToQraft(redoc, this.cwd, spinner)
79
- ).filter(([apiName]) => !apis.length || apis.includes(apiName));
80
-
81
- if (apis.length) {
82
- const notFoundAPIs = apis.filter(
83
- (inputAPIName: string) =>
84
- !redocAPIsToQraftEntries.some(
85
- ([apiName]) => apiName === inputAPIName
86
- )
87
- );
88
-
89
- if (notFoundAPIs.length) {
90
- spinner.fail(
91
- `The specified API${
92
- notFoundAPIs.length > 1 ? 's' : ''
93
- } ${notFoundAPIs.map(c.red).join(', ')} ${notFoundAPIs.length > 1 ? 'were' : 'was'} not found in the Redocly configuration.`
94
- );
95
-
96
- throw new CommanderError(
97
- 1,
98
- 'ERR_API_NOT_FOUND',
99
- `The specified API${
100
- notFoundAPIs.length > 1 ? 's' : ''
101
- } ${c.red(notFoundAPIs.join(', '))} ${notFoundAPIs.length > 1 ? 'were' : 'was'} not found in the Redocly configuration.`
102
- );
103
- }
104
- }
105
-
106
- redocAPIsToQraftEntries.forEach(([apiName, api]) => {
107
- const globalQraftConfig =
108
- 'x-openapi-qraft' in redoc.rawConfig
109
- ? redoc.rawConfig['x-openapi-qraft']
110
- : undefined;
111
-
112
- const {
113
- ['x-openapi-qraft']: {
114
- ['output-dir']: outputDir,
115
- ...apiQraftConfig
116
- },
117
- } = api;
118
-
119
- const cwd = fileURLToPath(this.cwd);
120
-
121
- this.parsedAPIs[apiName] = [
122
- apiName,
123
- ...parseConfigToArgs({
124
- redocly: relative(cwd, redocConfigFile),
125
- 'output-dir': relative(cwd, outputDir),
126
- ...(globalQraftConfig && typeof globalQraftConfig === 'object'
127
- ? globalQraftConfig
128
- : undefined),
129
- ...apiQraftConfig,
130
- }),
131
- ];
132
- });
133
-
134
- spinner.stop();
135
- });
136
- }
137
-
138
- async parseConfig<T>(
139
- callbackFn: CallbackFn<T>,
140
- argv: readonly string[],
141
- options?: ParseOptions
142
- ): Promise<T[] | undefined> {
143
- await this.parseAsync(argv, options);
144
-
145
- if (!Object.entries(this.parsedAPIs).length) return;
146
-
147
- return RedoclyConfigCommand.forEachRedoclyAPIEntry(
148
- this.parsedAPIs,
149
- callbackFn
150
- );
151
- }
152
-
153
- static async forEachRedoclyAPIEntry<T>(
154
- redoclyAPIs: RedoclyQraftAPIs,
155
- callbackFn: CallbackFn<T>
156
- ) {
157
- const redoclyAPIsEntries = Object.entries(redoclyAPIs);
158
-
159
- const spinner = QraftCommand.spinner;
160
-
161
- spinner.info('Loading Redocly configuration...');
162
-
163
- const { errors, results } = await Promise.allSettled(
164
- redoclyAPIsEntries.map(
165
- async ([apiName, [openAPIDocument, ...apiProcessArgv]]) => {
166
- spinner.info(
167
- `Generating API client for ${c.magenta(apiName)} with the following parameters:\n` +
168
- c.gray.italic('bin ') +
169
- `${c.green.italic(openAPIDocument)} ` +
170
- apiProcessArgv
171
- .map((arg) =>
172
- arg.startsWith('--')
173
- ? c.yellow.italic(arg)
174
- : c.yellow.italic.underline(maybeEscapeShellArg(arg))
175
- )
176
- .join(' ')
177
- );
178
- spinner.text = '';
179
- spinner.start();
180
-
181
- return callbackFn([openAPIDocument, ...apiProcessArgv], {
182
- from: 'user',
183
- });
184
- }
185
- )
186
- ).then((results) =>
187
- results.reduce<{ errors: unknown[]; results: T[] }>(
188
- (acc, result) => {
189
- if (result.status === 'rejected') acc.errors.push(result.reason);
190
- else acc.results.push(result.value);
191
-
192
- return acc;
193
- },
194
- { errors: [], results: [] }
195
- )
196
- );
197
-
198
- if (errors.length) {
199
- throw new CommanderError(
200
- 1,
201
- 'ERROR',
202
- 'The following errors occurred during API client generation:\n' +
203
- errors
204
- .map((error) =>
205
- error instanceof Error
206
- ? error.message + '\n' + error.stack
207
- : JSON.stringify(error, null, 2)
208
- )
209
- .join('\n\n')
210
- );
211
- }
212
-
213
- spinner.succeed(
214
- c.green(`API clients successfully generated for: `) +
215
- redoclyAPIsEntries
216
- .map(([apiName]) => `"${c.magenta(apiName)}"`)
217
- .join(', ') +
218
- '.'
219
- );
220
-
221
- return results;
222
- }
223
- }
224
-
225
- type CallbackFn<T> = (
226
- processArgv: string[],
227
- processArgvParseOptions?: ParseOptions
228
- ) => T;
229
-
230
- type RedoclyQraftAPIs = {
231
- [apiName: string]: string[];
232
- };
@@ -1,6 +0,0 @@
1
- export const fileHeader = `/**
2
- * This file was auto-generated by @openapi-qraft/cli.
3
- * Do not make direct changes to the file.
4
- */
5
-
6
- `;
@@ -1,4 +0,0 @@
1
- export const formatFileHeader = (fileHeader: string | undefined) => {
2
- if (!fileHeader) return '';
3
- return `${fileHeader}${fileHeader.endsWith('\n') ? '' : '\n'}`;
4
- };
@@ -1,87 +0,0 @@
1
- import type { Config } from '@redocly/openapi-core';
2
- import { isAbsolute } from 'node:path';
3
- import { fileURLToPath, pathToFileURL } from 'node:url';
4
- import { CommanderError } from 'commander';
5
- import { Ora } from 'ora';
6
-
7
- export const QRAFT_REDOC_CONFIG_KEY = 'x-openapi-qraft';
8
-
9
- export function getRedocAPIsToQraft(
10
- redoc: Config,
11
- cwd: URL,
12
- spinner: Ora,
13
- apiName?: string
14
- ) {
15
- const hasRedoclyApis = Object.keys(redoc?.apis ?? {}).length > 0;
16
- if (!hasRedoclyApis) {
17
- throw new CommanderError(
18
- 1,
19
- 'ERR_MISSING_APIS',
20
- 'No "apis" found in Redocly config. Please specify the APIs to be generated.'
21
- );
22
- }
23
- if (!redoc.configFile) {
24
- throw new CommanderError(
25
- 1,
26
- 'ERR_MISSING_CONFIG_FILE',
27
- 'No "configFile" found in Redocly config. Please specify the path to the Redocly config file.'
28
- );
29
- }
30
-
31
- const configRoot = isAbsolute(redoc.configFile)
32
- ? new URL(pathToFileURL(redoc.configFile))
33
- : new URL(redoc.configFile, cwd);
34
-
35
- const apisToQraftEntries = Object.entries(redoc.apis)
36
- .map(([itemPpiName, api]) => {
37
- if (apiName && apiName !== itemPpiName) return;
38
-
39
- const qraftConfig =
40
- QRAFT_REDOC_CONFIG_KEY in api ? api[QRAFT_REDOC_CONFIG_KEY] : undefined;
41
-
42
- if (!qraftConfig) {
43
- return void spinner.warn(
44
- `API ${itemPpiName} is missing an \`${QRAFT_REDOC_CONFIG_KEY}\` key. Skipping...`
45
- );
46
- }
47
-
48
- if (typeof qraftConfig !== 'object') {
49
- throw new CommanderError(
50
- 1,
51
- 'ERR_MISSING_API_CONFIG',
52
- `API ${itemPpiName} is missing an \`${QRAFT_REDOC_CONFIG_KEY}\` key. See https://openapi-qraft.github.io/openapi-qraft/docs/codegen/CLI/redocly-config.`
53
- );
54
- }
55
-
56
- const {
57
- o,
58
- ['output-dir']: outputPath = o,
59
- ...qraftConfigRest
60
- } = qraftConfig as {
61
- ['output-dir']?: string;
62
- o?: string;
63
- };
64
-
65
- if (!outputPath) {
66
- throw new CommanderError(
67
- 1,
68
- 'ERR_MISSING_API_OUTPUT',
69
- `API ${itemPpiName} is missing an "output-dir" key. See https://openapi-qraft.github.io/openapi-qraft/docs/codegen/CLI/redocly-config.`
70
- );
71
- }
72
-
73
- return [
74
- itemPpiName,
75
- {
76
- ...api,
77
- [QRAFT_REDOC_CONFIG_KEY]: {
78
- ...qraftConfigRest,
79
- ['output-dir']: fileURLToPath(new URL(outputPath, configRoot)),
80
- },
81
- },
82
- ] as const;
83
- })
84
- .filter((api) => !!api);
85
-
86
- return Object.fromEntries(apisToQraftEntries);
87
- }
@@ -1,53 +0,0 @@
1
- import type { Ora } from 'ora';
2
- import process from 'node:process';
3
- import { URL } from 'node:url';
4
-
5
- /**
6
- * Validates Schema's `input` and return `Readable` stream or `URL`
7
- * @throws {Error} if input is invalid
8
- */
9
- export function handleSchemaInput(input: unknown, cwd: URL, spinner: Ora) {
10
- if (!input) {
11
- /**
12
- * Handle `stdin`, if no input file is provided
13
- * @example
14
- * ```bash
15
- * cat schema.json | script.js
16
- * ```
17
- */
18
- if (process.stdin.isTTY) {
19
- spinner.fail(
20
- 'Input file not found or stdin is empty. Please specify `input` argument or pipe OpenAPI Schema to stdin.'
21
- );
22
-
23
- throw new Error('Invalid input.');
24
- }
25
-
26
- return process.stdin;
27
- }
28
-
29
- /**
30
- * Handle single file
31
- * @example
32
- * ```bash
33
- * script.js schema.json
34
- * ```
35
- */
36
-
37
- if (typeof input !== 'string') {
38
- spinner.fail('Invalid input. Please specify a single file or URL.');
39
-
40
- throw new Error('Invalid input.');
41
- }
42
-
43
- // throw error on glob
44
- if (input.includes('*')) {
45
- spinner.fail(
46
- 'Globbing is not supported. Please specify a single file or URL.'
47
- );
48
-
49
- throw new Error('Globbing is not supported.');
50
- }
51
-
52
- return new URL(input, cwd);
53
- }
@@ -1,47 +0,0 @@
1
- import { fileURLToPath, URL } from 'node:url';
2
- import {
3
- Config,
4
- CONFIG_FILE_NAMES,
5
- findConfig,
6
- loadConfig,
7
- } from '@redocly/openapi-core';
8
- import { CommanderError } from 'commander';
9
-
10
- /**
11
- * Loads Redocly config from the default config file:
12
- * 'redocly.yaml', 'redocly.yml', '.redocly.yaml', '.redocly.yml'
13
- */
14
- export async function loadRedoclyConfig(
15
- configPath: null | undefined | true,
16
- cwd: URL
17
- ): Promise<Config>;
18
- /**
19
- * Loads Redocly config from the specified path or from the default config file.
20
- */
21
- export async function loadRedoclyConfig(
22
- configPath: string,
23
- cwd: URL
24
- ): Promise<Config>;
25
- export async function loadRedoclyConfig(
26
- configPath: string | null | undefined | true,
27
- cwd: URL
28
- ): Promise<Config> {
29
- const normalizedConfigPath =
30
- typeof configPath === 'string'
31
- ? configPath
32
- : findConfig(fileURLToPath(cwd));
33
-
34
- if (!normalizedConfigPath) {
35
- throw new CommanderError(
36
- 1,
37
- 'INVALID_REDOCLY_CONFIG_PATH',
38
- typeof configPath === 'string'
39
- ? `Could not find Redocly config file at ${configPath}`
40
- : `Could not find Redocly config file in ${cwd}. Searched in: ${CONFIG_FILE_NAMES.join(', ')}`
41
- );
42
- }
43
-
44
- return await loadConfig({
45
- configPath: normalizedConfigPath,
46
- });
47
- }
@@ -1,10 +0,0 @@
1
- import { shouldQuoteCommandLineArg } from './shouldQuoteCommandLineArg.js';
2
-
3
- export function maybeEscapeShellArg(arg: string): string {
4
- if (shouldQuoteCommandLineArg(arg)) {
5
- // bash-safe single-quote escaping
6
- return `'${arg.replace(/'/g, `'\\''`)}'`;
7
- }
8
-
9
- return arg;
10
- }
@@ -1,134 +0,0 @@
1
- /**
2
- * Converts a parsed YAML configuration into command line arguments
3
- * @param config The parsed YAML configuration object
4
- * @returns Array of command line arguments
5
- */
6
- export function parseConfigToArgs(config: Record<string, unknown>): string[] {
7
- const args: string[] = [];
8
-
9
- const isPrimitive = (val: any): val is string | number | boolean =>
10
- typeof val === 'string' ||
11
- typeof val === 'number' ||
12
- typeof val === 'boolean';
13
-
14
- function flattenMapping(node: any, prefixKeys: string[]): string[] {
15
- const results: string[] = [];
16
-
17
- if (isPrimitive(node)) {
18
- if (typeof node === 'boolean') {
19
- if (node) {
20
- results.push(prefixKeys.join(':'));
21
- }
22
- } else {
23
- results.push(`${prefixKeys.join(':')}:${node.toString()}`);
24
- }
25
- return results;
26
- }
27
-
28
- if (Array.isArray(node)) {
29
- if (node.every((el) => isPrimitive(el))) {
30
- const primitives = node.filter(
31
- (el) => el !== null && el !== undefined
32
- ) as (string | number | boolean)[];
33
- const joined = primitives.map((el) => el.toString()).join(',');
34
- if (joined) {
35
- results.push(`${prefixKeys.join(':')}:${joined}`);
36
- }
37
- return results;
38
- }
39
-
40
- for (const el of node) {
41
- if (el == null) {
42
- continue;
43
- }
44
- results.push(...flattenMapping(el, prefixKeys));
45
- }
46
- return results;
47
- }
48
-
49
- if (typeof node === 'object' && node !== null) {
50
- for (const [key, value] of Object.entries(node)) {
51
- results.push(...flattenMapping(value, [...prefixKeys, key]));
52
- }
53
- return results;
54
- }
55
-
56
- return results;
57
- }
58
-
59
- for (const [key, value] of Object.entries(config)) {
60
- if (typeof value === 'string' || typeof value === 'number') {
61
- args.push(`--${key}`, value.toString());
62
- } else if (typeof value === 'boolean') {
63
- if (value) {
64
- args.push(`--${key}`);
65
- }
66
- } else if (value == null) {
67
- continue;
68
- } else if (Array.isArray(value)) {
69
- if (value.every((el) => isPrimitive(el))) {
70
- const primitives = value.filter(
71
- (el) => el !== null && el !== undefined
72
- ) as (string | number | boolean)[];
73
- args.push(`--${key}`, ...primitives.map((el) => el.toString()));
74
- } else {
75
- for (const el of value) {
76
- if (el == null) {
77
- continue;
78
- }
79
- if (typeof el === 'object') {
80
- const mappingPaths = flattenMapping(el, []);
81
- if (mappingPaths.length) {
82
- args.push(`--${key}`, ...mappingPaths);
83
- }
84
- } else if (isPrimitive(el)) {
85
- args.push(`--${key}`, el.toString());
86
- }
87
- }
88
- }
89
- } else if (typeof value === 'object') {
90
- for (const [childKey, childValue] of Object.entries(
91
- value as Record<string, unknown>
92
- )) {
93
- if (typeof childValue === 'string' || typeof childValue === 'number') {
94
- args.push(`--${key}`, childKey, childValue.toString());
95
- } else if (typeof childValue === 'boolean') {
96
- if (childValue) {
97
- args.push(`--${key}`, childKey);
98
- }
99
- } else if (childValue == null) {
100
- continue;
101
- } else if (Array.isArray(childValue)) {
102
- if (childValue.every((el) => isPrimitive(el))) {
103
- const primitives = childValue.filter(
104
- (el) => el !== null && el !== undefined
105
- ) as (string | number | boolean)[];
106
- const joined = primitives.map((el) => el.toString()).join(',');
107
- args.push(`--${key}`, childKey, joined);
108
- } else {
109
- for (const el of childValue) {
110
- if (el == null) {
111
- continue;
112
- }
113
- if (typeof el === 'object') {
114
- const mappingPaths = flattenMapping(el, [childKey]);
115
- if (mappingPaths.length) {
116
- args.push(`--${key}`, ...mappingPaths);
117
- }
118
- } else if (isPrimitive(el)) {
119
- args.push(`--${key}`, childKey, el.toString());
120
- }
121
- }
122
- }
123
- } else if (typeof childValue === 'object') {
124
- const mappingPaths = flattenMapping(childValue, []);
125
- if (mappingPaths.length) {
126
- args.push(`--${key}`, childKey, ...mappingPaths);
127
- }
128
- }
129
- }
130
- }
131
- }
132
-
133
- return args;
134
- }