@redocly/cli 1.0.0-beta.106 → 1.0.0-beta.109

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.
Files changed (37) hide show
  1. package/lib/__mocks__/@redocly/openapi-core.d.ts +28 -0
  2. package/lib/__mocks__/@redocly/openapi-core.js +35 -1
  3. package/lib/__mocks__/documents.d.ts +92 -0
  4. package/lib/__mocks__/documents.js +63 -0
  5. package/lib/__mocks__/utils.d.ts +1 -0
  6. package/lib/__mocks__/utils.js +2 -1
  7. package/lib/__tests__/commands/join.test.js +14 -0
  8. package/lib/commands/join.js +126 -53
  9. package/lib/commands/lint.js +5 -1
  10. package/lib/commands/preview-docs/index.js +3 -1
  11. package/lib/commands/preview-docs/preview-server/preview-server.js +2 -1
  12. package/lib/commands/push.js +6 -6
  13. package/lib/commands/split/index.js +5 -2
  14. package/lib/commands/split/types.d.ts +9 -9
  15. package/lib/commands/split/types.js +18 -18
  16. package/lib/commands/stats.js +2 -2
  17. package/lib/index.js +25 -5
  18. package/lib/js-utils.d.ts +1 -0
  19. package/lib/js-utils.js +7 -1
  20. package/lib/utils.js +1 -1
  21. package/package.json +2 -2
  22. package/src/__mocks__/@redocly/openapi-core.ts +38 -0
  23. package/src/__mocks__/documents.ts +63 -0
  24. package/src/__mocks__/utils.ts +1 -0
  25. package/src/__tests__/commands/join.test.ts +23 -1
  26. package/src/commands/join.ts +166 -62
  27. package/src/commands/lint.ts +6 -1
  28. package/src/commands/preview-docs/index.ts +4 -2
  29. package/src/commands/preview-docs/preview-server/preview-server.ts +2 -1
  30. package/src/commands/push.ts +6 -6
  31. package/src/commands/split/index.ts +9 -5
  32. package/src/commands/split/types.ts +17 -17
  33. package/src/commands/stats.ts +2 -2
  34. package/src/index.ts +25 -5
  35. package/src/js-utils.ts +5 -0
  36. package/src/utils.ts +1 -1
  37. package/tsconfig.tsbuildinfo +1 -1
