@redocly/cli 1.3.0 → 1.4.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/README.md +15 -7
- package/lib/__mocks__/@redocly/openapi-core.d.ts +1 -0
- package/lib/__mocks__/@redocly/openapi-core.js +4 -3
- package/lib/__mocks__/utils.d.ts +2 -0
- package/lib/__mocks__/utils.js +3 -1
- package/lib/__tests__/commands/build-docs.test.js +2 -2
- package/lib/__tests__/commands/bundle.test.js +7 -7
- package/lib/__tests__/commands/join.test.js +25 -18
- package/lib/__tests__/commands/lint.test.js +15 -15
- package/lib/__tests__/commands/push-region.test.js +2 -2
- package/lib/__tests__/commands/push.test.js +30 -30
- package/lib/__tests__/fetch-with-timeout.test.js +2 -2
- package/lib/__tests__/utils.test.js +63 -32
- package/lib/__tests__/wrapper.test.js +3 -3
- package/lib/assert-node-version.js +1 -1
- package/lib/commands/build-docs/index.js +9 -9
- package/lib/commands/build-docs/types.d.ts +2 -2
- package/lib/commands/build-docs/utils.js +10 -10
- package/lib/commands/bundle.d.ts +1 -1
- package/lib/commands/bundle.js +25 -25
- package/lib/commands/join.d.ts +1 -1
- package/lib/commands/join.js +49 -48
- package/lib/commands/lint.d.ts +1 -1
- package/lib/commands/lint.js +22 -22
- package/lib/commands/login.d.ts +1 -1
- package/lib/commands/login.js +3 -3
- package/lib/commands/preview-docs/index.d.ts +1 -1
- package/lib/commands/preview-docs/index.js +7 -7
- package/lib/commands/preview-docs/preview-server/hot.js +19 -2
- package/lib/commands/preview-docs/preview-server/preview-server.js +15 -14
- package/lib/commands/preview-docs/preview-server/server.d.ts +3 -1
- package/lib/commands/preview-docs/preview-server/server.js +2 -2
- package/lib/commands/push.d.ts +2 -2
- package/lib/commands/push.js +31 -31
- package/lib/commands/split/__tests__/index.test.js +9 -9
- package/lib/commands/split/index.d.ts +2 -2
- package/lib/commands/split/index.js +41 -40
- package/lib/commands/split/types.d.ts +2 -2
- package/lib/commands/split/types.js +2 -2
- package/lib/commands/stats.d.ts +1 -1
- package/lib/commands/stats.js +9 -9
- package/lib/fetch-with-timeout.js +5 -2
- package/lib/index.js +11 -12
- package/lib/types.d.ts +6 -6
- package/lib/update-version-notifier.js +18 -18
- package/lib/utils.d.ts +6 -3
- package/lib/utils.js +66 -38
- package/lib/wrapper.js +5 -5
- package/package.json +4 -3
- package/src/__mocks__/@redocly/openapi-core.ts +1 -0
- package/src/__mocks__/utils.ts +2 -0
- package/src/__tests__/commands/join.test.ts +37 -7
- package/src/__tests__/utils.test.ts +45 -1
- package/src/commands/join.ts +8 -3
- package/src/commands/preview-docs/preview-server/hot.js +19 -2
- package/src/commands/preview-docs/preview-server/preview-server.ts +6 -4
- package/src/commands/preview-docs/preview-server/server.ts +2 -2
- package/src/commands/split/__tests__/index.test.ts +14 -5
- package/src/commands/split/index.ts +25 -17
- package/src/fetch-with-timeout.ts +3 -0
- package/src/index.ts +0 -1
- package/src/utils.ts +40 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -3,12 +3,13 @@ import * as path from 'path';
|
|
|
3
3
|
import * as openapiCore from '@redocly/openapi-core';
|
|
4
4
|
import { ComponentsFiles } from '../types';
|
|
5
5
|
import { blue, green } from 'colorette';
|
|
6
|
+
import { writeToFileByExtension } from '../../../utils';
|
|
6
7
|
|
|
7
8
|
const utils = require('../../../utils');
|
|
8
9
|
|
|
9
10
|
jest.mock('../../../utils', () => ({
|
|
10
11
|
...jest.requireActual('../../../utils'),
|
|
11
|
-
|
|
12
|
+
writeToFileByExtension: jest.fn(),
|
|
12
13
|
}));
|
|
13
14
|
|
|
14
15
|
jest.mock('@redocly/openapi-core', () => ({
|
|
@@ -65,7 +66,9 @@ describe('#split', () => {
|
|
|
65
66
|
openapiDir,
|
|
66
67
|
path.join(openapiDir, 'paths'),
|
|
67
68
|
componentsFiles,
|
|
68
|
-
'_'
|
|
69
|
+
'_',
|
|
70
|
+
undefined,
|
|
71
|
+
'yaml'
|
|
69
72
|
);
|
|
70
73
|
|
|
71
74
|
expect(openapiCore.slash).toHaveBeenCalledWith('paths/test.yaml');
|
|
@@ -82,7 +85,9 @@ describe('#split', () => {
|
|
|
82
85
|
openapiDir,
|
|
83
86
|
path.join(openapiDir, 'webhooks'),
|
|
84
87
|
componentsFiles,
|
|
85
|
-
'webhook_'
|
|
88
|
+
'webhook_',
|
|
89
|
+
undefined,
|
|
90
|
+
'yaml'
|
|
86
91
|
);
|
|
87
92
|
|
|
88
93
|
expect(openapiCore.slash).toHaveBeenCalledWith('webhooks/test.yaml');
|
|
@@ -99,7 +104,9 @@ describe('#split', () => {
|
|
|
99
104
|
openapiDir,
|
|
100
105
|
path.join(openapiDir, 'webhooks'),
|
|
101
106
|
componentsFiles,
|
|
102
|
-
'webhook_'
|
|
107
|
+
'webhook_',
|
|
108
|
+
undefined,
|
|
109
|
+
'yaml'
|
|
103
110
|
);
|
|
104
111
|
|
|
105
112
|
expect(openapiCore.slash).toHaveBeenCalledWith('webhooks/test.yaml');
|
|
@@ -118,7 +125,9 @@ describe('#split', () => {
|
|
|
118
125
|
openapiDir,
|
|
119
126
|
path.join(openapiDir, 'paths'),
|
|
120
127
|
componentsFiles,
|
|
121
|
-
'_'
|
|
128
|
+
'_',
|
|
129
|
+
undefined,
|
|
130
|
+
'yaml'
|
|
122
131
|
);
|
|
123
132
|
|
|
124
133
|
expect(utils.escapeLanguageName).nthCalledWith(1, 'C#');
|
|
@@ -10,10 +10,11 @@ import {
|
|
|
10
10
|
printExecutionTime,
|
|
11
11
|
pathToFilename,
|
|
12
12
|
readYaml,
|
|
13
|
-
writeYaml,
|
|
14
13
|
exitWithError,
|
|
15
14
|
escapeLanguageName,
|
|
16
15
|
langToExt,
|
|
16
|
+
writeToFileByExtension,
|
|
17
|
+
getAndValidateFileExtension,
|
|
17
18
|
} from '../../utils';
|
|
18
19
|
import { isString, isObject, isEmptyObject } from '../../js-utils';
|
|
19
20
|
import {
|
|
@@ -46,8 +47,9 @@ export async function handleSplit(argv: SplitOptions) {
|
|
|
46
47
|
const startedAt = performance.now();
|
|
47
48
|
const { api, outDir, separator } = argv;
|
|
48
49
|
validateDefinitionFileName(api!);
|
|
50
|
+
const ext = getAndValidateFileExtension(api);
|
|
49
51
|
const openapi = readYaml(api!) as Oas3Definition | Oas3_1Definition;
|
|
50
|
-
splitDefinition(openapi, outDir, separator);
|
|
52
|
+
splitDefinition(openapi, outDir, separator, ext);
|
|
51
53
|
process.stderr.write(
|
|
52
54
|
`🪓 Document: ${blue(api!)} ${green('is successfully split')}
|
|
53
55
|
and all related files are saved to the directory: ${blue(outDir)} \n`
|
|
@@ -58,18 +60,21 @@ export async function handleSplit(argv: SplitOptions) {
|
|
|
58
60
|
function splitDefinition(
|
|
59
61
|
openapi: Oas3Definition | Oas3_1Definition,
|
|
60
62
|
openapiDir: string,
|
|
61
|
-
pathSeparator: string
|
|
63
|
+
pathSeparator: string,
|
|
64
|
+
ext: string
|
|
62
65
|
) {
|
|
63
66
|
fs.mkdirSync(openapiDir, { recursive: true });
|
|
64
67
|
|
|
65
68
|
const componentsFiles: ComponentsFiles = {};
|
|
66
|
-
iterateComponents(openapi, openapiDir, componentsFiles);
|
|
69
|
+
iterateComponents(openapi, openapiDir, componentsFiles, ext);
|
|
67
70
|
iteratePathItems(
|
|
68
71
|
openapi.paths,
|
|
69
72
|
openapiDir,
|
|
70
73
|
path.join(openapiDir, 'paths'),
|
|
71
74
|
componentsFiles,
|
|
72
|
-
pathSeparator
|
|
75
|
+
pathSeparator,
|
|
76
|
+
undefined,
|
|
77
|
+
ext
|
|
73
78
|
);
|
|
74
79
|
const webhooks =
|
|
75
80
|
(openapi as Oas3_1Definition).webhooks || (openapi as Oas3Definition)['x-webhooks'];
|
|
@@ -80,11 +85,12 @@ function splitDefinition(
|
|
|
80
85
|
path.join(openapiDir, 'webhooks'),
|
|
81
86
|
componentsFiles,
|
|
82
87
|
pathSeparator,
|
|
83
|
-
'webhook_'
|
|
88
|
+
'webhook_',
|
|
89
|
+
ext
|
|
84
90
|
);
|
|
85
91
|
|
|
86
92
|
replace$Refs(openapi, openapiDir, componentsFiles);
|
|
87
|
-
|
|
93
|
+
writeToFileByExtension(openapi, path.join(openapiDir, `openapi.${ext}`));
|
|
88
94
|
}
|
|
89
95
|
|
|
90
96
|
function isStartsWithComponents(node: string) {
|
|
@@ -135,7 +141,7 @@ function traverseDirectoryDeepCallback(
|
|
|
135
141
|
if (isNotYaml(filename)) return;
|
|
136
142
|
const pathData = readYaml(filename);
|
|
137
143
|
replace$Refs(pathData, directory, componentsFiles);
|
|
138
|
-
|
|
144
|
+
writeToFileByExtension(pathData, filename);
|
|
139
145
|
}
|
|
140
146
|
|
|
141
147
|
function crawl(object: any, visitor: any) {
|
|
@@ -251,8 +257,8 @@ function extractFileNameFromPath(filename: string) {
|
|
|
251
257
|
return path.basename(filename, path.extname(filename));
|
|
252
258
|
}
|
|
253
259
|
|
|
254
|
-
function getFileNamePath(componentDirPath: string, componentName: string) {
|
|
255
|
-
return path.join(componentDirPath, componentName) +
|
|
260
|
+
function getFileNamePath(componentDirPath: string, componentName: string, ext: string) {
|
|
261
|
+
return path.join(componentDirPath, componentName) + `.${ext}`;
|
|
256
262
|
}
|
|
257
263
|
|
|
258
264
|
function gatherComponentsFiles(
|
|
@@ -278,13 +284,14 @@ function iteratePathItems(
|
|
|
278
284
|
outDir: string,
|
|
279
285
|
componentsFiles: object,
|
|
280
286
|
pathSeparator: string,
|
|
281
|
-
codeSamplesPathPrefix: string = ''
|
|
287
|
+
codeSamplesPathPrefix: string = '',
|
|
288
|
+
ext: string
|
|
282
289
|
) {
|
|
283
290
|
if (!pathItems) return;
|
|
284
291
|
fs.mkdirSync(outDir, { recursive: true });
|
|
285
292
|
|
|
286
293
|
for (const pathName of Object.keys(pathItems)) {
|
|
287
|
-
const pathFile = `${path.join(outDir, pathToFilename(pathName, pathSeparator))}
|
|
294
|
+
const pathFile = `${path.join(outDir, pathToFilename(pathName, pathSeparator))}.${ext}`;
|
|
288
295
|
const pathData = pathItems[pathName] as Oas3PathItem;
|
|
289
296
|
|
|
290
297
|
if (isRef(pathData)) continue;
|
|
@@ -314,7 +321,7 @@ function iteratePathItems(
|
|
|
314
321
|
};
|
|
315
322
|
}
|
|
316
323
|
}
|
|
317
|
-
|
|
324
|
+
writeToFileByExtension(pathData, pathFile);
|
|
318
325
|
pathItems[pathName] = {
|
|
319
326
|
$ref: slash(path.relative(openapiDir, pathFile)),
|
|
320
327
|
};
|
|
@@ -326,7 +333,8 @@ function iteratePathItems(
|
|
|
326
333
|
function iterateComponents(
|
|
327
334
|
openapi: Oas3Definition | Oas3_1Definition,
|
|
328
335
|
openapiDir: string,
|
|
329
|
-
componentsFiles: ComponentsFiles
|
|
336
|
+
componentsFiles: ComponentsFiles,
|
|
337
|
+
ext: string
|
|
330
338
|
) {
|
|
331
339
|
const { components } = openapi;
|
|
332
340
|
if (components) {
|
|
@@ -340,7 +348,7 @@ function iterateComponents(
|
|
|
340
348
|
function iterateAndGatherComponentsFiles(componentType: Oas3ComponentName) {
|
|
341
349
|
const componentDirPath = path.join(componentsDir, componentType);
|
|
342
350
|
for (const componentName of Object.keys(components?.[componentType] || {})) {
|
|
343
|
-
const filename = getFileNamePath(componentDirPath, componentName);
|
|
351
|
+
const filename = getFileNamePath(componentDirPath, componentName, ext);
|
|
344
352
|
gatherComponentsFiles(components!, componentsFiles, componentType, componentName, filename);
|
|
345
353
|
}
|
|
346
354
|
}
|
|
@@ -350,7 +358,7 @@ function iterateComponents(
|
|
|
350
358
|
const componentDirPath = path.join(componentsDir, componentType);
|
|
351
359
|
createComponentDir(componentDirPath, componentType);
|
|
352
360
|
for (const componentName of Object.keys(components?.[componentType] || {})) {
|
|
353
|
-
const filename = getFileNamePath(componentDirPath, componentName);
|
|
361
|
+
const filename = getFileNamePath(componentDirPath, componentName, ext);
|
|
354
362
|
const componentData = components?.[componentType]?.[componentName];
|
|
355
363
|
replace$Refs(componentData, path.dirname(filename), componentsFiles);
|
|
356
364
|
implicitlyReferenceDiscriminator(
|
|
@@ -369,7 +377,7 @@ function iterateComponents(
|
|
|
369
377
|
)
|
|
370
378
|
);
|
|
371
379
|
} else {
|
|
372
|
-
|
|
380
|
+
writeToFileByExtension(componentData, filename);
|
|
373
381
|
}
|
|
374
382
|
|
|
375
383
|
if (isNotSecurityComponentType(componentType)) {
|
|
@@ -12,6 +12,9 @@ export default async (url: string, options = {}) => {
|
|
|
12
12
|
controller.abort();
|
|
13
13
|
}, TIMEOUT);
|
|
14
14
|
|
|
15
|
+
// FIXME: fix this (possibly along with this issue: https://github.com/Redocly/redocly-cli/issues/1260)
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
17
|
+
// @ts-ignore
|
|
15
18
|
const res = await nodeFetch(url, { signal: controller.signal, ...options });
|
|
16
19
|
clearTimeout(timeout);
|
|
17
20
|
return res;
|
package/src/index.ts
CHANGED
package/src/utils.ts
CHANGED
|
@@ -25,7 +25,14 @@ import {
|
|
|
25
25
|
RedoclyClient,
|
|
26
26
|
} from '@redocly/openapi-core';
|
|
27
27
|
import { ConfigValidationError } from '@redocly/openapi-core/lib/config';
|
|
28
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
Totals,
|
|
30
|
+
outputExtensions,
|
|
31
|
+
Entrypoint,
|
|
32
|
+
ConfigApis,
|
|
33
|
+
CommandOptions,
|
|
34
|
+
OutputExtensions,
|
|
35
|
+
} from './types';
|
|
29
36
|
import { isEmptyObject } from '@redocly/openapi-core/lib/utils';
|
|
30
37
|
import { Arguments } from 'yargs';
|
|
31
38
|
import { version } from './update-version-notifier';
|
|
@@ -209,6 +216,17 @@ export function readYaml(filename: string) {
|
|
|
209
216
|
return parseYaml(fs.readFileSync(filename, 'utf-8'), { filename });
|
|
210
217
|
}
|
|
211
218
|
|
|
219
|
+
export function writeToFileByExtension(data: unknown, filePath: string, noRefs?: boolean) {
|
|
220
|
+
const ext = getAndValidateFileExtension(filePath);
|
|
221
|
+
|
|
222
|
+
if (ext === 'json') {
|
|
223
|
+
writeJson(data, filePath);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
writeYaml(data, filePath, noRefs);
|
|
228
|
+
}
|
|
229
|
+
|
|
212
230
|
export function writeYaml(data: any, filename: string, noRefs = false) {
|
|
213
231
|
const content = stringifyYaml(data, { noRefs });
|
|
214
232
|
|
|
@@ -220,6 +238,27 @@ export function writeYaml(data: any, filename: string, noRefs = false) {
|
|
|
220
238
|
fs.writeFileSync(filename, content);
|
|
221
239
|
}
|
|
222
240
|
|
|
241
|
+
export function writeJson(data: unknown, filename: string) {
|
|
242
|
+
const content = JSON.stringify(data, null, 2);
|
|
243
|
+
|
|
244
|
+
if (process.env.NODE_ENV === 'test') {
|
|
245
|
+
process.stderr.write(content);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
fs.mkdirSync(dirname(filename), { recursive: true });
|
|
249
|
+
fs.writeFileSync(filename, content);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export function getAndValidateFileExtension(fileName: string): NonNullable<OutputExtensions> {
|
|
253
|
+
const ext = fileName.split('.').pop();
|
|
254
|
+
|
|
255
|
+
if (['yaml', 'yml', 'json'].includes(ext!)) {
|
|
256
|
+
return ext as NonNullable<OutputExtensions>;
|
|
257
|
+
}
|
|
258
|
+
process.stderr.write(yellow(`Unsupported file extension: ${ext}. Using yaml.\n`));
|
|
259
|
+
return 'yaml';
|
|
260
|
+
}
|
|
261
|
+
|
|
223
262
|
export function pluralize(label: string, num: number) {
|
|
224
263
|
if (label.endsWith('is')) {
|
|
225
264
|
[label] = label.split(' ');
|