@redocly/cli 1.18.0 → 1.19.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/__mocks__/@redocly/openapi-core.d.ts +2 -2
- package/lib/__mocks__/@redocly/openapi-core.js +1 -0
- package/lib/__mocks__/fs.d.ts +0 -1
- package/lib/__mocks__/perf_hooks.d.ts +0 -1
- package/lib/__mocks__/redoc.d.ts +0 -1
- package/lib/__tests__/commands/build-docs.test.js +21 -23
- package/lib/__tests__/commands/bundle.test.js +21 -30
- package/lib/__tests__/commands/join.test.js +101 -70
- package/lib/__tests__/commands/lint.test.js +54 -54
- package/lib/__tests__/commands/push-region.test.js +24 -25
- package/lib/__tests__/commands/push.test.js +269 -170
- package/lib/__tests__/fetch-with-timeout.test.js +3 -12
- package/lib/__tests__/fixtures/config.d.ts +0 -1
- package/lib/__tests__/utils.test.js +32 -37
- package/lib/__tests__/wrapper.test.js +31 -20
- package/lib/cms/api/__tests__/api.client.test.js +29 -38
- package/lib/cms/api/api-client.d.ts +0 -2
- package/lib/cms/api/api-client.js +106 -127
- package/lib/cms/api/api-keys.js +1 -2
- package/lib/cms/api/domains.js +1 -2
- package/lib/cms/commands/__tests__/push-status.test.js +251 -162
- package/lib/cms/commands/__tests__/push.test.js +120 -102
- package/lib/cms/commands/__tests__/utils.test.js +12 -21
- package/lib/cms/commands/push-status.d.ts +3 -2
- package/lib/cms/commands/push-status.js +94 -106
- package/lib/cms/commands/push.d.ts +3 -2
- package/lib/cms/commands/push.js +66 -75
- package/lib/cms/commands/utils.js +20 -34
- package/lib/commands/build-docs/index.d.ts +2 -2
- package/lib/commands/build-docs/index.js +8 -17
- package/lib/commands/build-docs/utils.js +26 -38
- package/lib/commands/bundle.d.ts +2 -2
- package/lib/commands/bundle.js +70 -94
- package/lib/commands/join.d.ts +2 -2
- package/lib/commands/join.js +377 -390
- package/lib/commands/lint.d.ts +2 -2
- package/lib/commands/lint.js +70 -78
- package/lib/commands/login.d.ts +3 -2
- package/lib/commands/login.js +9 -21
- package/lib/commands/preview-docs/index.d.ts +2 -2
- package/lib/commands/preview-docs/index.js +92 -106
- package/lib/commands/preview-docs/preview-server/preview-server.js +64 -76
- package/lib/commands/preview-docs/preview-server/server.d.ts +0 -3
- package/lib/commands/preview-docs/preview-server/server.js +6 -6
- package/lib/commands/preview-project/index.d.ts +2 -1
- package/lib/commands/preview-project/index.js +5 -14
- package/lib/commands/push.d.ts +8 -11
- package/lib/commands/push.js +177 -195
- package/lib/commands/split/__tests__/index.test.js +31 -25
- package/lib/commands/split/index.d.ts +2 -1
- package/lib/commands/split/index.js +22 -35
- package/lib/commands/stats.d.ts +2 -2
- package/lib/commands/stats.js +34 -45
- package/lib/index.js +32 -46
- package/lib/types.d.ts +2 -2
- package/lib/utils/__mocks__/miscellaneous.d.ts +0 -1
- package/lib/utils/fetch-with-timeout.js +7 -12
- package/lib/utils/getCommandNameFromArgs.js +2 -4
- package/lib/utils/js-utils.js +6 -7
- package/lib/utils/miscellaneous.d.ts +9 -5
- package/lib/utils/miscellaneous.js +150 -160
- package/lib/utils/update-version-notifier.js +4 -13
- package/lib/wrapper.d.ts +9 -2
- package/lib/wrapper.js +27 -16
- package/package.json +5 -3
- package/src/__mocks__/@redocly/openapi-core.ts +1 -0
- package/src/__tests__/commands/build-docs.test.ts +5 -4
- package/src/__tests__/commands/join.test.ts +51 -51
- package/src/__tests__/commands/push-region.test.ts +10 -8
- package/src/__tests__/commands/push.test.ts +127 -102
- package/src/__tests__/utils.test.ts +1 -0
- package/src/__tests__/wrapper.test.ts +24 -2
- package/src/cms/commands/__tests__/push-status.test.ts +70 -56
- package/src/cms/commands/__tests__/push.test.ts +30 -24
- package/src/cms/commands/push-status.ts +8 -7
- package/src/cms/commands/push.ts +19 -13
- package/src/commands/build-docs/index.ts +10 -5
- package/src/commands/bundle.ts +14 -6
- package/src/commands/join.ts +10 -6
- package/src/commands/lint.ts +20 -9
- package/src/commands/login.ts +4 -2
- package/src/commands/preview-docs/index.ts +6 -1
- package/src/commands/preview-project/index.ts +5 -4
- package/src/commands/push.ts +14 -16
- package/src/commands/split/__tests__/index.test.ts +17 -6
- package/src/commands/split/index.ts +6 -4
- package/src/commands/stats.ts +4 -2
- package/src/utils/miscellaneous.ts +55 -26
- package/src/wrapper.ts +37 -11
- package/tsconfig.tsbuildinfo +1 -1
package/src/commands/lint.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { blue, gray } from 'colorette';
|
|
2
|
+
import { performance } from 'perf_hooks';
|
|
1
3
|
import {
|
|
2
|
-
Config,
|
|
3
4
|
formatProblems,
|
|
4
5
|
getMergedConfig,
|
|
5
6
|
getTotals,
|
|
@@ -13,19 +14,19 @@ import {
|
|
|
13
14
|
getExecutionTime,
|
|
14
15
|
getFallbackApisOrExit,
|
|
15
16
|
handleError,
|
|
17
|
+
notifyAboutIncompatibleConfigOptions,
|
|
16
18
|
pluralize,
|
|
17
19
|
printConfigLintTotals,
|
|
18
20
|
printLintTotals,
|
|
19
21
|
printUnusedWarnings,
|
|
20
22
|
} from '../utils/miscellaneous';
|
|
21
|
-
import {
|
|
22
|
-
import { performance } from 'perf_hooks';
|
|
23
|
+
import { getCommandNameFromArgs } from '../utils/getCommandNameFromArgs';
|
|
23
24
|
|
|
25
|
+
import type { Arguments } from 'yargs';
|
|
24
26
|
import type { OutputFormat, ProblemSeverity, RuleSeverity } from '@redocly/openapi-core';
|
|
25
27
|
import type { RawConfigProcessor } from '@redocly/openapi-core/lib/config';
|
|
26
28
|
import type { CommandOptions, Skips, Totals } from '../types';
|
|
27
|
-
import {
|
|
28
|
-
import { Arguments } from 'yargs';
|
|
29
|
+
import type { CommandArgs } from '../wrapper';
|
|
29
30
|
|
|
30
31
|
export type LintOptions = {
|
|
31
32
|
apis?: string[];
|
|
@@ -37,7 +38,12 @@ export type LintOptions = {
|
|
|
37
38
|
'lint-config'?: RuleSeverity;
|
|
38
39
|
} & Omit<Skips, 'skip-decorator'>;
|
|
39
40
|
|
|
40
|
-
export async function handleLint(
|
|
41
|
+
export async function handleLint({
|
|
42
|
+
argv,
|
|
43
|
+
config,
|
|
44
|
+
version,
|
|
45
|
+
collectSpecData,
|
|
46
|
+
}: CommandArgs<LintOptions>) {
|
|
41
47
|
const apis = await getFallbackApisOrExit(argv.apis, config);
|
|
42
48
|
|
|
43
49
|
if (!apis.length) {
|
|
@@ -73,6 +79,7 @@ export async function handleLint(argv: LintOptions, config: Config, version: str
|
|
|
73
79
|
const results = await lint({
|
|
74
80
|
ref: path,
|
|
75
81
|
config: resolvedConfig,
|
|
82
|
+
collectSpecData,
|
|
76
83
|
});
|
|
77
84
|
|
|
78
85
|
const fileTotals = getTotals(results);
|
|
@@ -130,7 +137,13 @@ export function lintConfigCallback(
|
|
|
130
137
|
return;
|
|
131
138
|
}
|
|
132
139
|
|
|
133
|
-
return async ({ document, resolvedRefMap, config }) => {
|
|
140
|
+
return async ({ document, resolvedRefMap, config, parsed: { theme = {} } }) => {
|
|
141
|
+
const command = argv ? getCommandNameFromArgs(argv as Arguments) : undefined;
|
|
142
|
+
|
|
143
|
+
if (command === 'check-config') {
|
|
144
|
+
notifyAboutIncompatibleConfigOptions(theme.openapi);
|
|
145
|
+
}
|
|
146
|
+
|
|
134
147
|
const problems = await lintConfig({
|
|
135
148
|
document,
|
|
136
149
|
resolvedRefMap,
|
|
@@ -147,8 +160,6 @@ export function lintConfigCallback(
|
|
|
147
160
|
version,
|
|
148
161
|
});
|
|
149
162
|
|
|
150
|
-
const command = argv ? getCommandNameFromArgs(argv as unknown as Arguments) : undefined;
|
|
151
|
-
|
|
152
163
|
printConfigLintTotals(fileTotals, command);
|
|
153
164
|
|
|
154
165
|
if (fileTotals.errors > 0) {
|
package/src/commands/login.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import { Region, RedoclyClient
|
|
1
|
+
import { Region, RedoclyClient } from '@redocly/openapi-core';
|
|
2
2
|
import { blue, green, gray } from 'colorette';
|
|
3
3
|
import { promptUser } from '../utils/miscellaneous';
|
|
4
4
|
|
|
5
|
+
import type { CommandArgs } from '../wrapper';
|
|
6
|
+
|
|
5
7
|
export function promptClientToken(domain: string) {
|
|
6
8
|
return promptUser(
|
|
7
9
|
green(
|
|
@@ -17,7 +19,7 @@ export type LoginOptions = {
|
|
|
17
19
|
config?: string;
|
|
18
20
|
};
|
|
19
21
|
|
|
20
|
-
export async function handleLogin(argv
|
|
22
|
+
export async function handleLogin({ argv, config }: CommandArgs<LoginOptions>) {
|
|
21
23
|
const region = argv.region || config.region;
|
|
22
24
|
const client = new RedoclyClient(region);
|
|
23
25
|
const clientToken = await promptClientToken(client.domain);
|
|
@@ -7,7 +7,9 @@ import {
|
|
|
7
7
|
loadConfigAndHandleErrors,
|
|
8
8
|
} from '../../utils/miscellaneous';
|
|
9
9
|
import startPreviewServer from './preview-server/preview-server';
|
|
10
|
+
|
|
10
11
|
import type { Skips } from '../../types';
|
|
12
|
+
import type { CommandArgs } from '../../wrapper';
|
|
11
13
|
|
|
12
14
|
export type PreviewDocsOptions = {
|
|
13
15
|
port: number;
|
|
@@ -18,7 +20,10 @@ export type PreviewDocsOptions = {
|
|
|
18
20
|
force?: boolean;
|
|
19
21
|
} & Omit<Skips, 'skip-rule'>;
|
|
20
22
|
|
|
21
|
-
export async function previewDocs(
|
|
23
|
+
export async function previewDocs({
|
|
24
|
+
argv,
|
|
25
|
+
config: configFromFile,
|
|
26
|
+
}: CommandArgs<PreviewDocsOptions>) {
|
|
22
27
|
let isAuthorizedWithRedocly = false;
|
|
23
28
|
let redocOptions: any = {};
|
|
24
29
|
let config = await reloadConfig(configFromFile);
|
|
@@ -4,12 +4,13 @@ import { spawn } from 'child_process';
|
|
|
4
4
|
import { PRODUCT_NAMES, PRODUCT_PACKAGES } from './constants';
|
|
5
5
|
|
|
6
6
|
import type { PreviewProjectOptions, Product } from './types';
|
|
7
|
+
import type { CommandArgs } from '../../wrapper';
|
|
7
8
|
|
|
8
|
-
export const previewProject = async (
|
|
9
|
-
const { plan, port } =
|
|
10
|
-
const projectDir =
|
|
9
|
+
export const previewProject = async ({ argv }: CommandArgs<PreviewProjectOptions>) => {
|
|
10
|
+
const { plan, port } = argv;
|
|
11
|
+
const projectDir = argv['source-dir'];
|
|
11
12
|
|
|
12
|
-
const product =
|
|
13
|
+
const product = argv.product || tryGetProductFromPackageJson(projectDir);
|
|
13
14
|
|
|
14
15
|
if (!isValidProduct(product)) {
|
|
15
16
|
process.stderr.write(`Invalid product ${product}`);
|
package/src/commands/push.ts
CHANGED
|
@@ -20,12 +20,14 @@ import {
|
|
|
20
20
|
exitWithError,
|
|
21
21
|
printExecutionTime,
|
|
22
22
|
getFallbackApisOrExit,
|
|
23
|
-
pluralize,
|
|
24
23
|
dumpBundle,
|
|
24
|
+
pluralize,
|
|
25
25
|
} from '../utils/miscellaneous';
|
|
26
26
|
import { promptClientToken } from './login';
|
|
27
27
|
import { handlePush as handleCMSPush } from '../cms/commands/push';
|
|
28
28
|
|
|
29
|
+
import type { CommandArgs } from '../wrapper';
|
|
30
|
+
|
|
29
31
|
const DEFAULT_VERSION = 'latest';
|
|
30
32
|
|
|
31
33
|
export const DESTINATION_REGEX =
|
|
@@ -59,7 +61,7 @@ export function commonPushHandler({
|
|
|
59
61
|
return transformPush(handlePush);
|
|
60
62
|
}
|
|
61
63
|
|
|
62
|
-
export async function handlePush(argv
|
|
64
|
+
export async function handlePush({ argv, config }: CommandArgs<PushOptions>): Promise<void> {
|
|
63
65
|
const client = new RedoclyClient(config.region);
|
|
64
66
|
const isAuthorized = await client.isAuthorizedWithRedoclyByRegion();
|
|
65
67
|
if (!isAuthorized) {
|
|
@@ -366,16 +368,11 @@ type BarePushArgs = Omit<PushOptions, 'destination' | 'branchName'> & {
|
|
|
366
368
|
|
|
367
369
|
export const transformPush =
|
|
368
370
|
(callback: typeof handlePush) =>
|
|
369
|
-
(
|
|
370
|
-
{
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
'job-id': jobId,
|
|
375
|
-
...rest
|
|
376
|
-
}: BarePushArgs & { 'batch-id'?: string },
|
|
377
|
-
config: Config
|
|
378
|
-
) => {
|
|
371
|
+
({
|
|
372
|
+
argv: { apis, branch, 'batch-id': batchId, 'job-id': jobId, ...rest },
|
|
373
|
+
config,
|
|
374
|
+
version,
|
|
375
|
+
}: CommandArgs<BarePushArgs & { 'batch-id'?: string }>) => {
|
|
379
376
|
const [maybeApiOrDestination, maybeDestination, maybeBranchName] = apis || [];
|
|
380
377
|
|
|
381
378
|
if (batchId) {
|
|
@@ -414,16 +411,17 @@ export const transformPush =
|
|
|
414
411
|
apiFile = maybeApiOrDestination;
|
|
415
412
|
}
|
|
416
413
|
|
|
417
|
-
return callback(
|
|
418
|
-
{
|
|
414
|
+
return callback({
|
|
415
|
+
argv: {
|
|
419
416
|
...rest,
|
|
420
417
|
destination: rest.destination ?? destination,
|
|
421
418
|
api: apiFile,
|
|
422
419
|
branchName: branch ?? maybeBranchName,
|
|
423
420
|
'job-id': jobId || batchId,
|
|
424
421
|
},
|
|
425
|
-
config
|
|
426
|
-
|
|
422
|
+
config,
|
|
423
|
+
version,
|
|
424
|
+
});
|
|
427
425
|
};
|
|
428
426
|
|
|
429
427
|
export function getApiRoot({
|
|
@@ -3,6 +3,9 @@ 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 { loadConfigAndHandleErrors } from '../../../utils/__mocks__/miscellaneous';
|
|
7
|
+
|
|
8
|
+
import type { Config } from '@redocly/openapi-core';
|
|
6
9
|
|
|
7
10
|
const utils = require('../../../utils/miscellaneous');
|
|
8
11
|
|
|
@@ -25,9 +28,13 @@ describe('#split', () => {
|
|
|
25
28
|
jest.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
26
29
|
|
|
27
30
|
await handleSplit({
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
argv: {
|
|
32
|
+
api: filePath,
|
|
33
|
+
outDir: openapiDir,
|
|
34
|
+
separator: '_',
|
|
35
|
+
},
|
|
36
|
+
config: loadConfigAndHandleErrors() as any as Config,
|
|
37
|
+
version: 'cli-version',
|
|
31
38
|
});
|
|
32
39
|
|
|
33
40
|
expect(process.stderr.write).toBeCalledTimes(2);
|
|
@@ -46,9 +53,13 @@ describe('#split', () => {
|
|
|
46
53
|
jest.spyOn(utils, 'pathToFilename').mockImplementation(() => 'newFilePath');
|
|
47
54
|
|
|
48
55
|
await handleSplit({
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
56
|
+
argv: {
|
|
57
|
+
api: filePath,
|
|
58
|
+
outDir: openapiDir,
|
|
59
|
+
separator: '_',
|
|
60
|
+
},
|
|
61
|
+
config: loadConfigAndHandleErrors() as any as Config,
|
|
62
|
+
version: 'cli-version',
|
|
52
63
|
});
|
|
53
64
|
|
|
54
65
|
expect(utils.pathToFilename).toBeCalledWith(expect.anything(), '_');
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { red, blue, yellow, green } from 'colorette';
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import { parseYaml, slash, isRef, isTruthy } from '@redocly/openapi-core';
|
|
4
|
+
import { dequal } from '@redocly/openapi-core/lib/utils';
|
|
4
5
|
import * as path from 'path';
|
|
5
6
|
import { performance } from 'perf_hooks';
|
|
6
|
-
const isEqual = require('lodash.isequal');
|
|
7
7
|
import {
|
|
8
8
|
printExecutionTime,
|
|
9
9
|
pathToFilename,
|
|
@@ -36,6 +36,7 @@ import type {
|
|
|
36
36
|
Oas3PathItem,
|
|
37
37
|
Referenced,
|
|
38
38
|
} from './types';
|
|
39
|
+
import type { CommandArgs } from '../../wrapper';
|
|
39
40
|
|
|
40
41
|
export type SplitOptions = {
|
|
41
42
|
api: string;
|
|
@@ -44,12 +45,13 @@ export type SplitOptions = {
|
|
|
44
45
|
config?: string;
|
|
45
46
|
};
|
|
46
47
|
|
|
47
|
-
export async function handleSplit(argv: SplitOptions) {
|
|
48
|
+
export async function handleSplit({ argv, collectSpecData }: CommandArgs<SplitOptions>) {
|
|
48
49
|
const startedAt = performance.now();
|
|
49
50
|
const { api, outDir, separator } = argv;
|
|
50
51
|
validateDefinitionFileName(api!);
|
|
51
52
|
const ext = getAndValidateFileExtension(api);
|
|
52
53
|
const openapi = readYaml(api!) as Oas3Definition | Oas3_1Definition;
|
|
54
|
+
collectSpecData?.(openapi);
|
|
53
55
|
splitDefinition(openapi, outDir, separator, ext);
|
|
54
56
|
process.stderr.write(
|
|
55
57
|
`🪓 Document: ${blue(api!)} ${green('is successfully split')}
|
|
@@ -232,7 +234,7 @@ function findComponentTypes(components: any) {
|
|
|
232
234
|
}
|
|
233
235
|
|
|
234
236
|
function doesFileDiffer(filename: string, componentData: any) {
|
|
235
|
-
return fs.existsSync(filename) && !
|
|
237
|
+
return fs.existsSync(filename) && !dequal(readYaml(filename), componentData);
|
|
236
238
|
}
|
|
237
239
|
|
|
238
240
|
function removeEmptyComponents(
|
|
@@ -292,7 +294,7 @@ function iteratePathItems(
|
|
|
292
294
|
|
|
293
295
|
for (const pathName of Object.keys(pathItems)) {
|
|
294
296
|
const pathFile = `${path.join(outDir, pathToFilename(pathName, pathSeparator))}.${ext}`;
|
|
295
|
-
const pathData = pathItems[pathName]
|
|
297
|
+
const pathData = pathItems[pathName];
|
|
296
298
|
|
|
297
299
|
if (isRef(pathData)) continue;
|
|
298
300
|
|
package/src/commands/stats.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { performance } from 'perf_hooks';
|
|
2
2
|
import * as colors from 'colorette';
|
|
3
3
|
import {
|
|
4
|
-
Config,
|
|
5
4
|
StyleguideConfig,
|
|
6
5
|
normalizeTypes,
|
|
7
6
|
BaseResolver,
|
|
@@ -15,7 +14,9 @@ import {
|
|
|
15
14
|
} from '@redocly/openapi-core';
|
|
16
15
|
import { getFallbackApisOrExit } from '../utils/miscellaneous';
|
|
17
16
|
import { printExecutionTime } from '../utils/miscellaneous';
|
|
17
|
+
|
|
18
18
|
import type { StatsAccumulator, StatsName, WalkContext, OutputFormat } from '@redocly/openapi-core';
|
|
19
|
+
import type { CommandArgs } from '../wrapper';
|
|
19
20
|
|
|
20
21
|
const statsAccumulator: StatsAccumulator = {
|
|
21
22
|
refs: { metric: '🚗 References', total: 0, color: 'red', items: new Set() },
|
|
@@ -86,10 +87,11 @@ export type StatsOptions = {
|
|
|
86
87
|
config?: string;
|
|
87
88
|
};
|
|
88
89
|
|
|
89
|
-
export async function handleStats(argv
|
|
90
|
+
export async function handleStats({ argv, config, collectSpecData }: CommandArgs<StatsOptions>) {
|
|
90
91
|
const [{ path }] = await getFallbackApisOrExit(argv.api ? [argv.api] : [], config);
|
|
91
92
|
const externalRefResolver = new BaseResolver(config.resolve);
|
|
92
93
|
const { bundle: document } = await bundle({ config, ref: path });
|
|
94
|
+
collectSpecData?.(document.parsed);
|
|
93
95
|
const lintConfig: StyleguideConfig = config.styleguide;
|
|
94
96
|
const specVersion = detectSpec(document.parsed);
|
|
95
97
|
const types = normalizeTypes(
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as pluralizeOne from 'pluralize';
|
|
2
2
|
import { basename, dirname, extname, join, resolve, relative, isAbsolute } from 'path';
|
|
3
3
|
import { blue, gray, green, red, yellow } from 'colorette';
|
|
4
4
|
import { performance } from 'perf_hooks';
|
|
@@ -9,36 +9,34 @@ import { Writable } from 'stream';
|
|
|
9
9
|
import { execSync } from 'child_process';
|
|
10
10
|
import { promisify } from 'util';
|
|
11
11
|
import {
|
|
12
|
-
BundleOutputFormat,
|
|
13
|
-
StyleguideConfig,
|
|
14
12
|
ResolveError,
|
|
15
13
|
YamlParseError,
|
|
16
|
-
ResolvedApi,
|
|
17
14
|
parseYaml,
|
|
18
15
|
stringifyYaml,
|
|
19
16
|
isAbsoluteUrl,
|
|
20
17
|
loadConfig,
|
|
21
|
-
Region,
|
|
22
|
-
Config,
|
|
23
|
-
Oas3Definition,
|
|
24
|
-
Oas2Definition,
|
|
25
18
|
RedoclyClient,
|
|
26
19
|
} from '@redocly/openapi-core';
|
|
27
|
-
import {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
ConfigApis,
|
|
32
|
-
CommandOptions,
|
|
33
|
-
OutputExtensions,
|
|
34
|
-
} from '../types';
|
|
35
|
-
import { isEmptyObject } from '@redocly/openapi-core/lib/utils';
|
|
36
|
-
import { Arguments } from 'yargs';
|
|
20
|
+
import { isEmptyObject, isPlainObject } from '@redocly/openapi-core/lib/utils';
|
|
21
|
+
import { ConfigValidationError } from '@redocly/openapi-core/lib/config';
|
|
22
|
+
import { deprecatedRefDocsSchema } from '@redocly/config/lib/reference-docs-config-schema';
|
|
23
|
+
import { outputExtensions } from '../types';
|
|
37
24
|
import { version } from './update-version-notifier';
|
|
38
25
|
import { DESTINATION_REGEX } from '../commands/push';
|
|
39
|
-
import
|
|
26
|
+
import fetch from './fetch-with-timeout';
|
|
40
27
|
|
|
28
|
+
import type { Arguments } from 'yargs';
|
|
29
|
+
import type {
|
|
30
|
+
BundleOutputFormat,
|
|
31
|
+
StyleguideConfig,
|
|
32
|
+
ResolvedApi,
|
|
33
|
+
Region,
|
|
34
|
+
Config,
|
|
35
|
+
Oas3Definition,
|
|
36
|
+
Oas2Definition,
|
|
37
|
+
} from '@redocly/openapi-core';
|
|
41
38
|
import type { RawConfigProcessor } from '@redocly/openapi-core/lib/config';
|
|
39
|
+
import type { Totals, Entrypoint, ConfigApis, CommandOptions, OutputExtensions } from '../types';
|
|
42
40
|
|
|
43
41
|
export async function getFallbackApisOrExit(
|
|
44
42
|
argsApis: string[] | undefined,
|
|
@@ -279,12 +277,11 @@ export function getAndValidateFileExtension(fileName: string): NonNullable<Outpu
|
|
|
279
277
|
return 'yaml';
|
|
280
278
|
}
|
|
281
279
|
|
|
282
|
-
export function pluralize(
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
return num === 1 ? `${label}` : `${label}s`;
|
|
280
|
+
export function pluralize(sentence: string, count?: number, inclusive?: boolean) {
|
|
281
|
+
return sentence
|
|
282
|
+
.split(' ')
|
|
283
|
+
.map((word) => pluralizeOne(word, count, inclusive))
|
|
284
|
+
.join(' ');
|
|
288
285
|
}
|
|
289
286
|
|
|
290
287
|
export function handleError(e: Error, ref: string) {
|
|
@@ -525,6 +522,7 @@ export function checkIfRulesetExist(rules: typeof StyleguideConfig.prototype.rul
|
|
|
525
522
|
...rules.oas3_0,
|
|
526
523
|
...rules.oas3_1,
|
|
527
524
|
...rules.async2,
|
|
525
|
+
...rules.async3,
|
|
528
526
|
...rules.arazzo,
|
|
529
527
|
};
|
|
530
528
|
|
|
@@ -543,7 +541,10 @@ export function cleanColors(input: string): string {
|
|
|
543
541
|
export async function sendTelemetry(
|
|
544
542
|
argv: Arguments | undefined,
|
|
545
543
|
exit_code: ExitCode,
|
|
546
|
-
has_config: boolean | undefined
|
|
544
|
+
has_config: boolean | undefined,
|
|
545
|
+
spec_version: string | undefined,
|
|
546
|
+
spec_keyword: string | undefined,
|
|
547
|
+
spec_full_version: string | undefined
|
|
547
548
|
): Promise<void> {
|
|
548
549
|
try {
|
|
549
550
|
if (!argv) {
|
|
@@ -571,6 +572,9 @@ export async function sendTelemetry(
|
|
|
571
572
|
environment_ci: process.env.CI,
|
|
572
573
|
raw_input: cleanRawInput(process.argv.slice(2)),
|
|
573
574
|
has_config,
|
|
575
|
+
spec_version,
|
|
576
|
+
spec_keyword,
|
|
577
|
+
spec_full_version,
|
|
574
578
|
};
|
|
575
579
|
await fetch(`https://api.redocly.com/registry/telemetry/cli`, {
|
|
576
580
|
method: 'POST',
|
|
@@ -600,6 +604,9 @@ export type Analytics = {
|
|
|
600
604
|
environment_ci?: string;
|
|
601
605
|
raw_input: string;
|
|
602
606
|
has_config?: boolean;
|
|
607
|
+
spec_version?: string;
|
|
608
|
+
spec_keyword?: string;
|
|
609
|
+
spec_full_version?: string;
|
|
603
610
|
};
|
|
604
611
|
|
|
605
612
|
function isFile(value: string) {
|
|
@@ -664,3 +671,25 @@ export function checkForDeprecatedOptions<T>(argv: T, deprecatedOptions: Array<k
|
|
|
664
671
|
}
|
|
665
672
|
}
|
|
666
673
|
}
|
|
674
|
+
|
|
675
|
+
export function notifyAboutIncompatibleConfigOptions(
|
|
676
|
+
themeOpenapiOptions: Record<string, unknown> | undefined
|
|
677
|
+
) {
|
|
678
|
+
if (isPlainObject(themeOpenapiOptions)) {
|
|
679
|
+
const propertiesSet = Object.keys(themeOpenapiOptions);
|
|
680
|
+
const deprecatedSet = Object.keys(deprecatedRefDocsSchema.properties);
|
|
681
|
+
const intersection = propertiesSet.filter((prop) => deprecatedSet.includes(prop));
|
|
682
|
+
if (intersection.length > 0) {
|
|
683
|
+
process.stderr.write(
|
|
684
|
+
yellow(
|
|
685
|
+
`\n${pluralize('Property', intersection.length)} ${gray(
|
|
686
|
+
intersection.map((prop) => `'${prop}'`).join(', ')
|
|
687
|
+
)} ${pluralize(
|
|
688
|
+
'is',
|
|
689
|
+
intersection.length
|
|
690
|
+
)} only used in API Reference Docs and Redoc version 2.x or earlier.\n\n`
|
|
691
|
+
)
|
|
692
|
+
);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
}
|
package/src/wrapper.ts
CHANGED
|
@@ -1,22 +1,48 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { detectSpec, doesYamlFileExist } from '@redocly/openapi-core';
|
|
2
|
+
import { isPlainObject } from '@redocly/openapi-core/lib/utils';
|
|
3
3
|
import { version } from './utils/update-version-notifier';
|
|
4
|
-
import {
|
|
5
|
-
ExitCode,
|
|
6
|
-
exitWithError,
|
|
7
|
-
loadConfigAndHandleErrors,
|
|
8
|
-
sendTelemetry,
|
|
9
|
-
} from './utils/miscellaneous';
|
|
4
|
+
import { exitWithError, loadConfigAndHandleErrors, sendTelemetry } from './utils/miscellaneous';
|
|
10
5
|
import { lintConfigCallback } from './commands/lint';
|
|
6
|
+
|
|
7
|
+
import type { Arguments } from 'yargs';
|
|
8
|
+
import type { Config, Region } from '@redocly/openapi-core';
|
|
9
|
+
import type { CollectFn } from '@redocly/openapi-core/lib/utils';
|
|
10
|
+
import type { ExitCode } from './utils/miscellaneous';
|
|
11
11
|
import type { CommandOptions } from './types';
|
|
12
12
|
|
|
13
|
+
export type CommandArgs<T extends CommandOptions> = {
|
|
14
|
+
argv: T;
|
|
15
|
+
config: Config;
|
|
16
|
+
version: string;
|
|
17
|
+
collectSpecData?: CollectFn;
|
|
18
|
+
};
|
|
19
|
+
|
|
13
20
|
export function commandWrapper<T extends CommandOptions>(
|
|
14
|
-
commandHandler?: (
|
|
21
|
+
commandHandler?: (wrapperArgs: CommandArgs<T>) => Promise<unknown>
|
|
15
22
|
) {
|
|
16
23
|
return async (argv: Arguments<T>) => {
|
|
17
24
|
let code: ExitCode = 2;
|
|
18
25
|
let hasConfig;
|
|
19
26
|
let telemetry;
|
|
27
|
+
let specVersion: string | undefined;
|
|
28
|
+
let specKeyword: string | undefined;
|
|
29
|
+
let specFullVersion: string | undefined;
|
|
30
|
+
const collectSpecData: CollectFn = (document) => {
|
|
31
|
+
specVersion = detectSpec(document);
|
|
32
|
+
if (!isPlainObject(document)) return;
|
|
33
|
+
specKeyword = document?.openapi
|
|
34
|
+
? 'openapi'
|
|
35
|
+
: document?.swagger
|
|
36
|
+
? 'swagger'
|
|
37
|
+
: document?.asyncapi
|
|
38
|
+
? 'asyncapi'
|
|
39
|
+
: document?.arazzo
|
|
40
|
+
? 'arazzo'
|
|
41
|
+
: undefined;
|
|
42
|
+
if (specKeyword) {
|
|
43
|
+
specFullVersion = document[specKeyword] as string;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
20
46
|
try {
|
|
21
47
|
if (argv.config && !doesYamlFileExist(argv.config)) {
|
|
22
48
|
exitWithError('Please provide a valid path to the configuration file.');
|
|
@@ -32,14 +58,14 @@ export function commandWrapper<T extends CommandOptions>(
|
|
|
32
58
|
hasConfig = !config.styleguide.recommendedFallback;
|
|
33
59
|
code = 1;
|
|
34
60
|
if (typeof commandHandler === 'function') {
|
|
35
|
-
await commandHandler(argv, config, version);
|
|
61
|
+
await commandHandler({ argv, config, version, collectSpecData });
|
|
36
62
|
}
|
|
37
63
|
code = 0;
|
|
38
64
|
} catch (err) {
|
|
39
65
|
// Do nothing
|
|
40
66
|
} finally {
|
|
41
67
|
if (process.env.REDOCLY_TELEMETRY !== 'off' && telemetry !== 'off') {
|
|
42
|
-
await sendTelemetry(argv, code, hasConfig);
|
|
68
|
+
await sendTelemetry(argv, code, hasConfig, specVersion, specKeyword, specFullVersion);
|
|
43
69
|
}
|
|
44
70
|
process.once('beforeExit', () => {
|
|
45
71
|
process.exit(code);
|