@@ -198,8 +198,8 @@ function gatherComponentsFiles(components, componentsFiles, componentType, compo
198
198
  let inherits = [];
199
199
  if (componentType === types_1.OPENAPI3_COMPONENT.Schemas) {
200
200
  inherits = (((_b = (_a = components === null || components === void 0 ? void 0 : components[componentType]) === null || _a === void 0 ? void 0 : _a[componentName]) === null || _b === void 0 ? void 0 : _b.allOf) || [])
201
- .map((s) => s.$ref)
202
- .filter(Boolean);
201
+ .map(({ $ref }) => $ref)
202
+ .filter(openapi_core_1.isTruthy);
203
203
  }
204
204
  componentsFiles[componentType] = componentsFiles[componentType] || {};
205
205
  componentsFiles[componentType][componentName] = { inherits, filename };
@@ -225,6 +225,7 @@ function iteratePathItems(pathItems, openapiDir, outDir, componentsFiles, pathSe
225
225
  const sampleFileName = path.join(openapiDir, 'code_samples', utils_1.escapeLanguageName(sample.lang), codeSamplesPathPrefix + utils_1.pathToFilename(pathName, pathSeparator), method + langToExt(sample.lang));
226
226
  fs.mkdirSync(path.dirname(sampleFileName), { recursive: true });
227
227
  fs.writeFileSync(sampleFileName, sample.source);
228
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
228
229
  // @ts-ignore
229
230
  sample.source = {
230
231
  $ref: openapi_core_1.slash(path.relative(outDir, sampleFileName)),
@@ -247,6 +248,7 @@ function iterateComponents(openapi, openapiDir, componentsFiles) {
247
248
  const componentTypes = findComponentTypes(components);
248
249
  componentTypes.forEach(iterateAndGatherComponentsFiles);
249
250
  componentTypes.forEach(iterateComponentTypes);
251
+ // eslint-disable-next-line no-inner-declarations
250
252
  function iterateAndGatherComponentsFiles(componentType) {
251
253
  const componentDirPath = path.join(componentsDir, componentType);
252
254
  for (const componentName of Object.keys((components === null || components === void 0 ? void 0 : components[componentType]) || {})) {
@@ -254,6 +256,7 @@ function iterateComponents(openapi, openapiDir, componentsFiles) {
254
256
  gatherComponentsFiles(components, componentsFiles, componentType, componentName, filename);
255
257
  }
256
258
  }
259
+ // eslint-disable-next-line no-inner-declarations
257
260
  function iterateComponentTypes(componentType) {
258
261
  var _a, _b, _c;
259
262
  const componentDirPath = path.join(componentsDir, componentType);
@@ -12,15 +12,15 @@ export declare const PATHS = "paths";
12
12
  export declare const WEBHOOKS = "webhooks";
13
13
  export declare const xWEBHOOKS = "x-webhooks";
14
14
  export declare const componentsPath: string;
15
- declare enum OPENAPI3_METHOD {
16
- Get = "get",
17
- Put = "put",
18
- Post = "post",
19
- Delete = "delete",
20
- Options = "options",
21
- Head = "head",
22
- Patch = "patch",
23
- Trace = "trace"
15
+ export declare enum OPENAPI3_METHOD {
16
+ get = "get",
17
+ put = "put",
18
+ post = "post",
19
+ delete = "delete",
20
+ options = "options",
21
+ head = "head",
22
+ patch = "patch",
23
+ trace = "trace"
24
24
  }
25
25
  export declare const OPENAPI3_METHOD_NAMES: OPENAPI3_METHOD[];
26
26
  export declare enum OPENAPI3_COMPONENT {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.OPENAPI3_COMPONENT_NAMES = exports.OPENAPI3_COMPONENT = exports.OPENAPI3_METHOD_NAMES = exports.componentsPath = exports.xWEBHOOKS = exports.WEBHOOKS = exports.PATHS = exports.COMPONENTS = void 0;
3
+ exports.OPENAPI3_COMPONENT_NAMES = exports.OPENAPI3_COMPONENT = exports.OPENAPI3_METHOD_NAMES = exports.OPENAPI3_METHOD = exports.componentsPath = exports.xWEBHOOKS = exports.WEBHOOKS = exports.PATHS = exports.COMPONENTS = void 0;
4
4
  exports.COMPONENTS = 'components';
5
5
  exports.PATHS = 'paths';
6
6
  exports.WEBHOOKS = 'webhooks';
@@ -8,24 +8,24 @@ exports.xWEBHOOKS = 'x-webhooks';
8
8
  exports.componentsPath = `#/${exports.COMPONENTS}/`;
9
9
  var OPENAPI3_METHOD;
10
10
  (function (OPENAPI3_METHOD) {
11
- OPENAPI3_METHOD["Get"] = "get";
12
- OPENAPI3_METHOD["Put"] = "put";
13
- OPENAPI3_METHOD["Post"] = "post";
14
- OPENAPI3_METHOD["Delete"] = "delete";
15
- OPENAPI3_METHOD["Options"] = "options";
16
- OPENAPI3_METHOD["Head"] = "head";
17
- OPENAPI3_METHOD["Patch"] = "patch";
18
- OPENAPI3_METHOD["Trace"] = "trace";
19
- })(OPENAPI3_METHOD || (OPENAPI3_METHOD = {}));
11
+ OPENAPI3_METHOD["get"] = "get";
12
+ OPENAPI3_METHOD["put"] = "put";
13
+ OPENAPI3_METHOD["post"] = "post";
14
+ OPENAPI3_METHOD["delete"] = "delete";
15
+ OPENAPI3_METHOD["options"] = "options";
16
+ OPENAPI3_METHOD["head"] = "head";
17
+ OPENAPI3_METHOD["patch"] = "patch";
18
+ OPENAPI3_METHOD["trace"] = "trace";
19
+ })(OPENAPI3_METHOD = exports.OPENAPI3_METHOD || (exports.OPENAPI3_METHOD = {}));
20
20
  exports.OPENAPI3_METHOD_NAMES = [
21
- OPENAPI3_METHOD.Get,
22
- OPENAPI3_METHOD.Put,
23
- OPENAPI3_METHOD.Post,
24
- OPENAPI3_METHOD.Delete,
25
- OPENAPI3_METHOD.Options,
26
- OPENAPI3_METHOD.Head,
27
- OPENAPI3_METHOD.Patch,
28
- OPENAPI3_METHOD.Trace,
21
+ OPENAPI3_METHOD.get,
22
+ OPENAPI3_METHOD.put,
23
+ OPENAPI3_METHOD.post,
24
+ OPENAPI3_METHOD.delete,
25
+ OPENAPI3_METHOD.options,
26
+ OPENAPI3_METHOD.head,
27
+ OPENAPI3_METHOD.patch,
28
+ OPENAPI3_METHOD.trace,
29
29
  ];
30
30
  var OPENAPI3_COMPONENT;
31
31
  (function (OPENAPI3_COMPONENT) {
@@ -70,7 +70,7 @@ function handleStats(argv) {
70
70
  };
71
71
  const resolvedRefMap = yield openapi_core_1.resolveDocument({
72
72
  rootDocument: document,
73
- rootType: types.DefinitionRoot,
73
+ rootType: types.Root,
74
74
  externalRefResolver,
75
75
  });
76
76
  const statsVisitor = openapi_core_1.normalizeVisitors([
@@ -82,7 +82,7 @@ function handleStats(argv) {
82
82
  ], types);
83
83
  openapi_core_1.walkDocument({
84
84
  document,
85
- rootType: types.DefinitionRoot,
85
+ rootType: types.Root,
86
86
  normalizedVisitors: statsVisitor,
87
87
  resolvedRefMap,
88
88
  ctx,
package/lib/index.js CHANGED
@@ -33,7 +33,10 @@ yargs
33
33
  choices: ['stylish', 'json'],
34
34
  default: 'stylish',
35
35
  },
36
- }), stats_1.handleStats)
36
+ }), (argv) => {
37
+ process.env.REDOCLY_CLI_COMMAND = 'stats';
38
+ stats_1.handleStats(argv);
39
+ })
37
40
  .command('split [api]', 'Split definition into a multi-file structure.', (yargs) => yargs
38
41
  .positional('api', {
39
42
  description: 'API definition file that you want to split',
@@ -52,7 +55,10 @@ yargs
52
55
  default: '_',
53
56
  },
54
57
  })
55
- .demandOption('api'), split_1.handleSplit)
58
+ .demandOption('api'), (argv) => {
59
+ process.env.REDOCLY_CLI_COMMAND = 'split';
60
+ split_1.handleSplit(argv);
61
+ })
56
62
  .command('join [apis...]', 'Join definitions [experimental].', (yargs) => yargs
57
63
  .positional('apis', {
58
64
  array: true,
@@ -81,6 +87,7 @@ yargs
81
87
  type: 'boolean',
82
88
  },
83
89
  }), (argv) => {
90
+ process.env.REDOCLY_CLI_COMMAND = 'join';
84
91
  join_1.handleJoin(argv, version);
85
92
  })
86
93
  .command('push [maybeApiOrDestination] [maybeDestination] [maybeBranchName]', 'Push an API definition to the Redocly API registry.', (yargs) => yargs
@@ -112,7 +119,10 @@ yargs
112
119
  },
113
120
  })
