@redocly/cli 1.0.0-beta.103 → 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.
Files changed (63) hide show
  1. package/bin/cli.js +1 -1
  2. package/lib/__mocks__/@redocly/openapi-core.d.ts +2 -1
  3. package/lib/__mocks__/@redocly/openapi-core.js +2 -1
  4. package/lib/__mocks__/perf_hooks.js +1 -1
  5. package/lib/__mocks__/utils.d.ts +1 -1
  6. package/lib/__mocks__/utils.js +2 -2
  7. package/lib/__tests__/commands/bundle.test.js +52 -17
  8. package/lib/__tests__/commands/join.test.js +4 -4
  9. package/lib/__tests__/commands/lint.test.js +14 -8
  10. package/lib/__tests__/commands/push-region.test.js +2 -2
  11. package/lib/__tests__/commands/push.test.js +18 -18
  12. package/lib/__tests__/fixtures/config.d.ts +1 -1
  13. package/lib/__tests__/fixtures/config.js +1 -1
  14. package/lib/commands/bundle.d.ts +4 -12
  15. package/lib/commands/bundle.js +12 -11
  16. package/lib/commands/join.d.ts +1 -1
  17. package/lib/commands/join.js +109 -58
  18. package/lib/commands/lint.d.ts +3 -9
  19. package/lib/commands/lint.js +14 -11
  20. package/lib/commands/preview-docs/index.d.ts +3 -5
  21. package/lib/commands/preview-docs/index.js +14 -14
  22. package/lib/commands/push.d.ts +6 -6
  23. package/lib/commands/push.js +26 -26
  24. package/lib/commands/split/__tests__/index.test.js +8 -8
  25. package/lib/commands/split/index.d.ts +1 -1
  26. package/lib/commands/split/index.js +12 -11
  27. package/lib/commands/split/types.d.ts +2 -2
  28. package/lib/commands/split/types.js +2 -2
  29. package/lib/commands/stats.d.ts +1 -1
  30. package/lib/commands/stats.js +9 -7
  31. package/lib/index.js +12 -16
  32. package/lib/js-utils.js +2 -2
  33. package/lib/types.d.ts +13 -1
  34. package/lib/utils.d.ts +4 -4
  35. package/lib/utils.js +15 -17
  36. package/package.json +2 -2
  37. package/src/__mocks__/@redocly/openapi-core.ts +1 -0
  38. package/src/__mocks__/perf_hooks.ts +2 -2
  39. package/src/__mocks__/utils.ts +3 -1
  40. package/src/__tests__/commands/bundle.test.ts +71 -22
  41. package/src/__tests__/commands/join.test.ts +8 -8
  42. package/src/__tests__/commands/lint.test.ts +24 -11
  43. package/src/__tests__/commands/push-region.test.ts +2 -2
  44. package/src/__tests__/commands/push.test.ts +19 -24
  45. package/src/__tests__/fixtures/config.ts +1 -1
  46. package/src/__tests__/utils.test.ts +5 -8
  47. package/src/commands/bundle.ts +28 -40
  48. package/src/commands/join.ts +213 -121
  49. package/src/commands/lint.ts +30 -30
  50. package/src/commands/login.ts +2 -2
  51. package/src/commands/preview-docs/index.ts +33 -40
  52. package/src/commands/preview-docs/preview-server/preview-server.ts +6 -6
  53. package/src/commands/preview-docs/preview-server/server.ts +1 -1
  54. package/src/commands/push.ts +44 -53
  55. package/src/commands/split/__tests__/index.test.ts +47 -30
  56. package/src/commands/split/index.ts +84 -46
  57. package/src/commands/split/types.ts +19 -7
  58. package/src/commands/stats.ts +27 -24
  59. package/src/index.ts +16 -20
  60. package/src/js-utils.ts +2 -2
  61. package/src/types.ts +14 -1
  62. package/src/utils.ts +53 -53
  63. package/tsconfig.tsbuildinfo +1 -1
