@redocly/cli 1.0.0-beta.105 → 1.0.0-beta.106
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/bin/cli.js +1 -1
- package/lib/__mocks__/@redocly/openapi-core.d.ts +1 -1
- package/lib/__mocks__/perf_hooks.js +1 -1
- package/lib/__mocks__/utils.d.ts +1 -1
- package/lib/__mocks__/utils.js +2 -2
- package/lib/__tests__/commands/bundle.test.js +52 -17
- package/lib/__tests__/commands/join.test.js +4 -4
- package/lib/__tests__/commands/lint.test.js +6 -6
- package/lib/__tests__/commands/push-region.test.js +2 -2
- package/lib/__tests__/commands/push.test.js +18 -18
- package/lib/__tests__/fixtures/config.d.ts +1 -1
- package/lib/__tests__/fixtures/config.js +1 -1
- package/lib/commands/bundle.d.ts +4 -12
- package/lib/commands/bundle.js +12 -11
- package/lib/commands/join.d.ts +1 -1
- package/lib/commands/join.js +105 -56
- package/lib/commands/lint.d.ts +3 -9
- package/lib/commands/lint.js +11 -11
- package/lib/commands/preview-docs/index.d.ts +3 -5
- package/lib/commands/preview-docs/index.js +14 -14
- package/lib/commands/push.d.ts +6 -6
- package/lib/commands/push.js +26 -26
- package/lib/commands/split/__tests__/index.test.js +8 -8
- package/lib/commands/split/index.d.ts +1 -1
- package/lib/commands/split/index.js +12 -11
- 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 -7
- package/lib/index.js +12 -16
- package/lib/js-utils.js +2 -2
- package/lib/types.d.ts +13 -1
- package/lib/utils.d.ts +4 -4
- package/lib/utils.js +15 -17
- package/package.json +2 -2
- package/src/__mocks__/perf_hooks.ts +2 -2
- package/src/__mocks__/utils.ts +3 -1
- package/src/__tests__/commands/bundle.test.ts +71 -22
- package/src/__tests__/commands/join.test.ts +8 -8
- package/src/__tests__/commands/lint.test.ts +10 -8
- package/src/__tests__/commands/push-region.test.ts +2 -2
- package/src/__tests__/commands/push.test.ts +19 -24
- package/src/__tests__/fixtures/config.ts +1 -1
- package/src/__tests__/utils.test.ts +5 -8
- package/src/commands/bundle.ts +28 -40
- package/src/commands/join.ts +209 -119
- package/src/commands/lint.ts +25 -32
- package/src/commands/login.ts +2 -2
- package/src/commands/preview-docs/index.ts +33 -40
- package/src/commands/preview-docs/preview-server/preview-server.ts +6 -6
- package/src/commands/preview-docs/preview-server/server.ts +1 -1
- package/src/commands/push.ts +44 -53
- package/src/commands/split/__tests__/index.test.ts +47 -30
- package/src/commands/split/index.ts +84 -46
- package/src/commands/split/types.ts +19 -7
- package/src/commands/stats.ts +27 -24
- package/src/index.ts +16 -20
- package/src/js-utils.ts +2 -2
- package/src/types.ts +14 -1
- package/src/utils.ts +53 -53
- package/tsconfig.tsbuildinfo +1 -1
package/src/commands/lint.ts
CHANGED
|
@@ -6,43 +6,35 @@ import {
|
|
|
6
6
|
lintConfig,
|
|
7
7
|
findConfig,
|
|
8
8
|
getMergedConfig,
|
|
9
|
-
OutputFormat,
|
|
10
9
|
makeDocumentFromString,
|
|
11
10
|
loadConfig,
|
|
12
11
|
stringifyYaml,
|
|
13
12
|
RawConfig,
|
|
14
13
|
RuleSeverity,
|
|
15
14
|
ProblemSeverity,
|
|
16
|
-
doesYamlFileExist
|
|
15
|
+
doesYamlFileExist,
|
|
17
16
|
} from '@redocly/openapi-core';
|
|
18
17
|
import {
|
|
19
18
|
getExecutionTime,
|
|
20
|
-
|
|
19
|
+
getFallbackApisOrExit,
|
|
21
20
|
handleError,
|
|
22
21
|
pluralize,
|
|
23
22
|
printLintTotals,
|
|
24
23
|
printConfigLintTotals,
|
|
25
24
|
printUnusedWarnings,
|
|
26
|
-
exitWithError
|
|
25
|
+
exitWithError,
|
|
27
26
|
} from '../utils';
|
|
28
|
-
import { Totals } from '../types';
|
|
27
|
+
import type { CommonOptions, Skips, Totals } from '../types';
|
|
29
28
|
import { blue, gray, red } from 'colorette';
|
|
30
29
|
import { performance } from 'perf_hooks';
|
|
31
30
|
|
|
32
|
-
export type LintOptions =
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
'skip-preprocessor'?: string[];
|
|
38
|
-
'lint-config': RuleSeverity;
|
|
39
|
-
extends?: string[];
|
|
40
|
-
config?: string;
|
|
41
|
-
format: OutputFormat;
|
|
42
|
-
};
|
|
31
|
+
export type LintOptions = CommonOptions &
|
|
32
|
+
Omit<Skips, 'skip-decorator'> & {
|
|
33
|
+
'generate-ignore-file'?: boolean;
|
|
34
|
+
'lint-config': RuleSeverity;
|
|
35
|
+
};
|
|
43
36
|
|
|
44
37
|
export async function handleLint(argv: LintOptions, version: string) {
|
|
45
|
-
|
|
46
38
|
if (argv.config && !doesYamlFileExist(argv.config)) {
|
|
47
39
|
return exitWithError('Please, provide valid path to the configuration file');
|
|
48
40
|
}
|
|
@@ -53,29 +45,31 @@ export async function handleLint(argv: LintOptions, version: string) {
|
|
|
53
45
|
lintConfigCallback(argv, version)
|
|
54
46
|
);
|
|
55
47
|
|
|
56
|
-
const
|
|
48
|
+
const apis = await getFallbackApisOrExit(argv.apis, config);
|
|
57
49
|
|
|
58
50
|
if (argv['generate-ignore-file']) {
|
|
59
|
-
config.
|
|
51
|
+
config.styleguide.ignore = {}; // clear ignore
|
|
60
52
|
}
|
|
61
53
|
const totals: Totals = { errors: 0, warnings: 0, ignored: 0 };
|
|
62
54
|
let totalIgnored = 0;
|
|
63
55
|
|
|
64
56
|
// TODO: use shared externalRef resolver, blocked by preprocessors now as they can mutate documents
|
|
65
|
-
for (const { path, alias } of
|
|
57
|
+
for (const { path, alias } of apis) {
|
|
66
58
|
try {
|
|
67
59
|
const startedAt = performance.now();
|
|
68
60
|
const resolvedConfig = getMergedConfig(config, alias);
|
|
69
|
-
resolvedConfig
|
|
70
|
-
|
|
61
|
+
const { styleguide } = resolvedConfig;
|
|
62
|
+
|
|
63
|
+
styleguide.skipRules(argv['skip-rule']);
|
|
64
|
+
styleguide.skipPreprocessors(argv['skip-preprocessor']);
|
|
71
65
|
|
|
72
|
-
if (
|
|
66
|
+
if (styleguide.recommendedFallback) {
|
|
73
67
|
process.stderr.write(
|
|
74
68
|
`No configurations were defined in extends -- using built in ${blue(
|
|
75
|
-
'recommended'
|
|
69
|
+
'recommended'
|
|
76
70
|
)} configuration by default.\n${red(
|
|
77
|
-
'Warning! This default behavior is going to be deprecated soon.'
|
|
78
|
-
)}\n\n
|
|
71
|
+
'Warning! This default behavior is going to be deprecated soon.'
|
|
72
|
+
)}\n\n`
|
|
79
73
|
);
|
|
80
74
|
}
|
|
81
75
|
process.stderr.write(gray(`validating ${path.replace(process.cwd(), '')}...\n`));
|
|
@@ -91,7 +85,7 @@ export async function handleLint(argv: LintOptions, version: string) {
|
|
|
91
85
|
|
|
92
86
|
if (argv['generate-ignore-file']) {
|
|
93
87
|
for (let m of results) {
|
|
94
|
-
config.
|
|
88
|
+
config.styleguide.addIgnore(m);
|
|
95
89
|
totalIgnored++;
|
|
96
90
|
}
|
|
97
91
|
} else {
|
|
@@ -106,26 +100,25 @@ export async function handleLint(argv: LintOptions, version: string) {
|
|
|
106
100
|
const elapsed = getExecutionTime(startedAt);
|
|
107
101
|
process.stderr.write(gray(`${path.replace(process.cwd(), '')}: validated in ${elapsed}\n\n`));
|
|
108
102
|
} catch (e) {
|
|
109
|
-
totals.errors++;
|
|
110
103
|
handleError(e, path);
|
|
111
104
|
}
|
|
112
105
|
}
|
|
113
106
|
|
|
114
107
|
if (argv['generate-ignore-file']) {
|
|
115
|
-
config.
|
|
108
|
+
config.styleguide.saveIgnore();
|
|
116
109
|
process.stderr.write(
|
|
117
110
|
`Generated ignore file with ${totalIgnored} ${pluralize('problem', totalIgnored)}.\n\n`
|
|
118
111
|
);
|
|
119
112
|
} else {
|
|
120
|
-
printLintTotals(totals,
|
|
113
|
+
printLintTotals(totals, apis.length);
|
|
121
114
|
}
|
|
122
115
|
|
|
123
|
-
printUnusedWarnings(config.
|
|
116
|
+
printUnusedWarnings(config.styleguide);
|
|
124
117
|
|
|
125
118
|
// defer process exit to allow STDOUT pipe to flush
|
|
126
119
|
// see https://github.com/nodejs/node-v0.x-archive/issues/3737#issuecomment-19156072
|
|
127
120
|
process.once('exit', () =>
|
|
128
|
-
process.exit(totals.errors === 0 || argv['generate-ignore-file'] ? 0 : 1)
|
|
121
|
+
process.exit(totals.errors === 0 || argv['generate-ignore-file'] ? 0 : 1)
|
|
129
122
|
);
|
|
130
123
|
}
|
|
131
124
|
|
package/src/commands/login.ts
CHANGED
|
@@ -5,9 +5,9 @@ import { promptUser } from '../utils';
|
|
|
5
5
|
export function promptClientToken(domain: string) {
|
|
6
6
|
return promptUser(
|
|
7
7
|
green(
|
|
8
|
-
`\n 🔑 Copy your API key from ${blue(`https://app.${domain}/profile`)} and paste it below
|
|
8
|
+
`\n 🔑 Copy your API key from ${blue(`https://app.${domain}/profile`)} and paste it below`
|
|
9
9
|
),
|
|
10
|
-
true
|
|
10
|
+
true
|
|
11
11
|
);
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -9,29 +9,26 @@ import {
|
|
|
9
9
|
getTotals,
|
|
10
10
|
getMergedConfig,
|
|
11
11
|
} from '@redocly/openapi-core';
|
|
12
|
-
import {
|
|
12
|
+
import { getFallbackApisOrExit } from '../../utils';
|
|
13
13
|
import startPreviewServer from './preview-server/preview-server';
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
14
|
+
import type { Skips } from 'cli/src/types';
|
|
15
|
+
|
|
16
|
+
export async function previewDocs(
|
|
17
|
+
argv: {
|
|
18
|
+
port: number;
|
|
19
|
+
host: string;
|
|
20
|
+
'use-community-edition'?: boolean;
|
|
21
|
+
config?: string;
|
|
22
|
+
api?: string;
|
|
23
|
+
force?: boolean;
|
|
24
|
+
} & Omit<Skips, 'skip-rule'>
|
|
25
|
+
) {
|
|
26
26
|
let isAuthorizedWithRedocly: boolean = false;
|
|
27
27
|
let redocOptions: any = {};
|
|
28
28
|
let config = await reloadConfig();
|
|
29
29
|
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
config,
|
|
33
|
-
);
|
|
34
|
-
const entrypoint = entrypoints[0];
|
|
30
|
+
const apis = await getFallbackApisOrExit(argv.api ? [argv.api] : [], config);
|
|
31
|
+
const api = apis[0];
|
|
35
32
|
|
|
36
33
|
let cachedBundle: any;
|
|
37
34
|
const deps = new Set<string>();
|
|
@@ -48,7 +45,7 @@ export async function previewDocs(argv: {
|
|
|
48
45
|
problems,
|
|
49
46
|
fileDependencies,
|
|
50
47
|
} = await bundle({
|
|
51
|
-
ref:
|
|
48
|
+
ref: api.path,
|
|
52
49
|
config,
|
|
53
50
|
});
|
|
54
51
|
const removed = [...deps].filter((x) => !fileDependencies.has(x));
|
|
@@ -62,20 +59,20 @@ export async function previewDocs(argv: {
|
|
|
62
59
|
if (fileTotals.errors === 0) {
|
|
63
60
|
process.stdout.write(
|
|
64
61
|
fileTotals.errors === 0
|
|
65
|
-
? `Created a bundle for ${
|
|
62
|
+
? `Created a bundle for ${api.alias || api.path} ${
|
|
66
63
|
fileTotals.warnings > 0 ? 'with warnings' : 'successfully'
|
|
67
64
|
}\n`
|
|
68
65
|
: colorette.yellow(
|
|
69
66
|
`Created a bundle for ${
|
|
70
|
-
|
|
71
|
-
} with errors. Docs may be broken or not accurate\n
|
|
72
|
-
)
|
|
67
|
+
api.alias || api.path
|
|
68
|
+
} with errors. Docs may be broken or not accurate\n`
|
|
69
|
+
)
|
|
73
70
|
);
|
|
74
71
|
}
|
|
75
72
|
|
|
76
73
|
return openapiBundle.parsed;
|
|
77
74
|
} catch (e) {
|
|
78
|
-
handleError(e,
|
|
75
|
+
handleError(e, api.path);
|
|
79
76
|
}
|
|
80
77
|
}
|
|
81
78
|
|
|
@@ -87,8 +84,8 @@ export async function previewDocs(argv: {
|
|
|
87
84
|
if (!isAuthorized) {
|
|
88
85
|
process.stderr.write(
|
|
89
86
|
`Using Redoc community edition.\nLogin with redocly ${colorette.blue(
|
|
90
|
-
'login'
|
|
91
|
-
)} or use an enterprise license key to preview with the premium docs.\n\n
|
|
87
|
+
'login'
|
|
88
|
+
)} or use an enterprise license key to preview with the premium docs.\n\n`
|
|
92
89
|
);
|
|
93
90
|
}
|
|
94
91
|
|
|
@@ -98,7 +95,7 @@ export async function previewDocs(argv: {
|
|
|
98
95
|
useRedocPro: isAuthorized && !redocOptions.useCommunityEdition,
|
|
99
96
|
});
|
|
100
97
|
|
|
101
|
-
const watchPaths = [
|
|
98
|
+
const watchPaths = [api.path, config.configFile!].filter((e) => !!e);
|
|
102
99
|
const watcher = chockidar.watch(watchPaths, {
|
|
103
100
|
disableGlobbing: true,
|
|
104
101
|
ignoreInitial: true,
|
|
@@ -127,9 +124,7 @@ export async function previewDocs(argv: {
|
|
|
127
124
|
|
|
128
125
|
watcher.on('ready', () => {
|
|
129
126
|
process.stdout.write(
|
|
130
|
-
`\n 👀 Watching ${colorette.blue(
|
|
131
|
-
entrypoint.path,
|
|
132
|
-
)} and all related resources for changes\n\n`,
|
|
127
|
+
`\n 👀 Watching ${colorette.blue(api.path)} and all related resources for changes\n\n`
|
|
133
128
|
);
|
|
134
129
|
});
|
|
135
130
|
|
|
@@ -137,10 +132,12 @@ export async function previewDocs(argv: {
|
|
|
137
132
|
let config = await loadConfig(argv.config);
|
|
138
133
|
const redoclyClient = new RedoclyClient();
|
|
139
134
|
isAuthorizedWithRedocly = await redoclyClient.isAuthorizedWithRedocly();
|
|
140
|
-
const resolvedConfig = getMergedConfig(config, argv.
|
|
141
|
-
resolvedConfig
|
|
142
|
-
|
|
143
|
-
|
|
135
|
+
const resolvedConfig = getMergedConfig(config, argv.api);
|
|
136
|
+
const { styleguide } = resolvedConfig;
|
|
137
|
+
|
|
138
|
+
styleguide.skipPreprocessors(argv['skip-preprocessor']);
|
|
139
|
+
styleguide.skipDecorators(argv['skip-decorator']);
|
|
140
|
+
|
|
144
141
|
const referenceDocs = resolvedConfig['features.openapi'];
|
|
145
142
|
redocOptions = {
|
|
146
143
|
...referenceDocs,
|
|
@@ -175,13 +172,9 @@ export function debounce(func: Function, wait: number, immediate?: boolean) {
|
|
|
175
172
|
|
|
176
173
|
function handleError(e: Error, ref: string) {
|
|
177
174
|
if (e instanceof ResolveError) {
|
|
178
|
-
process.stderr.write(
|
|
179
|
-
`Failed to resolve entrypoint definition at ${ref}:\n\n - ${e.message}.\n\n`,
|
|
180
|
-
);
|
|
175
|
+
process.stderr.write(`Failed to resolve api definition at ${ref}:\n\n - ${e.message}.\n\n`);
|
|
181
176
|
} else if (e instanceof YamlParseError) {
|
|
182
|
-
process.stderr.write(
|
|
183
|
-
`Failed to parse entrypoint definition at ${ref}:\n\n - ${e.message}.\n\n`,
|
|
184
|
-
);
|
|
177
|
+
process.stderr.write(`Failed to parse api definition at ${ref}:\n\n - ${e.message}.\n\n`);
|
|
185
178
|
} else {
|
|
186
179
|
process.stderr.write(`Something went wrong when processing ${ref}:\n\n - ${e.message}.\n\n`);
|
|
187
180
|
}
|
|
@@ -12,7 +12,7 @@ function getPageHTML(
|
|
|
12
12
|
htmlTemplate: string,
|
|
13
13
|
redocOptions: object = {},
|
|
14
14
|
useRedocPro: boolean,
|
|
15
|
-
wsPort: number
|
|
15
|
+
wsPort: number
|
|
16
16
|
) {
|
|
17
17
|
let templateSrc = readFileSync(htmlTemplate, 'utf-8');
|
|
18
18
|
|
|
@@ -58,7 +58,7 @@ export default async function startPreviewServer(
|
|
|
58
58
|
getBundle,
|
|
59
59
|
getOptions,
|
|
60
60
|
useRedocPro,
|
|
61
|
-
}: { getBundle: Function; getOptions: Function; useRedocPro: boolean }
|
|
61
|
+
}: { getBundle: Function; getOptions: Function; useRedocPro: boolean }
|
|
62
62
|
) {
|
|
63
63
|
const defaultTemplate = path.join(__dirname, 'default.hbs');
|
|
64
64
|
const handler = async (request: IncomingMessage, response: any) => {
|
|
@@ -72,7 +72,7 @@ export default async function startPreviewServer(
|
|
|
72
72
|
response,
|
|
73
73
|
{
|
|
74
74
|
'Content-Type': 'text/html',
|
|
75
|
-
}
|
|
75
|
+
}
|
|
76
76
|
);
|
|
77
77
|
} else if (request.url === '/openapi.json') {
|
|
78
78
|
const bundle = await getBundle();
|
|
@@ -90,7 +90,7 @@ export default async function startPreviewServer(
|
|
|
90
90
|
response,
|
|
91
91
|
{
|
|
92
92
|
'Content-Type': 'application/json',
|
|
93
|
-
}
|
|
93
|
+
}
|
|
94
94
|
);
|
|
95
95
|
} else {
|
|
96
96
|
respondWithGzip(JSON.stringify(bundle), request, response, {
|
|
@@ -134,7 +134,7 @@ export default async function startPreviewServer(
|
|
|
134
134
|
request,
|
|
135
135
|
response,
|
|
136
136
|
{},
|
|
137
|
-
500
|
|
137
|
+
500
|
|
138
138
|
);
|
|
139
139
|
}
|
|
140
140
|
}
|
|
@@ -147,7 +147,7 @@ export default async function startPreviewServer(
|
|
|
147
147
|
const server = startHttpServer(port, host, handler);
|
|
148
148
|
server.on('listening', () => {
|
|
149
149
|
process.stdout.write(
|
|
150
|
-
`\n 🔎 Preview server running at ${colorette.blue(`http://${host}:${port}\n`)}
|
|
150
|
+
`\n 🔎 Preview server running at ${colorette.blue(`http://${host}:${port}\n`)}`
|
|
151
151
|
);
|
|
152
152
|
});
|
|
153
153
|
|
package/src/commands/push.ts
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
import {
|
|
20
20
|
exitWithError,
|
|
21
21
|
printExecutionTime,
|
|
22
|
-
|
|
22
|
+
getFallbackApisOrExit,
|
|
23
23
|
pluralize,
|
|
24
24
|
dumpBundle,
|
|
25
25
|
} from '../utils';
|
|
@@ -28,7 +28,7 @@ import { promptClientToken } from './login';
|
|
|
28
28
|
const DEFAULT_VERSION = 'latest';
|
|
29
29
|
|
|
30
30
|
type PushArgs = {
|
|
31
|
-
|
|
31
|
+
api?: string;
|
|
32
32
|
destination?: string;
|
|
33
33
|
branchName?: string;
|
|
34
34
|
upsert?: boolean;
|
|
@@ -36,7 +36,7 @@ type PushArgs = {
|
|
|
36
36
|
'batch-size'?: number;
|
|
37
37
|
region?: Region;
|
|
38
38
|
'skip-decorator'?: string[];
|
|
39
|
-
|
|
39
|
+
public?: boolean;
|
|
40
40
|
};
|
|
41
41
|
|
|
42
42
|
export async function handlePush(argv: PushArgs): Promise<void> {
|
|
@@ -61,8 +61,8 @@ export async function handlePush(argv: PushArgs): Promise<void> {
|
|
|
61
61
|
) {
|
|
62
62
|
exitWithError(
|
|
63
63
|
`Destination argument value is not valid, please use the right format: ${yellow(
|
|
64
|
-
'<@organization-id/api-name@api-version>'
|
|
65
|
-
)}
|
|
64
|
+
'<@organization-id/api-name@api-version>'
|
|
65
|
+
)}`
|
|
66
66
|
);
|
|
67
67
|
}
|
|
68
68
|
|
|
@@ -71,18 +71,17 @@ export async function handlePush(argv: PushArgs): Promise<void> {
|
|
|
71
71
|
if (!organizationId) {
|
|
72
72
|
return exitWithError(
|
|
73
73
|
`No organization provided, please use the right format: ${yellow(
|
|
74
|
-
'<@organization-id/api-name@api-version>'
|
|
75
|
-
)} or specify the 'organization' field in the config file
|
|
74
|
+
'<@organization-id/api-name@api-version>'
|
|
75
|
+
)} or specify the 'organization' field in the config file.`
|
|
76
76
|
);
|
|
77
77
|
}
|
|
78
|
-
const
|
|
79
|
-
argv.entrypoint || (name && version && getApiEntrypoint({ name, version, config }));
|
|
78
|
+
const api = argv.api || (name && version && getApiRoot({ name, version, config }));
|
|
80
79
|
|
|
81
|
-
if (name && version && !
|
|
80
|
+
if (name && version && !api) {
|
|
82
81
|
exitWithError(
|
|
83
|
-
`No
|
|
84
|
-
`${name}@${version}
|
|
85
|
-
)}. Please make sure you have provided the correct data in the config file
|
|
82
|
+
`No api found that matches ${blue(
|
|
83
|
+
`${name}@${version}`
|
|
84
|
+
)}. Please make sure you have provided the correct data in the config file.`
|
|
86
85
|
);
|
|
87
86
|
}
|
|
88
87
|
|
|
@@ -98,24 +97,24 @@ export async function handlePush(argv: PushArgs): Promise<void> {
|
|
|
98
97
|
);
|
|
99
98
|
}
|
|
100
99
|
|
|
101
|
-
const apis =
|
|
100
|
+
const apis = api ? { [`${name}@${version}`]: { root: api } } : config.apis;
|
|
102
101
|
|
|
103
|
-
for (const [apiNameAndVersion, { root:
|
|
102
|
+
for (const [apiNameAndVersion, { root: api }] of Object.entries(apis)) {
|
|
104
103
|
const resolvedConfig = getMergedConfig(config, apiNameAndVersion);
|
|
105
|
-
resolvedConfig.
|
|
104
|
+
resolvedConfig.styleguide.skipDecorators(argv['skip-decorator']);
|
|
106
105
|
|
|
107
106
|
const [name, version = DEFAULT_VERSION] = apiNameAndVersion.split('@');
|
|
108
107
|
try {
|
|
109
108
|
let rootFilePath = '';
|
|
110
109
|
const filePaths: string[] = [];
|
|
111
|
-
const filesToUpload = await collectFilesToUpload(
|
|
110
|
+
const filesToUpload = await collectFilesToUpload(api, resolvedConfig);
|
|
112
111
|
const filesHash = hashFiles(filesToUpload.files);
|
|
113
112
|
|
|
114
113
|
process.stdout.write(
|
|
115
114
|
`Uploading ${filesToUpload.files.length} ${pluralize(
|
|
116
115
|
'file',
|
|
117
|
-
filesToUpload.files.length
|
|
118
|
-
)}:\n
|
|
116
|
+
filesToUpload.files.length
|
|
117
|
+
)}:\n`
|
|
119
118
|
);
|
|
120
119
|
|
|
121
120
|
let uploaded = 0;
|
|
@@ -137,12 +136,12 @@ export async function handlePush(argv: PushArgs): Promise<void> {
|
|
|
137
136
|
filePaths.push(filePath);
|
|
138
137
|
|
|
139
138
|
process.stdout.write(
|
|
140
|
-
`Uploading ${file.contents ? 'bundle for ' : ''}${blue(file.filePath)}
|
|
139
|
+
`Uploading ${file.contents ? 'bundle for ' : ''}${blue(file.filePath)}...`
|
|
141
140
|
);
|
|
142
141
|
|
|
143
142
|
const uploadResponse = await uploadFileToS3(
|
|
144
143
|
signedUploadUrl,
|
|
145
|
-
file.contents || file.filePath
|
|
144
|
+
file.contents || file.filePath
|
|
146
145
|
);
|
|
147
146
|
|
|
148
147
|
const fileCounter = `(${++uploaded}/${filesToUpload.files.length})`;
|
|
@@ -175,9 +174,9 @@ export async function handlePush(argv: PushArgs): Promise<void> {
|
|
|
175
174
|
|
|
176
175
|
if (error.message === 'API_VERSION_NOT_FOUND') {
|
|
177
176
|
exitWithError(`The definition version ${blue(name)}/${blue(
|
|
178
|
-
version
|
|
177
|
+
version
|
|
179
178
|
)} does not exist in organization ${blue(organizationId)}!\n${yellow(
|
|
180
|
-
'Suggestion:'
|
|
179
|
+
'Suggestion:'
|
|
181
180
|
)} please use ${blue('-u')} or ${blue('--upsert')} to create definition.
|
|
182
181
|
`);
|
|
183
182
|
}
|
|
@@ -186,10 +185,10 @@ export async function handlePush(argv: PushArgs): Promise<void> {
|
|
|
186
185
|
}
|
|
187
186
|
|
|
188
187
|
process.stdout.write(
|
|
189
|
-
`Definition: ${blue(
|
|
188
|
+
`Definition: ${blue(api!)} is successfully pushed to Redocly API Registry \n`
|
|
190
189
|
);
|
|
191
190
|
}
|
|
192
|
-
printExecutionTime('push', startedAt,
|
|
191
|
+
printExecutionTime('push', startedAt, api || `apis in organization ${organizationId}`);
|
|
193
192
|
}
|
|
194
193
|
|
|
195
194
|
function getFilesList(dir: string, files?: any): string[] {
|
|
@@ -206,15 +205,15 @@ function getFilesList(dir: string, files?: any): string[] {
|
|
|
206
205
|
return files;
|
|
207
206
|
}
|
|
208
207
|
|
|
209
|
-
async function collectFilesToUpload(
|
|
208
|
+
async function collectFilesToUpload(api: string, config: Config) {
|
|
210
209
|
let files: { filePath: string; keyOnS3: string; contents?: Buffer }[] = [];
|
|
211
|
-
const [{ path:
|
|
210
|
+
const [{ path: apiPath }] = await getFallbackApisOrExit([api], config);
|
|
212
211
|
|
|
213
212
|
process.stdout.write('Bundling definition\n');
|
|
214
213
|
|
|
215
214
|
const { bundle: openapiBundle, problems } = await bundle({
|
|
216
215
|
config,
|
|
217
|
-
ref:
|
|
216
|
+
ref: apiPath,
|
|
218
217
|
skipRedoclyRegistryRefs: true,
|
|
219
218
|
});
|
|
220
219
|
|
|
@@ -222,17 +221,15 @@ async function collectFilesToUpload(entrypoint: string, config: Config) {
|
|
|
222
221
|
|
|
223
222
|
if (fileTotals.errors === 0) {
|
|
224
223
|
process.stdout.write(
|
|
225
|
-
`Created a bundle for ${blue(
|
|
226
|
-
fileTotals.warnings > 0 ? 'with warnings' : ''
|
|
227
|
-
}\n`,
|
|
224
|
+
`Created a bundle for ${blue(api)} ${fileTotals.warnings > 0 ? 'with warnings' : ''}\n`
|
|
228
225
|
);
|
|
229
226
|
} else {
|
|
230
|
-
exitWithError(`Failed to create a bundle for ${blue(
|
|
227
|
+
exitWithError(`Failed to create a bundle for ${blue(api)}\n`);
|
|
231
228
|
}
|
|
232
229
|
|
|
233
|
-
const fileExt = path.extname(
|
|
230
|
+
const fileExt = path.extname(apiPath).split('.').pop();
|
|
234
231
|
files.push(
|
|
235
|
-
getFileEntry(
|
|
232
|
+
getFileEntry(apiPath, dumpBundle(openapiBundle.parsed, fileExt as BundleOutputFormat))
|
|
236
233
|
);
|
|
237
234
|
|
|
238
235
|
if (fs.existsSync('package.json')) {
|
|
@@ -243,14 +240,14 @@ async function collectFilesToUpload(entrypoint: string, config: Config) {
|
|
|
243
240
|
}
|
|
244
241
|
if (config.configFile) {
|
|
245
242
|
// All config file paths including the root one
|
|
246
|
-
files.push(...[...new Set(config.
|
|
243
|
+
files.push(...[...new Set(config.styleguide.extendPaths)].map((f) => getFileEntry(f)));
|
|
247
244
|
if (config['features.openapi'].htmlTemplate) {
|
|
248
245
|
const dir = getFolder(config['features.openapi'].htmlTemplate);
|
|
249
246
|
const fileList = getFilesList(dir, []);
|
|
250
247
|
files.push(...fileList.map((f) => getFileEntry(f)));
|
|
251
248
|
}
|
|
252
249
|
let pluginFiles = new Set<string>();
|
|
253
|
-
for (const plugin of config.
|
|
250
|
+
for (const plugin of config.styleguide.pluginPaths) {
|
|
254
251
|
if (typeof plugin !== 'string') continue;
|
|
255
252
|
const fileList = getFilesList(getFolder(plugin), []);
|
|
256
253
|
fileList.forEach((f) => pluginFiles.add(f));
|
|
@@ -259,7 +256,7 @@ async function collectFilesToUpload(entrypoint: string, config: Config) {
|
|
|
259
256
|
}
|
|
260
257
|
return {
|
|
261
258
|
files,
|
|
262
|
-
root: path.resolve(
|
|
259
|
+
root: path.resolve(apiPath),
|
|
263
260
|
};
|
|
264
261
|
|
|
265
262
|
function filterPluginFilesByExt(files: string[]) {
|
|
@@ -302,7 +299,7 @@ function validateDestinationWithoutOrganization(destination: string) {
|
|
|
302
299
|
|
|
303
300
|
export function getDestinationProps(
|
|
304
301
|
destination: string | undefined,
|
|
305
|
-
organization: string | undefined
|
|
302
|
+
organization: string | undefined
|
|
306
303
|
) {
|
|
307
304
|
return destination && validateDestination(destination)
|
|
308
305
|
? destination.substring(1).split(/[@\/]/)
|
|
@@ -311,8 +308,8 @@ export function getDestinationProps(
|
|
|
311
308
|
: [organization];
|
|
312
309
|
}
|
|
313
310
|
|
|
314
|
-
type BarePushArgs = Omit<PushArgs, '
|
|
315
|
-
|
|
311
|
+
type BarePushArgs = Omit<PushArgs, 'api' | 'destination' | 'branchName'> & {
|
|
312
|
+
maybeApiOrDestination?: string;
|
|
316
313
|
maybeDestination?: string;
|
|
317
314
|
maybeBranchName?: string;
|
|
318
315
|
branch?: string;
|
|
@@ -320,31 +317,25 @@ type BarePushArgs = Omit<PushArgs, 'entrypoint' | 'destination' | 'branchName'>
|
|
|
320
317
|
|
|
321
318
|
export const transformPush =
|
|
322
319
|
(callback: typeof handlePush) =>
|
|
323
|
-
({
|
|
324
|
-
maybeEntrypointOrAliasOrDestination,
|
|
325
|
-
maybeDestination,
|
|
326
|
-
maybeBranchName,
|
|
327
|
-
branch,
|
|
328
|
-
...rest
|
|
329
|
-
}: BarePushArgs) => {
|
|
320
|
+
({ maybeApiOrDestination, maybeDestination, maybeBranchName, branch, ...rest }: BarePushArgs) => {
|
|
330
321
|
if (!!maybeBranchName) {
|
|
331
322
|
process.stderr.write(
|
|
332
323
|
yellow(
|
|
333
|
-
'Deprecation warning: Do not use the third parameter as a branch name. Please use a separate --branch option instead.'
|
|
334
|
-
)
|
|
324
|
+
'Deprecation warning: Do not use the third parameter as a branch name. Please use a separate --branch option instead.'
|
|
325
|
+
)
|
|
335
326
|
);
|
|
336
327
|
}
|
|
337
|
-
const
|
|
338
|
-
const destination = maybeDestination ||
|
|
328
|
+
const api = maybeDestination ? maybeApiOrDestination : undefined;
|
|
329
|
+
const destination = maybeDestination || maybeApiOrDestination;
|
|
339
330
|
return callback({
|
|
340
331
|
...rest,
|
|
341
332
|
destination,
|
|
342
|
-
|
|
333
|
+
api,
|
|
343
334
|
branchName: branch ?? maybeBranchName,
|
|
344
335
|
});
|
|
345
336
|
};
|
|
346
337
|
|
|
347
|
-
export function
|
|
338
|
+
export function getApiRoot({
|
|
348
339
|
name,
|
|
349
340
|
version,
|
|
350
341
|
config: { apis },
|