114
121
  .implies('batch-id', 'batch-size')
115
- .implies('batch-size', 'batch-id'), push_1.transformPush(push_1.handlePush))
122
+ .implies('batch-size', 'batch-id'), (argv) => {
123
+ process.env.REDOCLY_CLI_COMMAND = 'push';
124
+ push_1.transformPush(push_1.handlePush)(argv);
125
+ })
116
126
  .command('lint [apis...]', 'Lint definition.', (yargs) => yargs.positional('apis', { array: true, type: 'string', demandOption: true }).option({
117
127
  format: {
118
128
  description: 'Use a specific output format.',
@@ -122,6 +132,7 @@ yargs
122
132
  'json',
123
133
  'checkstyle',
124
134
  'codeclimate',
135
+ 'summary',
125
136
  ],
126
137
  default: 'codeframe',
127
138
  },
@@ -162,6 +173,7 @@ yargs
162
173
  type: 'string',
163
174
  },
164
175
  }), (argv) => {
176
+ process.env.REDOCLY_CLI_COMMAND = 'lint';
165
177
  lint_1.handleLint(argv, version);
166
178
  })
167
179
  .command('bundle [apis...]', 'Bundle definition.', (yargs) => yargs.positional('apis', { array: true, type: 'string', demandOption: true }).options({
@@ -232,6 +244,7 @@ yargs
232
244
  default: false,
233
245
  },
234
246
  }), (argv) => {
247
+ process.env.REDOCLY_CLI_COMMAND = 'bundle';
235
248
  bundle_1.handleBundle(argv, version);
236
249
  })
