@openapi-qraft/plugin 2.15.0-beta.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.
- package/CHANGELOG.md +19 -0
- package/dist/lib/QraftCommand.d.ts +8 -62
- package/dist/lib/QraftCommand.d.ts.map +1 -1
- package/dist/lib/QraftCommand.js +30 -193
- package/dist/lib/QraftCommand.js.map +1 -1
- package/dist/lib/QraftCommandPlugin.d.ts +2 -6
- package/dist/lib/QraftCommandPlugin.d.ts.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/package.json +4 -3
- package/src/lib/QraftCommand.ts +58 -381
- package/src/lib/QraftCommandPlugin.ts +2 -11
- package/src/packageVersion.ts +1 -1
- package/dist/lib/GeneratorFile.d.ts +0 -9
- package/dist/lib/GeneratorFile.d.ts.map +0 -1
- package/dist/lib/GeneratorFile.js +0 -2
- package/dist/lib/GeneratorFile.js.map +0 -1
- package/dist/lib/OutputOptions.d.ts +0 -6
- package/dist/lib/OutputOptions.d.ts.map +0 -1
- package/dist/lib/OutputOptions.js +0 -2
- package/dist/lib/OutputOptions.js.map +0 -1
- package/dist/lib/RedoclyConfigCommand.d.ts +0 -22
- package/dist/lib/RedoclyConfigCommand.d.ts.map +0 -1
- package/dist/lib/RedoclyConfigCommand.js +0 -133
- package/dist/lib/RedoclyConfigCommand.js.map +0 -1
- package/dist/lib/fileHeader.d.ts +0 -2
- package/dist/lib/fileHeader.d.ts.map +0 -1
- package/dist/lib/fileHeader.js +0 -7
- package/dist/lib/fileHeader.js.map +0 -1
- package/dist/lib/formatFileHeader.d.ts +0 -2
- package/dist/lib/formatFileHeader.d.ts.map +0 -1
- package/dist/lib/formatFileHeader.js +0 -6
- package/dist/lib/formatFileHeader.js.map +0 -1
- package/dist/lib/getRedocAPIsToQraft.d.ts +0 -16
- package/dist/lib/getRedocAPIsToQraft.d.ts.map +0 -1
- package/dist/lib/getRedocAPIsToQraft.js +0 -45
- package/dist/lib/getRedocAPIsToQraft.js.map +0 -1
- package/dist/lib/handleSchemaInput.d.ts +0 -10
- package/dist/lib/handleSchemaInput.d.ts.map +0 -1
- package/dist/lib/handleSchemaInput.js +0 -40
- package/dist/lib/handleSchemaInput.js.map +0 -1
- package/dist/lib/loadRedoclyConfig.d.ts +0 -12
- package/dist/lib/loadRedoclyConfig.d.ts.map +0 -1
- package/dist/lib/loadRedoclyConfig.js +0 -17
- package/dist/lib/loadRedoclyConfig.js.map +0 -1
- package/dist/lib/maybeEscapeShellArg.d.ts +0 -2
- package/dist/lib/maybeEscapeShellArg.d.ts.map +0 -1
- package/dist/lib/maybeEscapeShellArg.js +0 -9
- package/dist/lib/maybeEscapeShellArg.js.map +0 -1
- package/dist/lib/parseConfigToArgs.d.ts +0 -7
- package/dist/lib/parseConfigToArgs.d.ts.map +0 -1
- package/dist/lib/parseConfigToArgs.js +0 -130
- package/dist/lib/parseConfigToArgs.js.map +0 -1
- package/dist/lib/shouldQuoteCommandLineArg.d.ts +0 -11
- package/dist/lib/shouldQuoteCommandLineArg.d.ts.map +0 -1
- package/dist/lib/shouldQuoteCommandLineArg.js +0 -33
- package/dist/lib/shouldQuoteCommandLineArg.js.map +0 -1
- package/dist/lib/vitestFsMock.d.ts +0 -2
- package/dist/lib/vitestFsMock.d.ts.map +0 -1
- package/dist/lib/vitestFsMock.js +0 -16
- package/dist/lib/vitestFsMock.js.map +0 -1
- package/dist/lib/writeGeneratorFiles.d.ts +0 -7
- package/dist/lib/writeGeneratorFiles.d.ts.map +0 -1
- package/dist/lib/writeGeneratorFiles.js +0 -51
- package/dist/lib/writeGeneratorFiles.js.map +0 -1
- package/src/lib/GeneratorFile.ts +0 -5
- package/src/lib/OutputOptions.ts +0 -6
- package/src/lib/RedoclyConfigCommand.ts +0 -232
- package/src/lib/fileHeader.ts +0 -6
- package/src/lib/formatFileHeader.ts +0 -4
- package/src/lib/getRedocAPIsToQraft.ts +0 -87
- package/src/lib/handleSchemaInput.ts +0 -53
- package/src/lib/loadRedoclyConfig.ts +0 -47
- package/src/lib/maybeEscapeShellArg.ts +0 -10
- package/src/lib/parseConfigToArgs.ts +0 -134
- package/src/lib/shouldQuoteCommandLineArg.ts +0 -32
- package/src/lib/vitestFsMock.ts +0 -23
- 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"}
|
package/src/lib/GeneratorFile.ts
DELETED
package/src/lib/OutputOptions.ts
DELETED
|
@@ -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
|
-
};
|
package/src/lib/fileHeader.ts
DELETED
|
@@ -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
|
-
}
|