@@ -8,7 +8,7 @@ import {
8
8
  OasVersion,
9
9
  BaseResolver,
10
10
  Document,
11
- LintConfig,
11
+ StyleguideConfig,
12
12
  Oas3Tag,
13
13
  loadConfig,
14
14
  formatProblems,
@@ -19,12 +19,12 @@ import {
19
19
  } from '@redocly/openapi-core';
20
20
 
21
21
  import {
22
- getFallbackEntryPointsOrExit,
22
+ getFallbackApisOrExit,
23
23
  printExecutionTime,
24
24
  handleError,
25
25
  printLintTotals,
26
26
  writeYaml,
27
- exitWithError
27
+ exitWithError,
28
28
  } from '../utils';
29
29
  import { isObject, isString } from '../js-utils';
30
30
 
@@ -34,8 +34,8 @@ const xTagGroups = 'x-tagGroups';
34
34
  let potentialConflictsTotal = 0;
35
35
 
36
36
  type JoinDocumentContext = {
37
- entrypoint: string;
38
- entrypointFilename: string;
37
+ api: string;
38
+ apiFilename: string;
39
39
  tags: Oas3Tag[];
40
40
  potentialConflicts: any;
41
41
  tagsPrefix: string;
@@ -43,7 +43,7 @@ type JoinDocumentContext = {
43
43
  };
44
44
 
45
45
  type JoinArgv = {
46
- entrypoints: string[];
46
+ apis: string[];
47
47
  lint?: boolean;
48
48
  'prefix-tags-with-info-prop'?: string;
49
49
  'prefix-tags-with-filename'?: boolean;
@@ -51,11 +51,10 @@ type JoinArgv = {
51
51
  'without-x-tag-groups'?: boolean;
52
52
  };
53
53
 
54
-
55
54
  export async function handleJoin(argv: JoinArgv, packageVersion: string) {
56
55
  const startedAt = performance.now();
57
- if (argv.entrypoints.length < 2) {
58
- return exitWithError(`At least 2 entrypoints should be provided. \n\n`);
56
+ if (argv.apis.length < 2) {
57
+ return exitWithError(`At least 2 apis should be provided. \n\n`);
59
58
  }
60
59
 
61
60
  const {
@@ -73,27 +72,29 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
73
72
 
74
73
  if (usedTagsOptions.length > 1) {
75
74
  return exitWithError(
76
- `You use ${yellow(usedTagsOptions.join(', '))} together.\nPlease choose only one! \n\n`,
75
+ `You use ${yellow(usedTagsOptions.join(', '))} together.\nPlease choose only one! \n\n`
77
76
  );
78
77
  }
79
-
78
+
80
79
  const config: Config = await loadConfig();
81
- const entrypoints = await getFallbackEntryPointsOrExit(argv.entrypoints, config);
80
+ const apis = await getFallbackApisOrExit(argv.apis, config);
82
81
  const externalRefResolver = new BaseResolver(config.resolve);
83
82
  const documents = await Promise.all(
84
- entrypoints.map(
83
+ apis.map(
85
84
  ({ path }) => externalRefResolver.resolveDocument(null, path, true) as Promise<Document>
86
85
  )
87
86
  );
88
87
 
89
88
  const bundleResults = await Promise.all(
90
- documents.map(document => bundleDocument({
91
- document,
92
- config: config.lint,
93
- externalRefResolver
94
- }).catch(e => {
95
- exitWithError(`${e.message}: ${blue(document.source.absoluteRef)}`)
96
- }))
89
+ documents.map((document) =>
90
+ bundleDocument({
91
+ document,
92
+ config: config.styleguide,
93
+ externalRefResolver,
94
+ }).catch((e) => {
95
+ exitWithError(`${e.message}: ${blue(document.source.absoluteRef)}`);
96
+ })
97
+ )
97
98
  );
98
99
 
99
100
  for (const { problems, bundle: document } of bundleResults as any) {
@@ -101,17 +102,23 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
101
102
  if (fileTotals.errors) {
102
103
  formatProblems(problems, {
103
104
  totals: fileTotals,
104
- version: document.parsed.version
105
+ version: document.parsed.version,
105
106
  });
106
- exitWithError(`❌ Errors encountered while bundling ${blue(document.source.absoluteRef)}: join will not proceed.\n`);
107
+ exitWithError(
108
+ `❌ Errors encountered while bundling ${blue(
109
+ document.source.absoluteRef
110
+ )}: join will not proceed.\n`
111
+ );
107
112
  }
108
113
  }
109
114
 
110
115
  for (const document of documents) {
111
116
  try {
112
- const version = detectOpenAPI(document.parsed)
117
+ const version = detectOpenAPI(document.parsed);
113
118
  if (version !== OasVersion.Version3_0) {
114
- return exitWithError(`Only OpenAPI 3 is supported: ${blue(document.source.absoluteRef)} \n\n`);
119
+ return exitWithError(
120
+ `Only OpenAPI 3 is supported: ${blue(document.source.absoluteRef)} \n\n`
121
+ );
115
122
  }
116
123
  } catch (e) {
117
124
  return exitWithError(`${e.message}: ${blue(document.source.absoluteRef)}`);
@@ -120,7 +127,7 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
120
127
 
121
128
  if (argv.lint) {
122
129
  for (const document of documents) {
123
- await validateEntrypoint(document, config.lint, externalRefResolver, packageVersion);
130
+ await validateApi(document, config.styleguide, externalRefResolver, packageVersion);
124
131
  }
125
132
  }
126
133
 
@@ -137,24 +144,37 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
137
144
  for (const document of documents) {
138
145
  const openapi = document.parsed;
139
146
  const { tags, info } = openapi;
140
- const entrypoint = path.relative(process.cwd(), document.source.absoluteRef);
141
- const entrypointFilename = getEntrypointFilename(entrypoint);
142
- const tagsPrefix = prefixTagsWithFilename ? entrypointFilename : getInfoPrefix(info, prefixTagsWithInfoProp, 'tags');
147
+ const api = path.relative(process.cwd(), document.source.absoluteRef);
148
+ const apiFilename = getApiFilename(api);
149
+ const tagsPrefix = prefixTagsWithFilename
150
+ ? apiFilename
151
+ : getInfoPrefix(info, prefixTagsWithInfoProp, 'tags');
143
152
  const componentsPrefix = getInfoPrefix(info, prefixComponentsWithInfoProp, COMPONENTS);
144
153
 
145
154
  if (openapi.hasOwnProperty('x-tagGroups')) {
146
- process.stderr.write(yellow(`warning: x-tagGroups at ${blue(entrypoint)} will be skipped \n`));
155
+ process.stderr.write(yellow(`warning: x-tagGroups at ${blue(api)} will be skipped \n`));
147
156
  }
148
157
 
149
- const context = { entrypoint, entrypointFilename, tags, potentialConflicts, tagsPrefix, componentsPrefix };
150
- if (tags) { populateTags(context); }
158
+ const context = {
159
+ api,
160
+ apiFilename,
161
+ tags,
162
+ potentialConflicts,
163
+ tagsPrefix,
164
+ componentsPrefix,
165
+ };
166
+ if (tags) {
167
+ populateTags(context);
168
+ }
151
169
  collectServers(openapi);
152
170
  collectInfoDescriptions(openapi, context);
153
171
  collectExternalDocs(openapi, context);
154
172
  collectPaths(openapi, context);
155
173
  collectComponents(openapi, context);
156
174
  collectXWebhooks(openapi, context);
157
- if (componentsPrefix) { replace$Refs(openapi, componentsPrefix); }
175
+ if (componentsPrefix) {
176
+ replace$Refs(openapi, componentsPrefix);
177
+ }
158
178
  }
159
179
 
160
180
  iteratePotentialConflicts(potentialConflicts, withoutXTagGroups);
@@ -163,14 +183,14 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
163
183
 
164
184
  if (potentialConflictsTotal) {
165
185
  return exitWithError(`Please fix conflicts before running ${yellow('join')}.`);
166
- }
186
+ }
167
187
 
168
188
  writeYaml(joinedDef, specFilename, noRefs);
169
189
  printExecutionTime('join', startedAt, specFilename);
170
190
 
171
191
  function populateTags({
172
- entrypoint,
173
- entrypointFilename,
192
+ api,
193
+ apiFilename,
174
194
  tags,
175
195
  potentialConflicts,
176
196
  tagsPrefix,
@@ -194,55 +214,57 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
194
214
  const tagDuplicate = joinedDef.tags.find((t: Oas3Tag) => t.name === entrypointTagName);
195
215
 
196
216
  if (tagDuplicate && withoutXTagGroups) {
197
- // If tag already exist and `without-x-tag-groups` option;
198
- // check if description are different for potential conflicts warning;
217
+ // If tag already exist and `without-x-tag-groups` option,
218
+ // check if description are different for potential conflicts warning.
199
219
  const isTagDescriptionNotEqual =
200
220
  tag.hasOwnProperty('description') && tagDuplicate.description !== tag.description;
201
221
 
202
222
  potentialConflicts.tags.description[entrypointTagName].push(
203
- ...(isTagDescriptionNotEqual ? [entrypoint] : []),
223
+ ...(isTagDescriptionNotEqual ? [api] : [])
204
224
  );
205
- } else {
206
- // Instead add tag to joinedDef;
225
+ } else if (!tagDuplicate) {
226
+ // Instead add tag to joinedDef if there no duplicate;
207
227
  tag['x-displayName'] = tag['x-displayName'] || tag.name;
208
228
  tag.name = entrypointTagName;
209
229
  joinedDef.tags.push(tag);
210
230
 
211
231
  if (withoutXTagGroups) {
212
- potentialConflicts.tags.description[entrypointTagName] = [entrypoint];
232
+ potentialConflicts.tags.description[entrypointTagName] = [api];
213
233
  }
214
234
  }
215
235
 
216
236
  if (!withoutXTagGroups) {
217
- createXTagGroups(entrypointFilename);
218
- populateXTagGroups(entrypointTagName, getIndexGroup(entrypointFilename));
237
+ createXTagGroups(apiFilename);
238
+ if (!tagDuplicate) {
239
+ populateXTagGroups(entrypointTagName, getIndexGroup(apiFilename));
240
+ }
219
241
  }
220
242
 
221
243
  const doesEntrypointExist =
222
244
  !potentialConflicts.tags.all[entrypointTagName] ||
223
245
  (potentialConflicts.tags.all[entrypointTagName] &&
224
- !potentialConflicts.tags.all[entrypointTagName].includes(entrypoint));
246
+ !potentialConflicts.tags.all[entrypointTagName].includes(api));
225
247
  potentialConflicts.tags.all[entrypointTagName] = [
226
248
  ...(potentialConflicts.tags.all[entrypointTagName] || []),
227
- ...(!withoutXTagGroups && doesEntrypointExist ? [entrypoint] : []),
249
+ ...(!withoutXTagGroups && doesEntrypointExist ? [api] : []),
228
250
  ];
229
251
  }
230
252
  }
231
253
 
232
- function getIndexGroup(entrypointFilename: string): number {
233
- return joinedDef[xTagGroups].findIndex((item: any) => item.name === entrypointFilename);
254
+ function getIndexGroup(apiFilename: string): number {
255
+ return joinedDef[xTagGroups].findIndex((item: any) => item.name === apiFilename);
234
256
  }
235
257
 
236
- function createXTagGroups(entrypointFilename: string) {
258
+ function createXTagGroups(apiFilename: string) {
237
259
  if (!joinedDef.hasOwnProperty(xTagGroups)) {
238
260
  joinedDef[xTagGroups] = [];
239
261
  }
240
262
 
241
- if (!joinedDef[xTagGroups].some((g: any) => g.name === entrypointFilename)) {
242
- joinedDef[xTagGroups].push({ name: entrypointFilename, tags: [] });
263
+ if (!joinedDef[xTagGroups].some((g: any) => g.name === apiFilename)) {
264
+ joinedDef[xTagGroups].push({ name: apiFilename, tags: [] });
243
265
  }
244
266
 
245
- const indexGroup = getIndexGroup(entrypointFilename);
267
+ const indexGroup = getIndexGroup(apiFilename);
246
268
 
247
269
  if (!joinedDef[xTagGroups][indexGroup].hasOwnProperty(Tags)) {
248
270
  joinedDef[xTagGroups][indexGroup][Tags] = [];
@@ -250,7 +272,9 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
250
272
  }
251
273
 
252
274
  function populateXTagGroups(entrypointTagName: string, indexGroup: number) {
253
- if (!joinedDef[xTagGroups][indexGroup][Tags].find((t: Oas3Tag) => t.name === entrypointTagName)) {
275
+ if (
276
+ !joinedDef[xTagGroups][indexGroup][Tags].find((t: Oas3Tag) => t.name === entrypointTagName)
277
+ ) {
254
278
  joinedDef[xTagGroups][indexGroup][Tags].push(entrypointTagName);
255
279
  }
256
280
  }
@@ -258,7 +282,9 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
258
282
  function collectServers(openapi: Oas3Definition) {
259
283
  const { servers } = openapi;
260
284
  if (servers) {
261
- if (!joinedDef.hasOwnProperty('servers')) { joinedDef['servers'] = []; }
285
+ if (!joinedDef.hasOwnProperty('servers')) {
286
+ joinedDef['servers'] = [];
287
+ }
262
288
  for (const server of servers) {
263
289
  if (!joinedDef.servers.some((s: any) => s.url === server.url)) {
264
290
  joinedDef.servers.push(server);
@@ -269,14 +295,11 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
269
295
 
270
296
  function collectInfoDescriptions(
271
297
  openapi: Oas3Definition,
272
- {
273
- entrypointFilename,
274
- componentsPrefix
275
- }: JoinDocumentContext
298
+ { apiFilename, componentsPrefix }: JoinDocumentContext
276
299
  ) {
277
300
  const { info } = openapi;
278
301
  if (info?.description) {
279
- const groupIndex = joinedDef[xTagGroups] ? getIndexGroup(entrypointFilename) : -1;
302
+ const groupIndex = joinedDef[xTagGroups] ? getIndexGroup(apiFilename) : -1;
280
303
  if (
281
304
  joinedDef.hasOwnProperty(xTagGroups) &&
282
305
  groupIndex !== -1 &&
@@ -285,17 +308,19 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
285
308
  ) {
286
309
  joinedDef[xTagGroups][groupIndex]['description'] = addComponentsPrefix(
287
310
  info.description,
288
- componentsPrefix!,
311
+ componentsPrefix!
289
312
  );
290
313
  }
291
314
  }
292
315
  }
293
316
 
294
- function collectExternalDocs(openapi: Oas3Definition, { entrypoint }: JoinDocumentContext) {
317
+ function collectExternalDocs(openapi: Oas3Definition, { api }: JoinDocumentContext) {
295
318
  const { externalDocs } = openapi;
296
319
  if (externalDocs) {
297
320
  if (joinedDef.hasOwnProperty('externalDocs')) {
298
- process.stderr.write(yellow(`warning: skip externalDocs from ${blue(path.basename(entrypoint))} \n`));
321
+ process.stderr.write(
322
+ yellow(`warning: skip externalDocs from ${blue(path.basename(api))} \n`)
323
+ );
299
324
  return;
300
325
  }
301
326
  joinedDef['externalDocs'] = externalDocs;
@@ -304,42 +329,74 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
304
329
 
305
330
  function collectPaths(
306
331
  openapi: Oas3Definition,
307
- {
308
- entrypointFilename,
309
- entrypoint,
310
- potentialConflicts,
311
- tagsPrefix,
312
- componentsPrefix
313
- }: JoinDocumentContext
332
+ { apiFilename, api, potentialConflicts, tagsPrefix, componentsPrefix }: JoinDocumentContext
314
333
  ) {
315
334
  const { paths } = openapi;
316
335
  if (paths) {
317
- if (!joinedDef.hasOwnProperty('paths')) { joinedDef['paths'] = {}; }
336
+ if (!joinedDef.hasOwnProperty('paths')) {
337
+ joinedDef['paths'] = {};
338
+ }
318
339
  for (const path of Object.keys(paths)) {
319
- if (!joinedDef.paths.hasOwnProperty(path)) { joinedDef.paths[path] = {}; }
320
- if (!potentialConflicts.paths.hasOwnProperty(path)) { potentialConflicts.paths[path] = {}; }
340
+ if (!joinedDef.paths.hasOwnProperty(path)) {
341
+ joinedDef.paths[path] = {};
342
+ }
343
+ if (!potentialConflicts.paths.hasOwnProperty(path)) {
344
+ potentialConflicts.paths[path] = {};
345
+ }
321
346
  for (const operation of Object.keys(paths[path])) {
322
347
  // @ts-ignore
323
348
  const pathOperation = paths[path][operation];
324
349
  joinedDef.paths[path][operation] = pathOperation;
325
- potentialConflicts.paths[path][operation] = [...(potentialConflicts.paths[path][operation] || []), entrypoint];
350
+ potentialConflicts.paths[path][operation] = [
351
+ ...(potentialConflicts.paths[path][operation] || []),
352
+ api,
353
+ ];
326
354
  const { operationId } = pathOperation;
327
355
  if (operationId) {
328
- if (!potentialConflicts.paths.hasOwnProperty('operationIds')) { potentialConflicts.paths['operationIds'] = {}; }
329
- potentialConflicts.paths.operationIds[operationId] = [...(potentialConflicts.paths.operationIds[operationId] || []), entrypoint];
356
+ if (!potentialConflicts.paths.hasOwnProperty('operationIds')) {
357
+ potentialConflicts.paths['operationIds'] = {};
358
+ }
359
+ potentialConflicts.paths.operationIds[operationId] = [
360
+ ...(potentialConflicts.paths.operationIds[operationId] || []),
361
+ api,
362
+ ];
330
363
  }
331
364
  let { tags, security } = joinedDef.paths[path][operation];
332
365
  if (tags) {
333
- joinedDef.paths[path][operation].tags = tags.map((tag: string) => addPrefix(tag, tagsPrefix));
334
- populateTags({ entrypoint, entrypointFilename, tags: formatTags(tags), potentialConflicts, tagsPrefix, componentsPrefix });
366
+ joinedDef.paths[path][operation].tags = tags.map((tag: string) =>
367
+ addPrefix(tag, tagsPrefix)
368
+ );
369
+ populateTags({
370
+ api,
371
+ apiFilename,
372
+ tags: formatTags(tags),
373
+ potentialConflicts,
374
+ tagsPrefix,
375
+ componentsPrefix,
376
+ });
335
377
  } else {
336
- joinedDef.paths[path][operation]['tags'] = [addPrefix('other', tagsPrefix || entrypointFilename)];
337
- populateTags({ entrypoint, entrypointFilename, tags: formatTags(['other']), potentialConflicts, tagsPrefix: tagsPrefix || entrypointFilename, componentsPrefix });
378
+ joinedDef.paths[path][operation]['tags'] = [
379
+ addPrefix('other', tagsPrefix || apiFilename),
380
+ ];
381
+ populateTags({
382
+ api,
383
+ apiFilename,
384
+ tags: formatTags(['other']),
385
+ potentialConflicts,
386
+ tagsPrefix: tagsPrefix || apiFilename,
387
+ componentsPrefix,
388
+ });
338
389
  }
339
390
  if (!security && openapi.hasOwnProperty('security')) {
340
- joinedDef.paths[path][operation]['security'] = addSecurityPrefix(openapi.security, componentsPrefix!);
391
+ joinedDef.paths[path][operation]['security'] = addSecurityPrefix(
392
+ openapi.security,
393
+ componentsPrefix!
394
+ );
341
395
  } else if (pathOperation.security) {
342
- joinedDef.paths[path][operation].security = addSecurityPrefix(pathOperation.security, componentsPrefix!);
396
+ joinedDef.paths[path][operation].security = addSecurityPrefix(
397
+ pathOperation.security,
398
+ componentsPrefix!
399
+ );
343
400
  }
344
401
  }
345
402
  }
@@ -348,15 +405,13 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
348
405
 
349
406
  function collectComponents(
350
407
  openapi: Oas3Definition,
351
- {
352
- entrypoint,
353
- potentialConflicts,
354
- componentsPrefix
355
- }: JoinDocumentContext
408
+ { api, potentialConflicts, componentsPrefix }: JoinDocumentContext
356
409
  ) {
357
410
  const { components } = openapi;
358
411
  if (components) {
359
- if (!joinedDef.hasOwnProperty(COMPONENTS)) { joinedDef[COMPONENTS] = {}; }
412
+ if (!joinedDef.hasOwnProperty(COMPONENTS)) {
413
+ joinedDef[COMPONENTS] = {};
414
+ }
360
415
  for (const component of Object.keys(components)) {
361
416
  if (!potentialConflicts[COMPONENTS].hasOwnProperty(component)) {
362
417
  potentialConflicts[COMPONENTS][component] = {};
@@ -367,7 +422,8 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
367
422
  for (const item of Object.keys(componentObj)) {
368
423
  const componentPrefix = addPrefix(item, componentsPrefix!);
369
424
  potentialConflicts.components[component][componentPrefix] = [
370
- ...(potentialConflicts.components[component][item] || []), { [entrypoint]: componentObj[item]}
425
+ ...(potentialConflicts.components[component][item] || []),
426
+ { [api]: componentObj[item] },
371
427
  ];
372
428
  joinedDef.components[component][componentPrefix] = componentObj[item];
373
429
  }
@@ -377,40 +433,53 @@ export async function handleJoin(argv: JoinArgv, packageVersion: string) {
377
433
 
378
434
  function collectXWebhooks(
379
435
  openapi: Oas3Definition,
380
- {
381
- entrypointFilename,
382
- entrypoint,
383
- potentialConflicts,
384
- tagsPrefix,
385
- componentsPrefix
386
- }: JoinDocumentContext
436
+ { apiFilename, api, potentialConflicts, tagsPrefix, componentsPrefix }: JoinDocumentContext
387
437
  ) {
388
438
  const xWebhooks = 'x-webhooks';
389
439
  // @ts-ignore
390
440
  const openapiXWebhooks = openapi[xWebhooks];
391
441
  if (openapiXWebhooks) {
392
- if (!joinedDef.hasOwnProperty(xWebhooks)) { joinedDef[xWebhooks] = {}; }
442
+ if (!joinedDef.hasOwnProperty(xWebhooks)) {
443
+ joinedDef[xWebhooks] = {};
444
+ }
393
445
  for (const webhook of Object.keys(openapiXWebhooks)) {
394
446
  joinedDef[xWebhooks][webhook] = openapiXWebhooks[webhook];
395
447
 
396
- if (!potentialConflicts.xWebhooks.hasOwnProperty(webhook)) { potentialConflicts.xWebhooks[webhook] = {}; }
448
+ if (!potentialConflicts.xWebhooks.hasOwnProperty(webhook)) {
449
+ potentialConflicts.xWebhooks[webhook] = {};
450
+ }
397
451
  for (const operation of Object.keys(openapiXWebhooks[webhook])) {
398
- potentialConflicts.xWebhooks[webhook][operation] = [...(potentialConflicts.xWebhooks[webhook][operation] || []), entrypoint];
452
+ potentialConflicts.xWebhooks[webhook][operation] = [
453
+ ...(potentialConflicts.xWebhooks[webhook][operation] || []),
454
+ api,
455
+ ];
399
456
  }
400
457
  for (const operationKey of Object.keys(joinedDef[xWebhooks][webhook])) {
401
458
  let { tags } = joinedDef[xWebhooks][webhook][operationKey];
402
459
  if (tags) {
403
- joinedDef[xWebhooks][webhook][operationKey].tags = tags.map((tag: string) => addPrefix(tag, tagsPrefix));
404
- populateTags({ entrypoint, entrypointFilename, tags: formatTags(tags), potentialConflicts, tagsPrefix, componentsPrefix });
460
+ joinedDef[xWebhooks][webhook][operationKey].tags = tags.map((tag: string) =>
461
+ addPrefix(tag, tagsPrefix)
462
+ );
463
+ populateTags({
464
+ api,
465
+ apiFilename,
466
+ tags: formatTags(tags),
467
+ potentialConflicts,
468
+ tagsPrefix,
469
+ componentsPrefix,
470
+ });
405
471
  }
406
472
  }
407
473
  }
408
474
  }
409
475
  }
410
476
 
411
- function addInfoSectionAndSpecVersion(documents: any, prefixComponentsWithInfoProp: string | undefined) {
412
- const firstEntrypoint = documents[0];
413
- const openapi = firstEntrypoint.parsed;
477
+ function addInfoSectionAndSpecVersion(
478
+ documents: any,
479
+ prefixComponentsWithInfoProp: string | undefined
480
+ ) {
481
+ const firstApi = documents[0];
482
+ const openapi = firstApi.parsed;
414
483
  const componentsPrefix = getInfoPrefix(openapi.info, prefixComponentsWithInfoProp, COMPONENTS);
415
484
  if (!openapi.openapi) exitWithError('Version of specification is not found in. \n');
416
485
  if (!openapi.info) exitWithError('Info section is not found in specification. \n');
@@ -473,9 +542,9 @@ function duplicateTagDescriptionWarning(conflicts: [string, any][]) {
473
542
  process.stderr.write(
474
543
  yellow(
475
544
  `\nwarning: ${tagsKeys.length} conflict(s) on the ${red(
476
- tagsKeys.join(joinString),
477
- )} tags description.\n`,
478
- ),
545
+ tagsKeys.join(joinString)
546
+ )} tags description.\n`
547
+ )
479
548
  );
480
549
  }
481
550
 
@@ -501,12 +570,12 @@ function filterConflicts(entities: object) {
501
570
  return Object.entries(entities).filter(([_, files]) => files.length > 1);
502
571
  }
503
572
 
504
- function getEntrypointFilename(filePath: string) {
505
- return path.basename(filePath, path.extname(filePath))
573
+ function getApiFilename(filePath: string) {
574
+ return path.basename(filePath, path.extname(filePath));
506
575
  }
507
576
 
508
577
  function addPrefix(tag: string, tagsPrefix: string) {
509
- return tagsPrefix ? tagsPrefix +'_'+ tag : tag;
578
+ return tagsPrefix ? tagsPrefix + '_' + tag : tag;
510
579
  }
511
580
 
512
581
  function formatTags(tags: string[]) {
@@ -517,26 +586,44 @@ function addComponentsPrefix(description: string, componentsPrefix: string) {
517
586
  return description.replace(/"(#\/components\/.*?)"/g, (match) => {
518
587
  const componentName = path.basename(match);
519
588
  return match.replace(componentName, addPrefix(componentName, componentsPrefix));
520
- })
589
+ });
521
590
  }
522
591
 
523
592
  function addSecurityPrefix(security: any, componentsPrefix: string) {
524
- return componentsPrefix ? security?.map((s: any) => {
525
- const key = Object.keys(s)[0];
526
- return { [componentsPrefix +'_'+ key]: s[key] }
527
- }) : security;
593
+ return componentsPrefix
594
+ ? security?.map((s: any) => {
595
+ const key = Object.keys(s)[0];
596
+ return { [componentsPrefix + '_' + key]: s[key] };
597
+ })
598
+ : security;
528
599
  }
529
600
 
530
601
  function getInfoPrefix(info: any, prefixArg: string | undefined, type: string) {
531
602
  if (!prefixArg) return '';
532
603
  if (!info) exitWithError('Info section is not found in specification. \n');
533
- if (!info[prefixArg]) exitWithError(`${yellow(`prefix-${type}-with-info-prop`)} argument value is not found in info section. \n`);
534
- if (!isString(info[prefixArg])) exitWithError(`${yellow(`prefix-${type}-with-info-prop`)} argument value should be string. \n\n`);
535
- if (info[prefixArg].length > 50) exitWithError(`${yellow(`prefix-${type}-with-info-prop`)} argument value length should not exceed 50 characters. \n\n`);
604
+ if (!info[prefixArg])
605
+ exitWithError(
606
+ `${yellow(`prefix-${type}-with-info-prop`)} argument value is not found in info section. \n`
607
+ );
608
+ if (!isString(info[prefixArg]))
609
+ exitWithError(
610
+ `${yellow(`prefix-${type}-with-info-prop`)} argument value should be string. \n\n`
611
+ );
612
+ if (info[prefixArg].length > 50)
613
+ exitWithError(
614
+ `${yellow(
615
+ `prefix-${type}-with-info-prop`
616
+ )} argument value length should not exceed 50 characters. \n\n`
617
+ );
536
618
  return info[prefixArg];
537
619
  }
538
620
 
539
- async function validateEntrypoint(document: Document, config: LintConfig, externalRefResolver: BaseResolver, packageVersion: string) {
621
+ async function validateApi(
622
+ document: Document,
623
+ config: StyleguideConfig,
624
+ externalRefResolver: BaseResolver,
625
+ packageVersion: string
626
+ ) {
540
627
  try {
541
628
  const results = await lintDocument({ document, config, externalRefResolver });
542
629
  const fileTotals = getTotals(results);
@@ -559,7 +646,7 @@ function replace$Refs(obj: any, componentsPrefix: string) {
559
646
  crawl(obj, (node: any) => {
560
647
  if (node.$ref && isString(node.$ref) && node.$ref.startsWith(`#/${COMPONENTS}/`)) {
561
648
  const name = path.basename(node.$ref);
562
- node.$ref = node.$ref.replace(name, componentsPrefix +'_'+ name);
649
+ node.$ref = node.$ref.replace(name, componentsPrefix + '_' + name);
563
650
  } else if (
564
651
  node.discriminator &&
565
652
  node.discriminator.mapping &&
@@ -568,9 +655,14 @@ function replace$Refs(obj: any, componentsPrefix: string) {
568
655
  const { mapping } = node.discriminator;
569
656
  for (const name of Object.keys(mapping)) {
570
657
  if (isString(mapping[name]) && mapping[name].startsWith(`#/${COMPONENTS}/`)) {
571
- mapping[name] = mapping[name].split('/').map((name: string, i: number, arr: []) => {
572
- return (arr.length - 1 === i && !name.includes(componentsPrefix)) ? componentsPrefix+'_'+name : name;
573
- }).join('/')
658
+ mapping[name] = mapping[name]
659
+ .split('/')
660
+ .map((name: string, i: number, arr: []) => {
661
+ return arr.length - 1 === i && !name.includes(componentsPrefix)
662
+ ? componentsPrefix + '_' + name
663
+ : name;
664
+ })
665
+ .join('/');
574
666
  }
575
667
  }
576
668
  }