237
250
  .command('login', 'Login to the Redocly API registry with an access token.', (yargs) => __awaiter(void 0, void 0, void 0, function* () {
@@ -246,8 +259,12 @@ yargs
246
259
  choices: types_1.regionChoices,
247
260
  },
248
261
  });
249
- }), login_1.handleLogin)
262
+ }), (argv) => {
263
+ process.env.REDOCLY_CLI_COMMAND = 'login';
264
+ login_1.handleLogin(argv);
265
+ })
250
266
  .command('logout', 'Clear your stored credentials for the Redocly API registry.', (yargs) => yargs, () => __awaiter(void 0, void 0, void 0, function* () {
267
+ process.env.REDOCLY_CLI_COMMAND = 'logout';
251
268
  const client = new openapi_core_1.RedoclyClient();
252
269
  client.logout();
253
270
  process.stdout.write('Logged out from the Redocly account. ✋\n');
@@ -288,7 +305,10 @@ yargs
288
305
  description: 'Specify path to the config file.',
289
306
  type: 'string',
290
307
  },
291
- }), preview_docs_1.previewDocs)
308
+ }), (argv) => {
309
+ process.env.REDOCLY_CLI_COMMAND = 'preview-docs';
310
+ preview_docs_1.previewDocs(argv);
311
+ })
292
312
  .completion('completion', 'Generate completion script.')
293
313
  .demandCommand(1)
294
314
  .strict().argv;
package/lib/js-utils.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export declare function isObject(obj: any): boolean;
2
2
  export declare function isEmptyObject(obj: any): boolean;
3
3
  export declare function isString(str: string): boolean;
