@redocly/cli 1.8.1 → 1.9.0
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 +22 -0
- package/lib/__tests__/commands/push.test.js +12 -18
- package/lib/cms/commands/__tests__/push-status.test.js +5 -5
- package/lib/cms/commands/push-status.js +3 -2
- package/lib/commands/join.js +17 -25
- package/lib/commands/push.d.ts +9 -4
- package/lib/commands/push.js +5 -4
- package/lib/commands/stats.js +19 -4
- package/lib/index.js +1 -1
- package/lib/utils/js-utils.d.ts +1 -0
- package/lib/utils/js-utils.js +8 -1
- package/lib/utils/update-version-notifier.js +12 -13
- package/package.json +2 -2
- package/src/__tests__/commands/push.test.ts +14 -18
- package/src/cms/commands/__tests__/push-status.test.ts +5 -5
- package/src/cms/commands/push-status.ts +6 -5
- package/src/commands/join.ts +32 -33
- package/src/commands/push.ts +6 -9
- package/src/commands/stats.ts +25 -4
- package/src/index.ts +1 -1
- package/src/utils/js-utils.ts +7 -0
- package/src/utils/update-version-notifier.ts +18 -18
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -5,6 +5,7 @@ import { Spinner } from '../../utils/spinner';
|
|
|
5
5
|
import { DeploymentError } from '../utils';
|
|
6
6
|
import { yellow } from 'colorette';
|
|
7
7
|
import { ReuniteApiClient, getApiKeys, getDomain } from '../api';
|
|
8
|
+
import { capitalize } from '../../utils/js-utils';
|
|
8
9
|
|
|
9
10
|
import type { DeploymentStatus, PushResponse, ScorecardItem } from '../api/types';
|
|
10
11
|
|
|
@@ -177,15 +178,15 @@ function displayDeploymentAndBuildStatus({
|
|
|
177
178
|
case 'success':
|
|
178
179
|
spinner.stop();
|
|
179
180
|
return process.stdout.write(
|
|
180
|
-
`${colors.green(
|
|
181
|
-
|
|
182
|
-
)}
|
|
181
|
+
`${colors.green(`🚀 ${capitalize(buildType)} deploy success.`)}\n${colors.magenta(
|
|
182
|
+
`${capitalize(buildType)} URL`
|
|
183
|
+
)}: ${colors.cyan(previewUrl!)}\n`
|
|
183
184
|
);
|
|
184
185
|
case 'failed':
|
|
185
186
|
spinner.stop();
|
|
186
187
|
throw new DeploymentError(
|
|
187
|
-
`${colors.red(`❌ ${buildType
|
|
188
|
-
|
|
188
|
+
`${colors.red(`❌ ${capitalize(buildType)} deploy fail.`)}\n${colors.magenta(
|
|
189
|
+
`${capitalize(buildType)} URL`
|
|
189
190
|
)}: ${colors.cyan(previewUrl!)}`
|
|
190
191
|
);
|
|
191
192
|
case 'pending':
|
package/src/commands/join.ts
CHANGED
|
@@ -49,6 +49,7 @@ let potentialConflictsTotal = 0;
|
|
|
49
49
|
type JoinDocumentContext = {
|
|
50
50
|
api: string;
|
|
51
51
|
apiFilename: string;
|
|
52
|
+
apiTitle?: string;
|
|
52
53
|
tags: Oas3Tag[];
|
|
53
54
|
potentialConflicts: any;
|
|
54
55
|
tagsPrefix: string;
|
|
@@ -209,6 +210,7 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
209
210
|
const context = {
|
|
210
211
|
api,
|
|
211
212
|
apiFilename,
|
|
213
|
+
apiTitle: info?.title,
|
|
212
214
|
tags,
|
|
213
215
|
potentialConflicts,
|
|
214
216
|
tagsPrefix,
|
|
@@ -218,7 +220,6 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
218
220
|
populateTags(context);
|
|
219
221
|
}
|
|
220
222
|
collectServers(openapi);
|
|
221
|
-
collectInfoDescriptions(openapi, context);
|
|
222
223
|
collectExternalDocs(openapi, context);
|
|
223
224
|
collectPaths(openapi, context);
|
|
224
225
|
collectComponents(openapi, context);
|
|
@@ -242,6 +243,7 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
242
243
|
function populateTags({
|
|
243
244
|
api,
|
|
244
245
|
apiFilename,
|
|
246
|
+
apiTitle,
|
|
245
247
|
tags,
|
|
246
248
|
potentialConflicts,
|
|
247
249
|
tagsPrefix,
|
|
@@ -285,9 +287,10 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
285
287
|
}
|
|
286
288
|
|
|
287
289
|
if (!withoutXTagGroups) {
|
|
288
|
-
|
|
290
|
+
const groupName = apiTitle || apiFilename;
|
|
291
|
+
createXTagGroups(groupName);
|
|
289
292
|
if (!tagDuplicate) {
|
|
290
|
-
populateXTagGroups(entrypointTagName, getIndexGroup(
|
|
293
|
+
populateXTagGroups(entrypointTagName, getIndexGroup(groupName));
|
|
291
294
|
}
|
|
292
295
|
}
|
|
293
296
|
|
|
@@ -302,20 +305,20 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
302
305
|
}
|
|
303
306
|
}
|
|
304
307
|
|
|
305
|
-
function getIndexGroup(
|
|
306
|
-
return joinedDef[xTagGroups].findIndex((item: any) => item.name ===
|
|
308
|
+
function getIndexGroup(name: string): number {
|
|
309
|
+
return joinedDef[xTagGroups].findIndex((item: any) => item.name === name);
|
|
307
310
|
}
|
|
308
311
|
|
|
309
|
-
function createXTagGroups(
|
|
312
|
+
function createXTagGroups(name: string) {
|
|
310
313
|
if (!joinedDef.hasOwnProperty(xTagGroups)) {
|
|
311
314
|
joinedDef[xTagGroups] = [];
|
|
312
315
|
}
|
|
313
316
|
|
|
314
|
-
if (!joinedDef[xTagGroups].some((g: any) => g.name ===
|
|
315
|
-
joinedDef[xTagGroups].push({ name
|
|
317
|
+
if (!joinedDef[xTagGroups].some((g: any) => g.name === name)) {
|
|
318
|
+
joinedDef[xTagGroups].push({ name, tags: [] });
|
|
316
319
|
}
|
|
317
320
|
|
|
318
|
-
const indexGroup = getIndexGroup(
|
|
321
|
+
const indexGroup = getIndexGroup(name);
|
|
319
322
|
|
|
320
323
|
if (!joinedDef[xTagGroups][indexGroup].hasOwnProperty(Tags)) {
|
|
321
324
|
joinedDef[xTagGroups][indexGroup][Tags] = [];
|
|
@@ -344,27 +347,6 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
344
347
|
}
|
|
345
348
|
}
|
|
346
349
|
|
|
347
|
-
function collectInfoDescriptions(
|
|
348
|
-
openapi: Oas3Definition,
|
|
349
|
-
{ apiFilename, componentsPrefix }: JoinDocumentContext
|
|
350
|
-
) {
|
|
351
|
-
const { info } = openapi;
|
|
352
|
-
if (info?.description) {
|
|
353
|
-
const groupIndex = joinedDef[xTagGroups] ? getIndexGroup(apiFilename) : -1;
|
|
354
|
-
if (
|
|
355
|
-
joinedDef.hasOwnProperty(xTagGroups) &&
|
|
356
|
-
groupIndex !== -1 &&
|
|
357
|
-
joinedDef[xTagGroups][groupIndex]['tags'] &&
|
|
358
|
-
joinedDef[xTagGroups][groupIndex]['tags'].length
|
|
359
|
-
) {
|
|
360
|
-
joinedDef[xTagGroups][groupIndex]['description'] = addComponentsPrefix(
|
|
361
|
-
info.description,
|
|
362
|
-
componentsPrefix!
|
|
363
|
-
);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
|
|
368
350
|
function collectExternalDocs(openapi: Oas3Definition, { api }: JoinDocumentContext) {
|
|
369
351
|
const { externalDocs } = openapi;
|
|
370
352
|
if (externalDocs) {
|
|
@@ -380,7 +362,14 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
380
362
|
|
|
381
363
|
function collectPaths(
|
|
382
364
|
openapi: Oas3Definition,
|
|
383
|
-
{
|
|
365
|
+
{
|
|
366
|
+
apiFilename,
|
|
367
|
+
apiTitle,
|
|
368
|
+
api,
|
|
369
|
+
potentialConflicts,
|
|
370
|
+
tagsPrefix,
|
|
371
|
+
componentsPrefix,
|
|
372
|
+
}: JoinDocumentContext
|
|
384
373
|
) {
|
|
385
374
|
const { paths } = openapi;
|
|
386
375
|
const operationsSet = new Set(keysOf<typeof OPENAPI3_METHOD>(OPENAPI3_METHOD));
|
|
@@ -532,6 +521,7 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
532
521
|
populateTags({
|
|
533
522
|
api,
|
|
534
523
|
apiFilename,
|
|
524
|
+
apiTitle,
|
|
535
525
|
tags: formatTags(tags),
|
|
536
526
|
potentialConflicts,
|
|
537
527
|
tagsPrefix,
|
|
@@ -542,6 +532,7 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
542
532
|
populateTags({
|
|
543
533
|
api,
|
|
544
534
|
apiFilename,
|
|
535
|
+
apiTitle,
|
|
545
536
|
tags: formatTags(['other']),
|
|
546
537
|
potentialConflicts,
|
|
547
538
|
tagsPrefix: tagsPrefix || apiFilename,
|
|
@@ -599,7 +590,14 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
599
590
|
function collectWebhooks(
|
|
600
591
|
oasVersion: SpecVersion,
|
|
601
592
|
openapi: Oas3_1Definition,
|
|
602
|
-
{
|
|
593
|
+
{
|
|
594
|
+
apiFilename,
|
|
595
|
+
apiTitle,
|
|
596
|
+
api,
|
|
597
|
+
potentialConflicts,
|
|
598
|
+
tagsPrefix,
|
|
599
|
+
componentsPrefix,
|
|
600
|
+
}: JoinDocumentContext
|
|
603
601
|
) {
|
|
604
602
|
const webhooks = oasVersion === SpecVersion.OAS3_1 ? 'webhooks' : 'x-webhooks';
|
|
605
603
|
const openapiWebhooks = openapi[webhooks];
|
|
@@ -628,6 +626,7 @@ export async function handleJoin(argv: JoinOptions, config: Config, packageVersi
|
|
|
628
626
|
populateTags({
|
|
629
627
|
api,
|
|
630
628
|
apiFilename,
|
|
629
|
+
apiTitle,
|
|
631
630
|
tags: formatTags(tags),
|
|
632
631
|
potentialConflicts,
|
|
633
632
|
tagsPrefix,
|
|
@@ -802,7 +801,7 @@ async function validateApi(
|
|
|
802
801
|
function crawl(object: any, visitor: any) {
|
|
803
802
|
if (!isObject(object)) return;
|
|
804
803
|
for (const key of Object.keys(object)) {
|
|
805
|
-
visitor(object, key);
|
|
804
|
+
visitor(object[key], key);
|
|
806
805
|
crawl(object[key], visitor);
|
|
807
806
|
}
|
|
808
807
|
}
|
package/src/commands/push.ts
CHANGED
|
@@ -55,7 +55,7 @@ export function commonPushHandler({
|
|
|
55
55
|
if (project && mountPath) {
|
|
56
56
|
return handleCMSPush;
|
|
57
57
|
}
|
|
58
|
-
return handlePush;
|
|
58
|
+
return transformPush(handlePush);
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
export async function handlePush(argv: PushOptions, config: Config): Promise<void> {
|
|
@@ -354,8 +354,7 @@ export function getDestinationProps(
|
|
|
354
354
|
}
|
|
355
355
|
|
|
356
356
|
type BarePushArgs = Omit<PushOptions, 'destination' | 'branchName'> & {
|
|
357
|
-
|
|
358
|
-
maybeBranchName?: string;
|
|
357
|
+
apis?: string[];
|
|
359
358
|
branch?: string;
|
|
360
359
|
destination?: string;
|
|
361
360
|
};
|
|
@@ -364,9 +363,7 @@ export const transformPush =
|
|
|
364
363
|
(callback: typeof handlePush) =>
|
|
365
364
|
(
|
|
366
365
|
{
|
|
367
|
-
|
|
368
|
-
maybeDestination,
|
|
369
|
-
maybeBranchName,
|
|
366
|
+
apis,
|
|
370
367
|
branch,
|
|
371
368
|
'batch-id': batchId,
|
|
372
369
|
'job-id': jobId,
|
|
@@ -374,6 +371,8 @@ export const transformPush =
|
|
|
374
371
|
}: BarePushArgs & { 'batch-id'?: string },
|
|
375
372
|
config: Config
|
|
376
373
|
) => {
|
|
374
|
+
const [maybeApiOrDestination, maybeDestination, maybeBranchName] = apis || [];
|
|
375
|
+
|
|
377
376
|
if (batchId) {
|
|
378
377
|
process.stderr.write(
|
|
379
378
|
yellow(
|
|
@@ -410,12 +409,10 @@ export const transformPush =
|
|
|
410
409
|
apiFile = maybeApiOrDestination;
|
|
411
410
|
}
|
|
412
411
|
|
|
413
|
-
destination = rest.destination || destination;
|
|
414
|
-
|
|
415
412
|
return callback(
|
|
416
413
|
{
|
|
417
414
|
...rest,
|
|
418
|
-
destination,
|
|
415
|
+
destination: rest.destination ?? destination,
|
|
419
416
|
api: apiFile,
|
|
420
417
|
branchName: branch ?? maybeBranchName,
|
|
421
418
|
'job-id': jobId || batchId,
|
package/src/commands/stats.ts
CHANGED
|
@@ -46,15 +46,37 @@ function printStatsJson(statsAccumulator: StatsAccumulator) {
|
|
|
46
46
|
process.stdout.write(JSON.stringify(json, null, 2));
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
function
|
|
50
|
-
|
|
49
|
+
function printStatsMarkdown(statsAccumulator: StatsAccumulator) {
|
|
50
|
+
let output = '| Feature | Count |\n| --- | --- |\n';
|
|
51
|
+
for (const key of Object.keys(statsAccumulator)) {
|
|
52
|
+
output +=
|
|
53
|
+
'| ' +
|
|
54
|
+
statsAccumulator[key as StatsName].metric +
|
|
55
|
+
' | ' +
|
|
56
|
+
statsAccumulator[key as StatsName].total +
|
|
57
|
+
' |\n';
|
|
58
|
+
}
|
|
59
|
+
process.stdout.write(output);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function printStats(
|
|
63
|
+
statsAccumulator: StatsAccumulator,
|
|
64
|
+
api: string,
|
|
65
|
+
startedAt: number,
|
|
66
|
+
format: string
|
|
67
|
+
) {
|
|
51
68
|
switch (format) {
|
|
52
69
|
case 'stylish':
|
|
70
|
+
process.stderr.write(`Document: ${colors.magenta(api)} stats:\n\n`);
|
|
53
71
|
printStatsStylish(statsAccumulator);
|
|
72
|
+
printExecutionTime('stats', startedAt, api);
|
|
54
73
|
break;
|
|
55
74
|
case 'json':
|
|
56
75
|
printStatsJson(statsAccumulator);
|
|
57
76
|
break;
|
|
77
|
+
case 'markdown':
|
|
78
|
+
printStatsMarkdown(statsAccumulator);
|
|
79
|
+
break;
|
|
58
80
|
}
|
|
59
81
|
}
|
|
60
82
|
|
|
@@ -107,6 +129,5 @@ export async function handleStats(argv: StatsOptions, config: Config) {
|
|
|
107
129
|
ctx,
|
|
108
130
|
});
|
|
109
131
|
|
|
110
|
-
printStats(statsAccumulator, path, argv.format);
|
|
111
|
-
printExecutionTime('stats', startedAt, path);
|
|
132
|
+
printStats(statsAccumulator, path, startedAt, argv.format);
|
|
112
133
|
}
|
package/src/index.ts
CHANGED
|
@@ -46,7 +46,7 @@ yargs
|
|
|
46
46
|
},
|
|
47
47
|
format: {
|
|
48
48
|
description: 'Use a specific output format.',
|
|
49
|
-
choices: ['stylish', 'json'] as ReadonlyArray<OutputFormat>,
|
|
49
|
+
choices: ['stylish', 'json', 'markdown'] as ReadonlyArray<OutputFormat>,
|
|
50
50
|
default: 'stylish' as OutputFormat,
|
|
51
51
|
},
|
|
52
52
|
}),
|
package/src/utils/js-utils.ts
CHANGED
|
@@ -64,27 +64,27 @@ const renderUpdateBanner = (current: string, latest: string) => {
|
|
|
64
64
|
const maxLength = Math.max(...messageLines.map((line) => cleanColors(line).length));
|
|
65
65
|
|
|
66
66
|
const border = yellow('═'.repeat(maxLength + SPACE_TO_BORDER));
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
67
|
+
const extraSpaces = ' '.repeat(SPACE_TO_BORDER);
|
|
68
|
+
|
|
69
|
+
const banner = [
|
|
70
|
+
'',
|
|
71
|
+
extraSpaces + yellow('╔' + border + '╗'),
|
|
72
|
+
extraSpaces + yellow('║' + ' '.repeat(maxLength + SPACE_TO_BORDER) + '║'),
|
|
73
|
+
messageLines.map(getLineWithPadding(maxLength, extraSpaces)).join('\n'),
|
|
74
|
+
extraSpaces + yellow('║' + ' '.repeat(maxLength + SPACE_TO_BORDER) + '║'),
|
|
75
|
+
extraSpaces + yellow('╚' + border + '╝'),
|
|
76
|
+
'',
|
|
77
|
+
'',
|
|
78
|
+
].join('\n');
|
|
80
79
|
process.stderr.write(banner);
|
|
81
80
|
};
|
|
82
81
|
|
|
83
|
-
const getLineWithPadding =
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
82
|
+
const getLineWithPadding =
|
|
83
|
+
(maxLength: number, extraSpaces: string) =>
|
|
84
|
+
(line: string): string => {
|
|
85
|
+
const padding = ' '.repeat(maxLength - cleanColors(line).length);
|
|
86
|
+
return `${extraSpaces}${yellow('║')} ${line}${padding} ${yellow('║')}`;
|
|
87
|
+
};
|
|
88
88
|
|
|
89
89
|
const isNeedToBeCached = (): boolean => {
|
|
90
90
|
try {
|