@redocly/cli 1.18.1 → 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 +11 -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 -74
- 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 +375 -388
- package/lib/commands/lint.d.ts +2 -2
- package/lib/commands/lint.js +64 -75
- 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 +20 -33
- 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 +4 -1
- package/lib/utils/miscellaneous.js +130 -152
- 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 +3 -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 +12 -9
- package/src/commands/build-docs/index.ts +10 -5
- package/src/commands/bundle.ts +14 -6
- package/src/commands/join.ts +6 -2
- package/src/commands/lint.ts +9 -3
- 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 +13 -15
- package/src/commands/split/__tests__/index.test.ts +17 -6
- package/src/commands/split/index.ts +4 -2
- package/src/commands/stats.ts +4 -2
- package/src/utils/miscellaneous.ts +11 -1
- package/src/wrapper.ts +37 -11
- package/tsconfig.tsbuildinfo +1 -1
package/lib/commands/lint.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Config } from '@redocly/openapi-core';
|
|
2
1
|
import type { OutputFormat, RuleSeverity } from '@redocly/openapi-core';
|
|
3
2
|
import type { RawConfigProcessor } from '@redocly/openapi-core/lib/config';
|
|
4
3
|
import type { CommandOptions, Skips } from '../types';
|
|
4
|
+
import type { CommandArgs } from '../wrapper';
|
|
5
5
|
export type LintOptions = {
|
|
6
6
|
apis?: string[];
|
|
7
7
|
'max-problems': number;
|
|
@@ -11,5 +11,5 @@ export type LintOptions = {
|
|
|
11
11
|
'generate-ignore-file'?: boolean;
|
|
12
12
|
'lint-config'?: RuleSeverity;
|
|
13
13
|
} & Omit<Skips, 'skip-decorator'>;
|
|
14
|
-
export declare function handleLint(argv
|
|
14
|
+
export declare function handleLint({ argv, config, version, collectSpecData, }: CommandArgs<LintOptions>): Promise<void>;
|
|
15
15
|
export declare function lintConfigCallback(argv: CommandOptions & Record<string, undefined>, version: string): RawConfigProcessor | undefined;
|
package/lib/commands/lint.js
CHANGED
|
@@ -1,88 +1,78 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.
|
|
3
|
+
exports.handleLint = handleLint;
|
|
4
|
+
exports.lintConfigCallback = lintConfigCallback;
|
|
13
5
|
const colorette_1 = require("colorette");
|
|
14
6
|
const perf_hooks_1 = require("perf_hooks");
|
|
15
7
|
const openapi_core_1 = require("@redocly/openapi-core");
|
|
16
8
|
const config_1 = require("@redocly/openapi-core/lib/config");
|
|
17
9
|
const miscellaneous_1 = require("../utils/miscellaneous");
|
|
18
10
|
const getCommandNameFromArgs_1 = require("../utils/getCommandNameFromArgs");
|
|
19
|
-
function handleLint(argv, config, version) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
(0, openapi_core_1.formatProblems)(results, {
|
|
59
|
-
format: argv.format,
|
|
60
|
-
maxProblems: argv['max-problems'],
|
|
61
|
-
totals: fileTotals,
|
|
62
|
-
version,
|
|
63
|
-
});
|
|
11
|
+
async function handleLint({ argv, config, version, collectSpecData, }) {
|
|
12
|
+
const apis = await (0, miscellaneous_1.getFallbackApisOrExit)(argv.apis, config);
|
|
13
|
+
if (!apis.length) {
|
|
14
|
+
(0, miscellaneous_1.exitWithError)('No APIs were provided.');
|
|
15
|
+
}
|
|
16
|
+
if (argv['generate-ignore-file']) {
|
|
17
|
+
config.styleguide.ignore = {}; // clear ignore
|
|
18
|
+
}
|
|
19
|
+
const totals = { errors: 0, warnings: 0, ignored: 0 };
|
|
20
|
+
let totalIgnored = 0;
|
|
21
|
+
// TODO: use shared externalRef resolver, blocked by preprocessors now as they can mutate documents
|
|
22
|
+
for (const { path, alias } of apis) {
|
|
23
|
+
try {
|
|
24
|
+
const startedAt = perf_hooks_1.performance.now();
|
|
25
|
+
const resolvedConfig = (0, openapi_core_1.getMergedConfig)(config, alias);
|
|
26
|
+
const { styleguide } = resolvedConfig;
|
|
27
|
+
(0, miscellaneous_1.checkIfRulesetExist)(styleguide.rules);
|
|
28
|
+
styleguide.skipRules(argv['skip-rule']);
|
|
29
|
+
styleguide.skipPreprocessors(argv['skip-preprocessor']);
|
|
30
|
+
if (styleguide.recommendedFallback) {
|
|
31
|
+
process.stderr.write(`No configurations were provided -- using built in ${(0, colorette_1.blue)('recommended')} configuration by default.\n\n`);
|
|
32
|
+
}
|
|
33
|
+
process.stderr.write((0, colorette_1.gray)(`validating ${path.replace(process.cwd(), '')}...\n`));
|
|
34
|
+
const results = await (0, openapi_core_1.lint)({
|
|
35
|
+
ref: path,
|
|
36
|
+
config: resolvedConfig,
|
|
37
|
+
collectSpecData,
|
|
38
|
+
});
|
|
39
|
+
const fileTotals = (0, openapi_core_1.getTotals)(results);
|
|
40
|
+
totals.errors += fileTotals.errors;
|
|
41
|
+
totals.warnings += fileTotals.warnings;
|
|
42
|
+
totals.ignored += fileTotals.ignored;
|
|
43
|
+
if (argv['generate-ignore-file']) {
|
|
44
|
+
for (const m of results) {
|
|
45
|
+
config.styleguide.addIgnore(m);
|
|
46
|
+
totalIgnored++;
|
|
64
47
|
}
|
|
65
|
-
const elapsed = (0, miscellaneous_1.getExecutionTime)(startedAt);
|
|
66
|
-
process.stderr.write((0, colorette_1.gray)(`${path.replace(process.cwd(), '')}: validated in ${elapsed}\n\n`));
|
|
67
48
|
}
|
|
68
|
-
|
|
69
|
-
(0,
|
|
49
|
+
else {
|
|
50
|
+
(0, openapi_core_1.formatProblems)(results, {
|
|
51
|
+
format: argv.format,
|
|
52
|
+
maxProblems: argv['max-problems'],
|
|
53
|
+
totals: fileTotals,
|
|
54
|
+
version,
|
|
55
|
+
});
|
|
70
56
|
}
|
|
57
|
+
const elapsed = (0, miscellaneous_1.getExecutionTime)(startedAt);
|
|
58
|
+
process.stderr.write((0, colorette_1.gray)(`${path.replace(process.cwd(), '')}: validated in ${elapsed}\n\n`));
|
|
71
59
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
process.stderr.write(`Generated ignore file with ${totalIgnored} ${(0, miscellaneous_1.pluralize)('problem', totalIgnored)}.\n\n`);
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
(0, miscellaneous_1.printLintTotals)(totals, apis.length);
|
|
78
|
-
}
|
|
79
|
-
(0, miscellaneous_1.printUnusedWarnings)(config.styleguide);
|
|
80
|
-
if (!(totals.errors === 0 || argv['generate-ignore-file'])) {
|
|
81
|
-
throw new Error('Lint failed.');
|
|
60
|
+
catch (e) {
|
|
61
|
+
(0, miscellaneous_1.handleError)(e, path);
|
|
82
62
|
}
|
|
83
|
-
}
|
|
63
|
+
}
|
|
64
|
+
if (argv['generate-ignore-file']) {
|
|
65
|
+
config.styleguide.saveIgnore();
|
|
66
|
+
process.stderr.write(`Generated ignore file with ${totalIgnored} ${(0, miscellaneous_1.pluralize)('problem', totalIgnored)}.\n\n`);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
(0, miscellaneous_1.printLintTotals)(totals, apis.length);
|
|
70
|
+
}
|
|
71
|
+
(0, miscellaneous_1.printUnusedWarnings)(config.styleguide);
|
|
72
|
+
if (!(totals.errors === 0 || argv['generate-ignore-file'])) {
|
|
73
|
+
throw new Error('Lint failed.');
|
|
74
|
+
}
|
|
84
75
|
}
|
|
85
|
-
exports.handleLint = handleLint;
|
|
86
76
|
function lintConfigCallback(argv, version) {
|
|
87
77
|
if (argv['lint-config'] === 'off') {
|
|
88
78
|
return;
|
|
@@ -91,12 +81,12 @@ function lintConfigCallback(argv, version) {
|
|
|
91
81
|
// we can't print config lint results as it will break json output
|
|
92
82
|
return;
|
|
93
83
|
}
|
|
94
|
-
return ({ document, resolvedRefMap, config, parsed: { theme = {} } }) =>
|
|
84
|
+
return async ({ document, resolvedRefMap, config, parsed: { theme = {} } }) => {
|
|
95
85
|
const command = argv ? (0, getCommandNameFromArgs_1.getCommandNameFromArgs)(argv) : undefined;
|
|
96
86
|
if (command === 'check-config') {
|
|
97
87
|
(0, miscellaneous_1.notifyAboutIncompatibleConfigOptions)(theme.openapi);
|
|
98
88
|
}
|
|
99
|
-
const problems =
|
|
89
|
+
const problems = await (0, openapi_core_1.lintConfig)({
|
|
100
90
|
document,
|
|
101
91
|
resolvedRefMap,
|
|
102
92
|
config,
|
|
@@ -113,6 +103,5 @@ function lintConfigCallback(argv, version) {
|
|
|
113
103
|
if (fileTotals.errors > 0) {
|
|
114
104
|
throw new config_1.ConfigValidationError();
|
|
115
105
|
}
|
|
116
|
-
}
|
|
106
|
+
};
|
|
117
107
|
}
|
|
118
|
-
exports.lintConfigCallback = lintConfigCallback;
|
package/lib/commands/login.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { Region
|
|
1
|
+
import { Region } from '@redocly/openapi-core';
|
|
2
|
+
import type { CommandArgs } from '../wrapper';
|
|
2
3
|
export declare function promptClientToken(domain: string): Promise<string>;
|
|
3
4
|
export type LoginOptions = {
|
|
4
5
|
verbose?: boolean;
|
|
5
6
|
region?: Region;
|
|
6
7
|
config?: string;
|
|
7
8
|
};
|
|
8
|
-
export declare function handleLogin(argv
|
|
9
|
+
export declare function handleLogin({ argv, config }: CommandArgs<LoginOptions>): Promise<void>;
|
package/lib/commands/login.js
CHANGED
|
@@ -1,30 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.
|
|
3
|
+
exports.promptClientToken = promptClientToken;
|
|
4
|
+
exports.handleLogin = handleLogin;
|
|
13
5
|
const openapi_core_1 = require("@redocly/openapi-core");
|
|
14
6
|
const colorette_1 = require("colorette");
|
|
15
7
|
const miscellaneous_1 = require("../utils/miscellaneous");
|
|
16
8
|
function promptClientToken(domain) {
|
|
17
9
|
return (0, miscellaneous_1.promptUser)((0, colorette_1.green)(`\n 🔑 Copy your API key from ${(0, colorette_1.blue)(`https://app.${domain}/profile`)} and paste it below`), true);
|
|
18
10
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
yield client.login(clientToken, argv.verbose);
|
|
27
|
-
process.stdout.write((0, colorette_1.green)(' Authorization confirmed. ✅\n\n'));
|
|
28
|
-
});
|
|
11
|
+
async function handleLogin({ argv, config }) {
|
|
12
|
+
const region = argv.region || config.region;
|
|
13
|
+
const client = new openapi_core_1.RedoclyClient(region);
|
|
14
|
+
const clientToken = await promptClientToken(client.domain);
|
|
15
|
+
process.stdout.write((0, colorette_1.gray)('\n Logging in...\n'));
|
|
16
|
+
await client.login(clientToken, argv.verbose);
|
|
17
|
+
process.stdout.write((0, colorette_1.green)(' Authorization confirmed. ✅\n\n'));
|
|
29
18
|
}
|
|
30
|
-
exports.handleLogin = handleLogin;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Config } from '@redocly/openapi-core';
|
|
2
1
|
import type { Skips } from '../../types';
|
|
2
|
+
import type { CommandArgs } from '../../wrapper';
|
|
3
3
|
export type PreviewDocsOptions = {
|
|
4
4
|
port: number;
|
|
5
5
|
host: string;
|
|
@@ -8,5 +8,5 @@ export type PreviewDocsOptions = {
|
|
|
8
8
|
api?: string;
|
|
9
9
|
force?: boolean;
|
|
10
10
|
} & Omit<Skips, 'skip-rule'>;
|
|
11
|
-
export declare function previewDocs(argv:
|
|
11
|
+
export declare function previewDocs({ argv, config: configFromFile, }: CommandArgs<PreviewDocsOptions>): Promise<void>;
|
|
12
12
|
export declare function debounce(func: Function, wait: number, immediate?: boolean): (...args: any[]) => void;
|
|
@@ -1,122 +1,109 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.
|
|
3
|
+
exports.previewDocs = previewDocs;
|
|
4
|
+
exports.debounce = debounce;
|
|
13
5
|
const colorette = require("colorette");
|
|
14
6
|
const chockidar = require("chokidar");
|
|
15
7
|
const openapi_core_1 = require("@redocly/openapi-core");
|
|
16
8
|
const miscellaneous_1 = require("../../utils/miscellaneous");
|
|
17
9
|
const preview_server_1 = require("./preview-server/preview-server");
|
|
18
|
-
function previewDocs(argv, configFromFile) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
10
|
+
async function previewDocs({ argv, config: configFromFile, }) {
|
|
11
|
+
let isAuthorizedWithRedocly = false;
|
|
12
|
+
let redocOptions = {};
|
|
13
|
+
let config = await reloadConfig(configFromFile);
|
|
14
|
+
const apis = await (0, miscellaneous_1.getFallbackApisOrExit)(argv.api ? [argv.api] : [], config);
|
|
15
|
+
const api = apis[0];
|
|
16
|
+
let cachedBundle;
|
|
17
|
+
const deps = new Set();
|
|
18
|
+
async function getBundle() {
|
|
19
|
+
return cachedBundle;
|
|
20
|
+
}
|
|
21
|
+
async function updateBundle() {
|
|
22
|
+
process.stdout.write('\nBundling...\n\n');
|
|
23
|
+
try {
|
|
24
|
+
const { bundle: openapiBundle, problems, fileDependencies, } = await (0, openapi_core_1.bundle)({
|
|
25
|
+
ref: api.path,
|
|
26
|
+
config,
|
|
30
27
|
});
|
|
28
|
+
const removed = [...deps].filter((x) => !fileDependencies.has(x));
|
|
29
|
+
watcher.unwatch(removed);
|
|
30
|
+
watcher.add([...fileDependencies]);
|
|
31
|
+
deps.clear();
|
|
32
|
+
fileDependencies.forEach(deps.add, deps);
|
|
33
|
+
const fileTotals = (0, openapi_core_1.getTotals)(problems);
|
|
34
|
+
if (fileTotals.errors === 0) {
|
|
35
|
+
process.stdout.write(fileTotals.errors === 0
|
|
36
|
+
? `Created a bundle for ${api.alias || api.path} ${fileTotals.warnings > 0 ? 'with warnings' : 'successfully'}\n`
|
|
37
|
+
: colorette.yellow(`Created a bundle for ${api.alias || api.path} with errors. Docs may be broken or not accurate\n`));
|
|
38
|
+
}
|
|
39
|
+
return openapiBundle.parsed;
|
|
31
40
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
process.stdout.write('\nBundling...\n\n');
|
|
35
|
-
try {
|
|
36
|
-
const { bundle: openapiBundle, problems, fileDependencies, } = yield (0, openapi_core_1.bundle)({
|
|
37
|
-
ref: api.path,
|
|
38
|
-
config,
|
|
39
|
-
});
|
|
40
|
-
const removed = [...deps].filter((x) => !fileDependencies.has(x));
|
|
41
|
-
watcher.unwatch(removed);
|
|
42
|
-
watcher.add([...fileDependencies]);
|
|
43
|
-
deps.clear();
|
|
44
|
-
fileDependencies.forEach(deps.add, deps);
|
|
45
|
-
const fileTotals = (0, openapi_core_1.getTotals)(problems);
|
|
46
|
-
if (fileTotals.errors === 0) {
|
|
47
|
-
process.stdout.write(fileTotals.errors === 0
|
|
48
|
-
? `Created a bundle for ${api.alias || api.path} ${fileTotals.warnings > 0 ? 'with warnings' : 'successfully'}\n`
|
|
49
|
-
: colorette.yellow(`Created a bundle for ${api.alias || api.path} with errors. Docs may be broken or not accurate\n`));
|
|
50
|
-
}
|
|
51
|
-
return openapiBundle.parsed;
|
|
52
|
-
}
|
|
53
|
-
catch (e) {
|
|
54
|
-
(0, miscellaneous_1.handleError)(e, api.path);
|
|
55
|
-
}
|
|
56
|
-
});
|
|
41
|
+
catch (e) {
|
|
42
|
+
(0, miscellaneous_1.handleError)(e, api.path);
|
|
57
43
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
44
|
+
}
|
|
45
|
+
setImmediate(() => {
|
|
46
|
+
cachedBundle = updateBundle();
|
|
47
|
+
}); // initial cache
|
|
48
|
+
const isAuthorized = isAuthorizedWithRedocly || redocOptions.licenseKey;
|
|
49
|
+
if (!isAuthorized) {
|
|
50
|
+
process.stderr.write(`Using Redoc community edition.\nLogin with redocly ${colorette.blue('login')} or use an enterprise license key to preview with the premium docs.\n\n`);
|
|
51
|
+
}
|
|
52
|
+
const hotClients = await (0, preview_server_1.default)(argv.port, argv.host, {
|
|
53
|
+
getBundle,
|
|
54
|
+
getOptions: () => redocOptions,
|
|
55
|
+
useRedocPro: isAuthorized && !redocOptions.useCommunityEdition,
|
|
56
|
+
});
|
|
57
|
+
const watchPaths = [api.path, config.configFile].filter((e) => !!e);
|
|
58
|
+
const watcher = chockidar.watch(watchPaths, {
|
|
59
|
+
disableGlobbing: true,
|
|
60
|
+
ignoreInitial: true,
|
|
61
|
+
});
|
|
62
|
+
const debouncedUpdatedBundle = debounce(async () => {
|
|
63
|
+
cachedBundle = updateBundle();
|
|
64
|
+
await cachedBundle;
|
|
65
|
+
hotClients.broadcast('{"type": "reload", "bundle": true}');
|
|
66
|
+
}, 2000);
|
|
67
|
+
const changeHandler = async (type, file) => {
|
|
68
|
+
process.stdout.write(`${colorette.green('watch')} ${type} ${colorette.blue(file)}\n`);
|
|
69
|
+
if (file === config.configFile) {
|
|
70
|
+
config = await reloadConfig();
|
|
71
|
+
hotClients.broadcast(JSON.stringify({ type: 'reload' }));
|
|
72
|
+
return;
|
|
64
73
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
const changeHandler = (type, file) => __awaiter(this, void 0, void 0, function* () {
|
|
81
|
-
process.stdout.write(`${colorette.green('watch')} ${type} ${colorette.blue(file)}\n`);
|
|
82
|
-
if (file === config.configFile) {
|
|
83
|
-
config = yield reloadConfig();
|
|
84
|
-
hotClients.broadcast(JSON.stringify({ type: 'reload' }));
|
|
85
|
-
return;
|
|
74
|
+
debouncedUpdatedBundle();
|
|
75
|
+
};
|
|
76
|
+
watcher.on('change', changeHandler.bind(undefined, 'changed'));
|
|
77
|
+
watcher.on('add', changeHandler.bind(undefined, 'added'));
|
|
78
|
+
watcher.on('unlink', changeHandler.bind(undefined, 'removed'));
|
|
79
|
+
watcher.on('ready', () => {
|
|
80
|
+
process.stdout.write(`\n 👀 Watching ${colorette.blue(api.path)} and all related resources for changes\n\n`);
|
|
81
|
+
});
|
|
82
|
+
async function reloadConfig(config) {
|
|
83
|
+
if (!config) {
|
|
84
|
+
try {
|
|
85
|
+
config = (await (0, miscellaneous_1.loadConfigAndHandleErrors)({ configPath: argv.config }));
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
config = new openapi_core_1.Config({ apis: {}, styleguide: {} });
|
|
86
89
|
}
|
|
87
|
-
debouncedUpdatedBundle();
|
|
88
|
-
});
|
|
89
|
-
watcher.on('change', changeHandler.bind(undefined, 'changed'));
|
|
90
|
-
watcher.on('add', changeHandler.bind(undefined, 'added'));
|
|
91
|
-
watcher.on('unlink', changeHandler.bind(undefined, 'removed'));
|
|
92
|
-
watcher.on('ready', () => {
|
|
93
|
-
process.stdout.write(`\n 👀 Watching ${colorette.blue(api.path)} and all related resources for changes\n\n`);
|
|
94
|
-
});
|
|
95
|
-
function reloadConfig(config) {
|
|
96
|
-
var _a;
|
|
97
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
98
|
-
if (!config) {
|
|
99
|
-
try {
|
|
100
|
-
config = (yield (0, miscellaneous_1.loadConfigAndHandleErrors)({ configPath: argv.config }));
|
|
101
|
-
}
|
|
102
|
-
catch (err) {
|
|
103
|
-
config = new openapi_core_1.Config({ apis: {}, styleguide: {} });
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
const redoclyClient = new openapi_core_1.RedoclyClient();
|
|
107
|
-
isAuthorizedWithRedocly = yield redoclyClient.isAuthorizedWithRedocly();
|
|
108
|
-
const resolvedConfig = (0, openapi_core_1.getMergedConfig)(config, argv.api);
|
|
109
|
-
const { styleguide } = resolvedConfig;
|
|
110
|
-
styleguide.skipPreprocessors(argv['skip-preprocessor']);
|
|
111
|
-
styleguide.skipDecorators(argv['skip-decorator']);
|
|
112
|
-
const referenceDocs = (_a = resolvedConfig.theme) === null || _a === void 0 ? void 0 : _a.openapi;
|
|
113
|
-
redocOptions = Object.assign(Object.assign({}, referenceDocs), { useCommunityEdition: argv['use-community-edition'] || (referenceDocs === null || referenceDocs === void 0 ? void 0 : referenceDocs.useCommunityEdition), licenseKey: process.env.REDOCLY_LICENSE_KEY || (referenceDocs === null || referenceDocs === void 0 ? void 0 : referenceDocs.licenseKey), whiteLabel: true });
|
|
114
|
-
return resolvedConfig;
|
|
115
|
-
});
|
|
116
90
|
}
|
|
117
|
-
|
|
91
|
+
const redoclyClient = new openapi_core_1.RedoclyClient();
|
|
92
|
+
isAuthorizedWithRedocly = await redoclyClient.isAuthorizedWithRedocly();
|
|
93
|
+
const resolvedConfig = (0, openapi_core_1.getMergedConfig)(config, argv.api);
|
|
94
|
+
const { styleguide } = resolvedConfig;
|
|
95
|
+
styleguide.skipPreprocessors(argv['skip-preprocessor']);
|
|
96
|
+
styleguide.skipDecorators(argv['skip-decorator']);
|
|
97
|
+
const referenceDocs = resolvedConfig.theme?.openapi;
|
|
98
|
+
redocOptions = {
|
|
99
|
+
...referenceDocs,
|
|
100
|
+
useCommunityEdition: argv['use-community-edition'] || referenceDocs?.useCommunityEdition,
|
|
101
|
+
licenseKey: process.env.REDOCLY_LICENSE_KEY || referenceDocs?.licenseKey,
|
|
102
|
+
whiteLabel: true,
|
|
103
|
+
};
|
|
104
|
+
return resolvedConfig;
|
|
105
|
+
}
|
|
118
106
|
}
|
|
119
|
-
exports.previewDocs = previewDocs;
|
|
120
107
|
function debounce(func, wait, immediate) {
|
|
121
108
|
let timeout;
|
|
122
109
|
return function executedFunction(...args) {
|
|
@@ -137,4 +124,3 @@ function debounce(func, wait, immediate) {
|
|
|
137
124
|
func.apply(context, args);
|
|
138
125
|
};
|
|
139
126
|
}
|
|
140
|
-
exports.debounce = debounce;
|
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = startPreviewServer;
|
|
12
4
|
const handlebars_1 = require("handlebars");
|
|
13
5
|
const colorette = require("colorette");
|
|
14
6
|
const get_port_please_1 = require("get-port-please");
|
|
@@ -47,79 +39,75 @@ function getPageHTML(htmlTemplate, redocOptions = {}, useRedocPro, wsPort, host)
|
|
|
47
39
|
</script>`,
|
|
48
40
|
});
|
|
49
41
|
}
|
|
50
|
-
function startPreviewServer(port, host, { getBundle, getOptions, useRedocPro, }) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
42
|
+
async function startPreviewServer(port, host, { getBundle, getOptions, useRedocPro, }) {
|
|
43
|
+
const defaultTemplate = path.join(__dirname, 'default.hbs');
|
|
44
|
+
const handler = async (request, response) => {
|
|
45
|
+
console.time(colorette.dim(`GET ${request.url}`));
|
|
46
|
+
const { htmlTemplate } = getOptions() || {};
|
|
47
|
+
if (request.url?.endsWith('/') || path.extname(request.url) === '') {
|
|
48
|
+
(0, server_1.respondWithGzip)(getPageHTML(htmlTemplate || defaultTemplate, getOptions(), useRedocPro, wsPort, host), request, response, {
|
|
49
|
+
'Content-Type': 'text/html',
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
else if (request.url === '/openapi.json') {
|
|
53
|
+
const bundle = await getBundle();
|
|
54
|
+
if (bundle === undefined) {
|
|
55
|
+
(0, server_1.respondWithGzip)(JSON.stringify({
|
|
56
|
+
openapi: '3.0.0',
|
|
57
|
+
info: {
|
|
58
|
+
description: '<code> Failed to generate bundle: check out console output for more details </code>',
|
|
59
|
+
},
|
|
60
|
+
paths: {},
|
|
61
|
+
}), request, response, {
|
|
62
|
+
'Content-Type': 'application/json',
|
|
60
63
|
});
|
|
61
64
|
}
|
|
62
|
-
else if (request.url === '/openapi.json') {
|
|
63
|
-
const bundle = yield getBundle();
|
|
64
|
-
if (bundle === undefined) {
|
|
65
|
-
(0, server_1.respondWithGzip)(JSON.stringify({
|
|
66
|
-
openapi: '3.0.0',
|
|
67
|
-
info: {
|
|
68
|
-
description: '<code> Failed to generate bundle: check out console output for more details </code>',
|
|
69
|
-
},
|
|
70
|
-
paths: {},
|
|
71
|
-
}), request, response, {
|
|
72
|
-
'Content-Type': 'application/json',
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
(0, server_1.respondWithGzip)(JSON.stringify(bundle), request, response, {
|
|
77
|
-
'Content-Type': 'application/json',
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
65
|
else {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
66
|
+
(0, server_1.respondWithGzip)(JSON.stringify(bundle), request, response, {
|
|
67
|
+
'Content-Type': 'application/json',
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
let filePath =
|
|
73
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
74
|
+
// @ts-ignore
|
|
75
|
+
{
|
|
76
|
+
'/hot.js': path.join(__dirname, 'hot.js'),
|
|
77
|
+
'/oauth2-redirect.html': path.join(__dirname, 'oauth2-redirect.html'),
|
|
78
|
+
'/simplewebsocket.min.js': require.resolve('simple-websocket/simplewebsocket.min.js'),
|
|
79
|
+
}[request.url || ''];
|
|
80
|
+
if (!filePath) {
|
|
81
|
+
const basePath = htmlTemplate ? path.dirname(htmlTemplate) : process.cwd();
|
|
82
|
+
filePath = path.resolve(basePath, `.${request.url}`);
|
|
83
|
+
if (!(0, miscellaneous_1.isSubdir)(basePath, filePath)) {
|
|
84
|
+
(0, server_1.respondWithGzip)('404 Not Found', request, response, { 'Content-Type': 'text/html' }, 404);
|
|
85
|
+
console.timeEnd(colorette.dim(`GET ${request.url}`));
|
|
86
|
+
return;
|
|
98
87
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
88
|
+
}
|
|
89
|
+
const extname = String(path.extname(filePath)).toLowerCase();
|
|
90
|
+
const contentType = server_1.mimeTypes[extname] || 'application/octet-stream';
|
|
91
|
+
try {
|
|
92
|
+
(0, server_1.respondWithGzip)(await fs_1.promises.readFile(filePath), request, response, {
|
|
93
|
+
'Content-Type': contentType,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
catch (e) {
|
|
97
|
+
if (e.code === 'ENOENT') {
|
|
98
|
+
(0, server_1.respondWithGzip)('404 Not Found', request, response, { 'Content-Type': 'text/html' }, 404);
|
|
105
99
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
(0, server_1.respondWithGzip)('404 Not Found', request, response, { 'Content-Type': 'text/html' }, 404);
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
(0, server_1.respondWithGzip)(`Something went wrong: ${e.code || e.message}...\n`, request, response, {}, 500);
|
|
112
|
-
}
|
|
100
|
+
else {
|
|
101
|
+
(0, server_1.respondWithGzip)(`Something went wrong: ${e.code || e.message}...\n`, request, response, {}, 500);
|
|
113
102
|
}
|
|
114
103
|
}
|
|
115
|
-
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
});
|
|
122
|
-
return (0, server_1.startWsServer)(wsPort, host);
|
|
104
|
+
}
|
|
105
|
+
console.timeEnd(colorette.dim(`GET ${request.url}`));
|
|
106
|
+
};
|
|
107
|
+
const wsPort = await (0, get_port_please_1.getPort)({ port: 32201, portRange: [32201, 32301], host });
|
|
108
|
+
const server = (0, server_1.startHttpServer)(port, host, handler);
|
|
109
|
+
server.on('listening', () => {
|
|
110
|
+
process.stdout.write(`\n 🔎 Preview server running at ${colorette.blue(`http://${host}:${port}\n`)}`);
|
|
123
111
|
});
|
|
112
|
+
return (0, server_1.startWsServer)(wsPort, host);
|
|
124
113
|
}
|
|
125
|
-
exports.default = startPreviewServer;
|