4
+ export declare function keysOf<T>(obj: T): (keyof T)[];
package/lib/js-utils.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isString = exports.isEmptyObject = exports.isObject = void 0;
3
+ exports.keysOf = exports.isString = exports.isEmptyObject = exports.isObject = void 0;
4
4
  function isObject(obj) {
5
5
  const type = typeof obj;
6
6
  return type === 'function' || (type === 'object' && !!obj);
@@ -14,3 +14,9 @@ function isString(str) {
14
14
  return Object.prototype.toString.call(str) === '[object String]';
15
15
  }
16
16
  exports.isString = isString;
17
+ function keysOf(obj) {
18
+ if (!obj)
19
+ return [];
20
+ return Object.keys(obj);
21
+ }
22
+ exports.keysOf = keysOf;
package/lib/utils.js CHANGED
@@ -106,6 +106,7 @@ function dumpBundle(obj, format, dereference) {
106
106
  else {
107
107
  return openapi_core_1.stringifyYaml(obj, {
108
108
  noRefs: !dereference,
109
+ lineWidth: -1,
109
110
  });
110
111
  }
111
112
  }
@@ -175,7 +176,6 @@ function handleError(e, ref) {
175
176
  // TODO: codeframe
176
177
  }
177
178
  else {
178
- // @ts-ignore
179
179
  if (e instanceof CircularJSONNotSupportedError) {
180
180
  process.stderr.write(colorette_1.red(`Detected circular reference which can't be converted to JSON.\n`) +
181
181
  `Try to use ${colorette_1.blue('yaml')} output or remove ${colorette_1.blue('--dereferenced')}.\n\n`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/cli",
3
- "version": "1.0.0-beta.106",
3
+ "version": "1.0.0-beta.109",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -35,7 +35,7 @@
35
35
  "Andriy Leliv <andriy@redoc.ly> (https://redoc.ly/)"
36
36
  ],
37
37
  "dependencies": {
38
- "@redocly/openapi-core": "1.0.0-beta.106",
38
+ "@redocly/openapi-core": "1.0.0-beta.109",
39
39
  "assert-node-version": "^1.0.3",
40
40
  "chokidar": "^3.5.1",
41
41
  "colorette": "^1.2.0",
@@ -1,4 +1,6 @@
1
1
  import { ConfigFixture } from './../../__tests__/fixtures/config';
2
+ import { Document, ResolveError } from '@redocly/openapi-core';
3
+ import { firstDocument, secondDocument } from '../documents';
2
4
 
3
5
  export const __redoclyClient = {
4
6
  isAuthorizedWithRedocly: jest.fn().mockResolvedValue(true),
@@ -25,3 +27,39 @@ export const formatProblems = jest.fn();
25
27
  export const slash = jest.fn();
26
28
  export const findConfig = jest.fn();
27
29
  export const doesYamlFileExist = jest.fn();
30
+ export const bundleDocument = jest.fn(() => Promise.resolve({ problems: {} }));
31
+ export const detectOpenAPI = jest.fn();
32
+
33
+ export class BaseResolver {
34
+ cache = new Map<string, Promise<Document | ResolveError>>();
35
+
36
+ getFiles = jest.fn();
37
+ resolveExternalRef = jest.fn();
38
+ loadExternalRef = jest.fn;
39
+ parseDocument = jest.fn();
40
+ resolveDocument = jest
41
+ .fn()
42
+ .mockImplementationOnce(() =>
43
+ Promise.resolve({ source: { absoluteRef: 'ref' }, parsed: firstDocument })
44
+ )
45
+ .mockImplementationOnce(() =>
46
+ Promise.resolve({ source: { absoluteRef: 'ref' }, parsed: secondDocument })
47
+ );
48
+ }
49
+
50
+ export enum OasVersion {
51
+ Version2 = 'oas2',
52
+ Version3_0 = 'oas3_0',
53
+ Version3_1 = 'oas3_1',
54
+ }
55
+
56
+ export enum Oas3Operations {
57
+ get = 'get',
58
+ put = 'put',
59
+ post = 'post',
60
+ delete = 'delete',
61
+ options = 'options',
62
+ head = 'head',
63
+ patch = 'patch',
64
+ trace = 'trace',
65
+ }
@@ -0,0 +1,63 @@
1
+ export const firstDocument = {
2
+ openapi: '3.0.0',
3
+ servers: [{ url: 'http://localhost:8080' }],
4
+ info: {
5
+ description: 'example test',
6
+ version: '1.0.0',
7
+ title: 'Swagger Petstore',
8
+ termsOfService: 'http://swagger.io/terms/',
9
+ license: {
10
+ name: 'Apache 2.0',
11
+ url: 'http://www.apache.org/licenses/LICENSE-2.0.html',
12
+ },
13
+ },
14
+ paths: {
15
+ '/GETUser/{userId}': {
16
+ summary: 'get user by id',
17
+ description: 'user info',
18
+ servers: [{ url: '/user' }, { url: '/pet', description: 'pet server' }],
19
+
20
+ get: {
21
+ tags: ['pet'],
22
+ summary: 'Find pet by ID',
23
+ description: 'Returns a single pet',
24
+ operationId: 'getPetById',
25
+ servers: [{ url: '/pet' }],
26
+ },
27
+ parameters: [{ name: 'param1', in: 'header', schema: { description: 'string' } }],
28
+ },
29
+ },
30
+ components: {},
31
+ };
32
+
33
+ export const secondDocument = {
34
+ openapi: '3.0.0',
35
+ servers: [{ url: 'http://localhost:8080' }],
36
+ info: {
37
+ description: 'example test',
38
+ version: '1.0.0',
39
+ title: 'Swagger Petstore',
40
+ termsOfService: 'http://swagger.io/terms/',
41
+ license: {
42
+ name: 'Apache 2.0',
43
+ url: 'http://www.apache.org/licenses/LICENSE-2.0.html',
44
+ },
45
+ },
46
+ post: {
47
+ '/GETUser/{userId}': {
48
+ summary: 'get user',
49
+ description: 'user information',
50
+ servers: [{ url: '/user' }, { url: '/pet', description: '' }],
51
+
52
+ get: {
53
+ tags: ['pet'],
54
+ summary: 'Find pet by ID',
55
+ description: 'Returns a single pet',
56
+ operationId: 'getPetById',
57
+ servers: [{ url: '/pet' }],
58
+ },
59
+ parameters: [{ name: 'param1', in: 'header', schema: { description: 'string' } }],
60
+ },
61
+ },
62
+ components: {},
63
+ };
@@ -11,3 +11,4 @@ export const printLintTotals = jest.fn();
11
11
  export const getOutputFileName = jest.fn(() => ({ outputFile: 'test.yaml', ext: 'yaml' }));
12
12
  export const handleError = jest.fn();
13
13
  export const exitWithError = jest.fn();
14
+ export const writeYaml = jest.fn();
@@ -1,6 +1,7 @@
1
1
  import { handleJoin } from '../../commands/join';
2
- import { exitWithError } from '../../utils';
2
+ import { exitWithError, writeYaml } from '../../utils';
3
3
  import { yellow } from 'colorette';
4
+ import { detectOpenAPI } from '@redocly/openapi-core';
4
5
 
5
6
  jest.mock('../../utils');
6
7
  jest.mock('colorette');
@@ -44,4 +45,25 @@ describe('handleJoin fails', () => {
44
45
  `You use prefix-tags-with-filename, without-x-tag-groups together.\nPlease choose only one! \n\n`
45
46
  );
46
47
  });
48
+
49
+ it('should call exitWithError because Only OpenAPI 3 is supported', async () => {
50
+ await handleJoin(
51
+ {
52
+ apis: ['first.yaml', 'second.yaml'],
53
+ },
54
+ 'cli-version'
55
+ );
56
+ expect(exitWithError).toHaveBeenCalledWith('Only OpenAPI 3 is supported: undefined \n\n');
57
+ });
58
+
59
+ it('should call writeYaml function', async () => {
60
+ (detectOpenAPI as jest.Mock).mockReturnValue('oas3_0');
61
+ await handleJoin(
62
+ {
63
+ apis: ['first.yaml', 'second.yaml'],
64
+ },
65
+ 'cli-version'
66
+ );
67
+ expect(writeYaml).toHaveBeenCalled();
68
+ });
47
69
  });