@redocly/cli 1.0.0-beta.100
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/README.md +39 -0
- package/bin/cli.js +3 -0
- package/lib/__mocks__/@redocly/openapi-core.d.ts +44 -0
- package/lib/__mocks__/@redocly/openapi-core.js +28 -0
- package/lib/__mocks__/fs.d.ts +7 -0
- package/lib/__mocks__/fs.js +7 -0
- package/lib/__mocks__/utils.d.ts +17 -0
- package/lib/__mocks__/utils.js +14 -0
- package/lib/__tests__/commands/bundle.test.d.ts +1 -0
- package/lib/__tests__/commands/bundle.test.js +92 -0
- package/lib/__tests__/commands/push-region.test.d.ts +1 -0
- package/lib/__tests__/commands/push-region.test.js +55 -0
- package/lib/__tests__/commands/push.test.d.ts +1 -0
- package/lib/__tests__/commands/push.test.js +155 -0
- package/lib/__tests__/utils.test.d.ts +1 -0
- package/lib/__tests__/utils.test.js +41 -0
- package/lib/assert-node-version.d.ts +1 -0
- package/lib/assert-node-version.js +10 -0
- package/lib/commands/bundle.d.ts +20 -0
- package/lib/commands/bundle.js +129 -0
- package/lib/commands/join.d.ts +7 -0
- package/lib/commands/join.js +421 -0
- package/lib/commands/lint.d.ts +11 -0
- package/lib/commands/lint.js +80 -0
- package/lib/commands/login.d.ts +6 -0
- package/lib/commands/login.js +30 -0
- package/lib/commands/preview-docs/index.d.ts +12 -0
- package/lib/commands/preview-docs/index.js +141 -0
- package/lib/commands/preview-docs/preview-server/default.hbs +24 -0
- package/lib/commands/preview-docs/preview-server/hot.js +42 -0
- package/lib/commands/preview-docs/preview-server/oauth2-redirect.html +21 -0
- package/lib/commands/preview-docs/preview-server/preview-server.d.ts +5 -0
- package/lib/commands/preview-docs/preview-server/preview-server.js +123 -0
- package/lib/commands/preview-docs/preview-server/server.d.ts +23 -0
- package/lib/commands/preview-docs/preview-server/server.js +85 -0
- package/lib/commands/push.d.ts +26 -0
- package/lib/commands/push.js +248 -0
- package/lib/commands/split/__tests__/index.test.d.ts +1 -0
- package/lib/commands/split/__tests__/index.test.js +85 -0
- package/lib/commands/split/index.d.ts +8 -0
- package/lib/commands/split/index.js +279 -0
- package/lib/commands/split/types.d.ts +37 -0
- package/lib/commands/split/types.js +52 -0
- package/lib/commands/stats.d.ts +5 -0
- package/lib/commands/stats.js +92 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +274 -0
- package/lib/js-utils.d.ts +3 -0
- package/lib/js-utils.js +16 -0
- package/lib/types.d.ts +13 -0
- package/lib/types.js +5 -0
- package/lib/utils.d.ts +29 -0
- package/lib/utils.js +267 -0
- package/package.json +53 -0
- package/src/__mocks__/@redocly/openapi-core.ts +26 -0
- package/src/__mocks__/fs.ts +4 -0
- package/src/__mocks__/utils.ts +11 -0
- package/src/__tests__/commands/bundle.test.ts +120 -0
- package/src/__tests__/commands/push-region.test.ts +51 -0
- package/src/__tests__/commands/push.test.ts +158 -0
- package/src/__tests__/utils.test.ts +50 -0
- package/src/assert-node-version.ts +8 -0
- package/src/commands/bundle.ts +180 -0
- package/src/commands/join.ts +488 -0
- package/src/commands/lint.ts +110 -0
- package/src/commands/login.ts +21 -0
- package/src/commands/preview-docs/index.ts +188 -0
- package/src/commands/preview-docs/preview-server/default.hbs +24 -0
- package/src/commands/preview-docs/preview-server/hot.js +42 -0
- package/src/commands/preview-docs/preview-server/oauth2-redirect.html +21 -0
- package/src/commands/preview-docs/preview-server/preview-server.ts +155 -0
- package/src/commands/preview-docs/preview-server/server.ts +91 -0
- package/src/commands/push.ts +357 -0
- package/src/commands/split/__tests__/fixtures/samples.json +61 -0
- package/src/commands/split/__tests__/fixtures/spec.json +70 -0
- package/src/commands/split/__tests__/fixtures/webhooks.json +88 -0
- package/src/commands/split/__tests__/index.test.ts +120 -0
- package/src/commands/split/index.ts +349 -0
- package/src/commands/split/types.ts +73 -0
- package/src/commands/stats.ts +115 -0
- package/src/index.ts +316 -0
- package/src/js-utils.ts +12 -0
- package/src/types.ts +13 -0
- package/src/utils.ts +307 -0
- package/tsconfig.json +9 -0
- package/tsconfig.tsbuildinfo +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Redocly CLI toolset
|
|
2
|
+
|
|
3
|
+
Redocly CLI toolbox with rich validation and bundling features.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
Currently, @redocly/cli supports these features:
|
|
13
|
+
|
|
14
|
+
- [x] Multifile validation. No need to bundle your file before validation.
|
|
15
|
+
- [x] Lightning-fast validation. Lint a 1 Mb file in less than one second.
|
|
16
|
+
- [x] Built-in rules for common validations.
|
|
17
|
+
- [x] Configurable severity levels for each rule.
|
|
18
|
+
- [x] Human-readable error messages with codeframes and stylish format options.
|
|
19
|
+
- [x] Intuitive suggestions for misspelled types or references.
|
|
20
|
+
- [x] Easy to implement custom rules.
|
|
21
|
+
- [x] Bundle a multifile definition into a single file.
|
|
22
|
+
- [x] Decorators to modify a validated definition during bundling.
|
|
23
|
+
- [x] Preview reference docs for local development.
|
|
24
|
+
- [x] Support for OpenAPI 2 (fka Swagger) and OpenAPI 3.0.
|
|
25
|
+
- [ ] Support for OpenAPI 3.1 ([coming soon](https://github.com/Redocly/redocly-cli/issues/160)).
|
|
26
|
+
|
|
27
|
+
## What makes this tool different
|
|
28
|
+
|
|
29
|
+
Unlike other OpenAPI linters, `@redocly/cli` defines the possible type tree of a valid OpenAPI definition and then traverses it. This approach is very similar to how linters for programming languages work and results in major performance benefits over other approaches. Extend functionality at different points in the lifecycle with preprocessors, rules, and decorators.
|
|
30
|
+
|
|
31
|
+
## TLDR
|
|
32
|
+
|
|
33
|
+
`npx @redocly/cli lint path-to-root-file.yaml`
|
|
34
|
+
|
|
35
|
+
## [Read the docs](https://redoc.ly/docs/cli/)
|
|
36
|
+
|
|
37
|
+
## Credits
|
|
38
|
+
|
|
39
|
+
Thanks to [graphql-js](https://github.com/graphql/graphql-js) and [eslint](https://github.com/eslint/eslint) for inspiration of the definition traversal approach and to [Swagger](https://github.com/swagger-api/swagger-editor), [Spectral](https://github.com/stoplightio/spectral), and [OAS-Kit](https://github.com/Mermade/oas-kit) for inspiring the ruleset.
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/// <reference types="jest" />
|
|
2
|
+
export declare const __redoclyClient: {
|
|
3
|
+
isAuthorizedWithRedocly: jest.Mock<any, any>;
|
|
4
|
+
isAuthorizedWithRedoclyByRegion: jest.Mock<any, any>;
|
|
5
|
+
login: jest.Mock<any, any>;
|
|
6
|
+
registryApi: {
|
|
7
|
+
setAccessTokens: jest.Mock<any, any>;
|
|
8
|
+
authStatus: jest.Mock<any, any>;
|
|
9
|
+
prepareFileUpload: jest.Mock<any, any>;
|
|
10
|
+
pushApi: jest.Mock<any, any>;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
export declare const RedoclyClient: jest.Mock<{
|
|
14
|
+
isAuthorizedWithRedocly: jest.Mock<any, any>;
|
|
15
|
+
isAuthorizedWithRedoclyByRegion: jest.Mock<any, any>;
|
|
16
|
+
login: jest.Mock<any, any>;
|
|
17
|
+
registryApi: {
|
|
18
|
+
setAccessTokens: jest.Mock<any, any>;
|
|
19
|
+
authStatus: jest.Mock<any, any>;
|
|
20
|
+
prepareFileUpload: jest.Mock<any, any>;
|
|
21
|
+
pushApi: jest.Mock<any, any>;
|
|
22
|
+
};
|
|
23
|
+
}, []>;
|
|
24
|
+
export declare const loadConfig: jest.Mock<{
|
|
25
|
+
configFile: null;
|
|
26
|
+
lint: {
|
|
27
|
+
skipRules: jest.Mock<any, any>;
|
|
28
|
+
skipPreprocessors: jest.Mock<any, any>;
|
|
29
|
+
skipDecorators: jest.Mock<any, any>;
|
|
30
|
+
};
|
|
31
|
+
}, []>;
|
|
32
|
+
export declare const getMergedConfig: jest.Mock<any, any>;
|
|
33
|
+
export declare const lint: jest.Mock<any, any>;
|
|
34
|
+
export declare const bundle: jest.Mock<{
|
|
35
|
+
bundle: {
|
|
36
|
+
parsed: null;
|
|
37
|
+
};
|
|
38
|
+
problems: null;
|
|
39
|
+
}, []>;
|
|
40
|
+
export declare const getTotals: jest.Mock<{
|
|
41
|
+
errors: number;
|
|
42
|
+
}, []>;
|
|
43
|
+
export declare const formatProblems: jest.Mock<any, any>;
|
|
44
|
+
export declare const slash: jest.Mock<any, any>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.slash = exports.formatProblems = exports.getTotals = exports.bundle = exports.lint = exports.getMergedConfig = exports.loadConfig = exports.RedoclyClient = exports.__redoclyClient = void 0;
|
|
4
|
+
exports.__redoclyClient = {
|
|
5
|
+
isAuthorizedWithRedocly: jest.fn().mockResolvedValue(true),
|
|
6
|
+
isAuthorizedWithRedoclyByRegion: jest.fn().mockResolvedValue(true),
|
|
7
|
+
login: jest.fn(),
|
|
8
|
+
registryApi: {
|
|
9
|
+
setAccessTokens: jest.fn(),
|
|
10
|
+
authStatus: jest.fn(),
|
|
11
|
+
prepareFileUpload: jest.fn().mockResolvedValue({
|
|
12
|
+
signedUploadUrl: 'signedUploadUrl',
|
|
13
|
+
filePath: 'filePath',
|
|
14
|
+
}),
|
|
15
|
+
pushApi: jest.fn(),
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
exports.RedoclyClient = jest.fn(() => exports.__redoclyClient);
|
|
19
|
+
exports.loadConfig = jest.fn(() => ({
|
|
20
|
+
configFile: null,
|
|
21
|
+
lint: { skipRules: jest.fn(), skipPreprocessors: jest.fn(), skipDecorators: jest.fn() },
|
|
22
|
+
}));
|
|
23
|
+
exports.getMergedConfig = jest.fn();
|
|
24
|
+
exports.lint = jest.fn();
|
|
25
|
+
exports.bundle = jest.fn(() => ({ bundle: { parsed: null }, problems: null }));
|
|
26
|
+
exports.getTotals = jest.fn(() => ({ errors: 0 }));
|
|
27
|
+
exports.formatProblems = jest.fn();
|
|
28
|
+
exports.slash = jest.fn();
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/// <reference types="jest" />
|
|
2
|
+
export declare const existsSync: jest.Mock<any, any>;
|
|
3
|
+
export declare const readFileSync: jest.Mock<string, []>;
|
|
4
|
+
export declare const statSync: jest.Mock<{
|
|
5
|
+
size: number;
|
|
6
|
+
}, []>;
|
|
7
|
+
export declare const createReadStream: jest.Mock<any, any>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createReadStream = exports.statSync = exports.readFileSync = exports.existsSync = void 0;
|
|
4
|
+
exports.existsSync = jest.fn();
|
|
5
|
+
exports.readFileSync = jest.fn(() => '');
|
|
6
|
+
exports.statSync = jest.fn(() => ({ size: 0 }));
|
|
7
|
+
exports.createReadStream = jest.fn();
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/// <reference types="jest" />
|
|
2
|
+
export declare const getFallbackEntryPointsOrExit: jest.Mock<any, [entrypoints: any]>;
|
|
3
|
+
export declare const getTotals: jest.Mock<{
|
|
4
|
+
errors: number;
|
|
5
|
+
}, []>;
|
|
6
|
+
export declare const dumpBundle: jest.Mock<string, []>;
|
|
7
|
+
export declare const slash: jest.Mock<any, any>;
|
|
8
|
+
export declare const pluralize: jest.Mock<any, any>;
|
|
9
|
+
export declare const getExecutionTime: jest.Mock<any, any>;
|
|
10
|
+
export declare const printExecutionTime: jest.Mock<any, any>;
|
|
11
|
+
export declare const printUnusedWarnings: jest.Mock<any, any>;
|
|
12
|
+
export declare const printLintTotals: jest.Mock<any, any>;
|
|
13
|
+
export declare const getOutputFileName: jest.Mock<{
|
|
14
|
+
outputFile: string;
|
|
15
|
+
ext: string;
|
|
16
|
+
}, []>;
|
|
17
|
+
export declare const handleError: jest.Mock<any, any>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleError = exports.getOutputFileName = exports.printLintTotals = exports.printUnusedWarnings = exports.printExecutionTime = exports.getExecutionTime = exports.pluralize = exports.slash = exports.dumpBundle = exports.getTotals = exports.getFallbackEntryPointsOrExit = void 0;
|
|
4
|
+
exports.getFallbackEntryPointsOrExit = jest.fn((entrypoints) => entrypoints.map(() => ({ path: '' })));
|
|
5
|
+
exports.getTotals = jest.fn(() => ({ errors: 0 }));
|
|
6
|
+
exports.dumpBundle = jest.fn(() => '');
|
|
7
|
+
exports.slash = jest.fn();
|
|
8
|
+
exports.pluralize = jest.fn();
|
|
9
|
+
exports.getExecutionTime = jest.fn();
|
|
10
|
+
exports.printExecutionTime = jest.fn();
|
|
11
|
+
exports.printUnusedWarnings = jest.fn();
|
|
12
|
+
exports.printLintTotals = jest.fn();
|
|
13
|
+
exports.getOutputFileName = jest.fn(() => ({ outputFile: 'test.yaml', ext: 'yaml' }));
|
|
14
|
+
exports.handleError = jest.fn();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,92 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const openapi_core_1 = require("@redocly/openapi-core");
|
|
13
|
+
const bundle_1 = require("../../commands/bundle");
|
|
14
|
+
jest.mock('@redocly/openapi-core');
|
|
15
|
+
jest.mock('../../utils');
|
|
16
|
+
openapi_core_1.getMergedConfig.mockImplementation(config => config);
|
|
17
|
+
describe('bundle', () => {
|
|
18
|
+
let processExitMock;
|
|
19
|
+
let exitCb;
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
processExitMock = jest.spyOn(process, 'exit').mockImplementation();
|
|
22
|
+
jest.spyOn(process, 'once').mockImplementation((_e, cb) => {
|
|
23
|
+
exitCb = cb;
|
|
24
|
+
return process.on(_e, cb);
|
|
25
|
+
});
|
|
26
|
+
jest.spyOn(process.stderr, 'write').mockImplementation(() => true);
|
|
27
|
+
});
|
|
28
|
+
afterEach(() => {
|
|
29
|
+
openapi_core_1.lint.mockClear();
|
|
30
|
+
openapi_core_1.bundle.mockClear();
|
|
31
|
+
openapi_core_1.getTotals.mockClear();
|
|
32
|
+
});
|
|
33
|
+
it('bundles definitions w/o linting', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
34
|
+
const entrypoints = ['foo.yaml', 'bar.yaml'];
|
|
35
|
+
yield bundle_1.handleBundle({
|
|
36
|
+
entrypoints,
|
|
37
|
+
ext: 'yaml',
|
|
38
|
+
format: 'codeframe',
|
|
39
|
+
}, '1.0.0');
|
|
40
|
+
expect(openapi_core_1.lint).toBeCalledTimes(0);
|
|
41
|
+
expect(openapi_core_1.bundle).toBeCalledTimes(entrypoints.length);
|
|
42
|
+
}));
|
|
43
|
+
it('exits with code 0 when bundles definitions', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
44
|
+
const entrypoints = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
|
|
45
|
+
yield bundle_1.handleBundle({
|
|
46
|
+
entrypoints,
|
|
47
|
+
ext: 'yaml',
|
|
48
|
+
format: 'codeframe',
|
|
49
|
+
}, '1.0.0');
|
|
50
|
+
exitCb === null || exitCb === void 0 ? void 0 : exitCb();
|
|
51
|
+
expect(processExitMock).toHaveBeenCalledWith(0);
|
|
52
|
+
}));
|
|
53
|
+
it('bundles definitions w/ linting', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
54
|
+
const entrypoints = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
|
|
55
|
+
yield bundle_1.handleBundle({
|
|
56
|
+
entrypoints,
|
|
57
|
+
ext: 'yaml',
|
|
58
|
+
format: 'codeframe',
|
|
59
|
+
lint: true,
|
|
60
|
+
}, '1.0.0');
|
|
61
|
+
expect(openapi_core_1.lint).toBeCalledTimes(entrypoints.length);
|
|
62
|
+
expect(openapi_core_1.bundle).toBeCalledTimes(entrypoints.length);
|
|
63
|
+
}));
|
|
64
|
+
it('exits with code 0 when bundles definitions w/linting w/o errors', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
65
|
+
const entrypoints = ['foo.yaml', 'bar.yaml', 'foobar.yaml'];
|
|
66
|
+
yield bundle_1.handleBundle({
|
|
67
|
+
entrypoints,
|
|
68
|
+
ext: 'yaml',
|
|
69
|
+
format: 'codeframe',
|
|
70
|
+
lint: true,
|
|
71
|
+
}, '1.0.0');
|
|
72
|
+
exitCb === null || exitCb === void 0 ? void 0 : exitCb();
|
|
73
|
+
expect(processExitMock).toHaveBeenCalledWith(0);
|
|
74
|
+
}));
|
|
75
|
+
it('exits with code 1 when bundles definitions w/linting w/errors', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
76
|
+
const entrypoints = ['foo.yaml'];
|
|
77
|
+
openapi_core_1.getTotals.mockReturnValue({
|
|
78
|
+
errors: 1,
|
|
79
|
+
warnings: 0,
|
|
80
|
+
ignored: 0
|
|
81
|
+
});
|
|
82
|
+
yield bundle_1.handleBundle({
|
|
83
|
+
entrypoints,
|
|
84
|
+
ext: 'yaml',
|
|
85
|
+
format: 'codeframe',
|
|
86
|
+
lint: true,
|
|
87
|
+
}, '1.0.0');
|
|
88
|
+
expect(openapi_core_1.lint).toBeCalledTimes(entrypoints.length);
|
|
89
|
+
exitCb === null || exitCb === void 0 ? void 0 : exitCb();
|
|
90
|
+
expect(processExitMock).toHaveBeenCalledWith(1);
|
|
91
|
+
}));
|
|
92
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const openapi_core_1 = require("@redocly/openapi-core");
|
|
13
|
+
const push_1 = require("../../commands/push");
|
|
14
|
+
const login_1 = require("../../commands/login");
|
|
15
|
+
jest.mock('fs');
|
|
16
|
+
jest.mock('node-fetch', () => ({
|
|
17
|
+
default: jest.fn(() => ({
|
|
18
|
+
ok: true,
|
|
19
|
+
json: jest.fn().mockResolvedValue({}),
|
|
20
|
+
})),
|
|
21
|
+
}));
|
|
22
|
+
jest.mock('@redocly/openapi-core');
|
|
23
|
+
jest.mock('../../commands/login');
|
|
24
|
+
jest.mock('../../utils');
|
|
25
|
+
openapi_core_1.getMergedConfig.mockImplementation((config) => config);
|
|
26
|
+
const mockPromptClientToken = login_1.promptClientToken;
|
|
27
|
+
describe('push-with-region', () => {
|
|
28
|
+
const redoclyClient = require('@redocly/openapi-core').__redoclyClient;
|
|
29
|
+
redoclyClient.isAuthorizedWithRedoclyByRegion = jest.fn().mockResolvedValue(false);
|
|
30
|
+
beforeAll(() => {
|
|
31
|
+
jest.spyOn(process.stdout, 'write').mockImplementation(() => true);
|
|
32
|
+
});
|
|
33
|
+
it('should call login with default domain when region is US', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
34
|
+
redoclyClient.domain = 'redoc.ly';
|
|
35
|
+
yield push_1.handlePush({
|
|
36
|
+
upsert: true,
|
|
37
|
+
entrypoint: 'spec.json',
|
|
38
|
+
destination: '@org/my-api@1.0.0',
|
|
39
|
+
branchName: 'test',
|
|
40
|
+
});
|
|
41
|
+
expect(mockPromptClientToken).toBeCalledTimes(1);
|
|
42
|
+
expect(mockPromptClientToken).toHaveBeenCalledWith(redoclyClient.domain);
|
|
43
|
+
}));
|
|
44
|
+
it('should call login with EU domain when region is EU', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
45
|
+
redoclyClient.domain = 'eu.redocly.com';
|
|
46
|
+
yield push_1.handlePush({
|
|
47
|
+
upsert: true,
|
|
48
|
+
entrypoint: 'spec.json',
|
|
49
|
+
destination: '@org/my-api@1.0.0',
|
|
50
|
+
branchName: 'test',
|
|
51
|
+
});
|
|
52
|
+
expect(mockPromptClientToken).toBeCalledTimes(1);
|
|
53
|
+
expect(mockPromptClientToken).toHaveBeenCalledWith(redoclyClient.domain);
|
|
54
|
+
}));
|
|
55
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,155 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const openapi_core_1 = require("@redocly/openapi-core");
|
|
13
|
+
const push_1 = require("../../commands/push");
|
|
14
|
+
jest.mock('fs');
|
|
15
|
+
jest.mock('node-fetch', () => ({
|
|
16
|
+
default: jest.fn(() => ({
|
|
17
|
+
ok: true,
|
|
18
|
+
json: jest.fn().mockResolvedValue({}),
|
|
19
|
+
})),
|
|
20
|
+
}));
|
|
21
|
+
jest.mock('@redocly/openapi-core');
|
|
22
|
+
jest.mock('../../utils');
|
|
23
|
+
openapi_core_1.getMergedConfig.mockImplementation((config) => config);
|
|
24
|
+
describe('push', () => {
|
|
25
|
+
const redoclyClient = require('@redocly/openapi-core').__redoclyClient;
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
jest.spyOn(process.stdout, 'write').mockImplementation(() => true);
|
|
28
|
+
});
|
|
29
|
+
it('pushes definition', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
30
|
+
yield push_1.handlePush({
|
|
31
|
+
upsert: true,
|
|
32
|
+
entrypoint: 'spec.json',
|
|
33
|
+
destination: '@org/my-api@1.0.0',
|
|
34
|
+
branchName: 'test',
|
|
35
|
+
'public': true
|
|
36
|
+
});
|
|
37
|
+
expect(redoclyClient.registryApi.prepareFileUpload).toBeCalledTimes(1);
|
|
38
|
+
expect(redoclyClient.registryApi.pushApi).toBeCalledTimes(1);
|
|
39
|
+
expect(redoclyClient.registryApi.pushApi).toHaveBeenLastCalledWith({
|
|
40
|
+
branch: 'test',
|
|
41
|
+
filePaths: ['filePath'],
|
|
42
|
+
isUpsert: true,
|
|
43
|
+
isPublic: true,
|
|
44
|
+
name: 'my-api',
|
|
45
|
+
organizationId: 'org',
|
|
46
|
+
rootFilePath: 'filePath',
|
|
47
|
+
version: '1.0.0',
|
|
48
|
+
});
|
|
49
|
+
}));
|
|
50
|
+
});
|
|
51
|
+
describe('transformPush', () => {
|
|
52
|
+
it('should adapt the existing syntax', () => {
|
|
53
|
+
const cb = jest.fn();
|
|
54
|
+
push_1.transformPush(cb)({
|
|
55
|
+
maybeEntrypointOrAliasOrDestination: 'openapi.yaml',
|
|
56
|
+
maybeDestination: '@testing_org/main@v1',
|
|
57
|
+
});
|
|
58
|
+
expect(cb).toBeCalledWith({
|
|
59
|
+
entrypoint: 'openapi.yaml',
|
|
60
|
+
destination: '@testing_org/main@v1',
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
it('should adapt the existing syntax (including branchName)', () => {
|
|
64
|
+
const cb = jest.fn();
|
|
65
|
+
push_1.transformPush(cb)({
|
|
66
|
+
maybeEntrypointOrAliasOrDestination: 'openapi.yaml',
|
|
67
|
+
maybeDestination: '@testing_org/main@v1',
|
|
68
|
+
maybeBranchName: 'other',
|
|
69
|
+
});
|
|
70
|
+
expect(cb).toBeCalledWith({
|
|
71
|
+
entrypoint: 'openapi.yaml',
|
|
72
|
+
destination: '@testing_org/main@v1',
|
|
73
|
+
branchName: 'other',
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
it('should use --branch option firstly', () => {
|
|
77
|
+
const cb = jest.fn();
|
|
78
|
+
push_1.transformPush(cb)({
|
|
79
|
+
maybeEntrypointOrAliasOrDestination: 'openapi.yaml',
|
|
80
|
+
maybeDestination: '@testing_org/main@v1',
|
|
81
|
+
maybeBranchName: 'other',
|
|
82
|
+
branch: 'priority-branch',
|
|
83
|
+
});
|
|
84
|
+
expect(cb).toBeCalledWith({
|
|
85
|
+
entrypoint: 'openapi.yaml',
|
|
86
|
+
destination: '@testing_org/main@v1',
|
|
87
|
+
branchName: 'priority-branch',
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
it('should work for a destination only', () => {
|
|
91
|
+
const cb = jest.fn();
|
|
92
|
+
push_1.transformPush(cb)({
|
|
93
|
+
maybeEntrypointOrAliasOrDestination: '@testing_org/main@v1',
|
|
94
|
+
});
|
|
95
|
+
expect(cb).toBeCalledWith({
|
|
96
|
+
destination: '@testing_org/main@v1',
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
it('should accept aliases for the old syntax', () => {
|
|
100
|
+
const cb = jest.fn();
|
|
101
|
+
push_1.transformPush(cb)({
|
|
102
|
+
maybeEntrypointOrAliasOrDestination: 'alias',
|
|
103
|
+
maybeDestination: '@testing_org/main@v1',
|
|
104
|
+
});
|
|
105
|
+
expect(cb).toBeCalledWith({
|
|
106
|
+
destination: '@testing_org/main@v1',
|
|
107
|
+
entrypoint: 'alias',
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
it('should accept no arguments at all', () => {
|
|
111
|
+
const cb = jest.fn();
|
|
112
|
+
push_1.transformPush(cb)({});
|
|
113
|
+
expect(cb).toBeCalledWith({});
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
describe('getDestinationProps', () => {
|
|
117
|
+
it('should get valid destination props for the full destination syntax', () => {
|
|
118
|
+
expect(push_1.getDestinationProps('@testing_org/main@v1', 'org-from-config')).toEqual([
|
|
119
|
+
'testing_org',
|
|
120
|
+
'main',
|
|
121
|
+
'v1',
|
|
122
|
+
]);
|
|
123
|
+
});
|
|
124
|
+
it('should fallback the organizationId from a config for the short destination syntax', () => {
|
|
125
|
+
expect(push_1.getDestinationProps('main@v1', 'org-from-config')).toEqual([
|
|
126
|
+
'org-from-config',
|
|
127
|
+
'main',
|
|
128
|
+
'v1',
|
|
129
|
+
]);
|
|
130
|
+
});
|
|
131
|
+
it('should fallback the organizationId from a config if no destination provided', () => {
|
|
132
|
+
expect(push_1.getDestinationProps(undefined, 'org-from-config')).toEqual(['org-from-config']);
|
|
133
|
+
});
|
|
134
|
+
it('should return empty organizationId if there is no one found', () => {
|
|
135
|
+
expect(push_1.getDestinationProps('main@v1', undefined)).toEqual([, 'main', 'v1']);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
describe('getApiEntrypoint', () => {
|
|
139
|
+
let config = {
|
|
140
|
+
apis: {
|
|
141
|
+
'main@v1': {
|
|
142
|
+
root: 'openapi.yaml',
|
|
143
|
+
},
|
|
144
|
+
main: {
|
|
145
|
+
root: 'latest.yaml',
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
it('should resolve the correct api for a valid name & version', () => {
|
|
150
|
+
expect(push_1.getApiEntrypoint({ name: 'main', version: 'v1', config })).toEqual('openapi.yaml');
|
|
151
|
+
});
|
|
152
|
+
it('should resolve the latest version of api if there is no matching version', () => {
|
|
153
|
+
expect(push_1.getApiEntrypoint({ name: 'main', version: 'latest', config })).toEqual('latest.yaml');
|
|
154
|
+
});
|
|
155
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const utils_1 = require("../utils");
|
|
4
|
+
jest.mock("os");
|
|
5
|
+
describe('isSubdir', () => {
|
|
6
|
+
it('can correctly determine if subdir', () => {
|
|
7
|
+
[
|
|
8
|
+
['/foo', '/foo', false],
|
|
9
|
+
['/foo', '/bar', false],
|
|
10
|
+
['/foo', '/foobar', false],
|
|
11
|
+
['/foo', '/foo/bar', true],
|
|
12
|
+
['/foo', '/foo/../bar', false],
|
|
13
|
+
['/foo', '/foo/./bar', true],
|
|
14
|
+
['/bar/../foo', '/foo/bar', true],
|
|
15
|
+
['/foo', './bar', false],
|
|
16
|
+
['/foo', '/foo/..bar', true],
|
|
17
|
+
].forEach(([parent, child, expectRes]) => {
|
|
18
|
+
expect(utils_1.isSubdir(parent, child)).toBe(expectRes);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
it('can correctly determine if subdir for windows-based paths', () => {
|
|
22
|
+
const os = require('os');
|
|
23
|
+
os.platform.mockImplementation(() => 'win32');
|
|
24
|
+
[
|
|
25
|
+
['C:/Foo', 'C:/Foo/Bar', true],
|
|
26
|
+
['C:\\Foo', 'C:\\Bar', false],
|
|
27
|
+
['C:\\Foo', 'D:\\Foo\\Bar', false],
|
|
28
|
+
].forEach(([parent, child, expectRes]) => {
|
|
29
|
+
expect(utils_1.isSubdir(parent, child)).toBe(expectRes);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
afterEach(() => {
|
|
33
|
+
jest.resetModules();
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
describe('pathToFilename', () => {
|
|
37
|
+
it('should use correct path separator', () => {
|
|
38
|
+
const processedPath = utils_1.pathToFilename('/user/createWithList', '_');
|
|
39
|
+
expect(processedPath).toEqual('user_createWithList');
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
try {
|
|
6
|
+
require('assert-node-version')(path.join(__dirname, '../'));
|
|
7
|
+
}
|
|
8
|
+
catch (err) {
|
|
9
|
+
utils_1.exitWithError(err.message);
|
|
10
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { OutputFormat } from '@redocly/openapi-core';
|
|
2
|
+
import { OutputExtensions } from '../types';
|
|
3
|
+
export declare function handleBundle(argv: {
|
|
4
|
+
entrypoints: string[];
|
|
5
|
+
output?: string;
|
|
6
|
+
ext: OutputExtensions;
|
|
7
|
+
'max-problems'?: number;
|
|
8
|
+
'skip-rule'?: string[];
|
|
9
|
+
'skip-preprocessor'?: string[];
|
|
10
|
+
'skip-decorator'?: string[];
|
|
11
|
+
dereferenced?: boolean;
|
|
12
|
+
force?: boolean;
|
|
13
|
+
config?: string;
|
|
14
|
+
lint?: boolean;
|
|
15
|
+
format: OutputFormat;
|
|
16
|
+
metafile?: string;
|
|
17
|
+
extends?: string[];
|
|
18
|
+
'remove-unused-components'?: boolean;
|
|
19
|
+
'keep-url-references'?: boolean;
|
|
20
|
+
}, version: string): Promise<void>;
|