@redocly/openapi-core 1.9.0 → 1.9.1

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 (43) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/lib/bundle.d.ts +1 -1
  3. package/lib/lint.d.ts +1 -0
  4. package/lib/lint.js +1 -1
  5. package/lib/oas-types.d.ts +1 -1
  6. package/lib/ref-utils.js +2 -2
  7. package/lib/resolve.js +9 -1
  8. package/lib/types/index.d.ts +7 -7
  9. package/lib/types/json-schema-adapter.d.ts +3 -0
  10. package/lib/types/json-schema-adapter.js +173 -0
  11. package/lib/types/oas2.d.ts +3 -2
  12. package/lib/types/oas3.d.ts +3 -2
  13. package/lib/types/oas3_1.d.ts +3 -2
  14. package/lib/types/portal-config-schema.d.ts +5261 -52
  15. package/lib/types/portal-config-schema.js +71 -55
  16. package/lib/types/redocly-yaml.d.ts +13 -1
  17. package/lib/types/redocly-yaml.js +101 -39
  18. package/lib/types/theme-config.d.ts +819 -36
  19. package/lib/types/theme-config.js +67 -29
  20. package/lib/utils.d.ts +2 -2
  21. package/lib/visitors.js +1 -1
  22. package/lib/walk.js +7 -1
  23. package/package.json +1 -1
  24. package/src/__tests__/lint.test.ts +1218 -36
  25. package/src/__tests__/ref-utils.test.ts +22 -0
  26. package/src/config/__tests__/load.test.ts +13 -13
  27. package/src/decorators/oas2/remove-unused-components.ts +3 -2
  28. package/src/decorators/oas3/remove-unused-components.ts +3 -2
  29. package/src/lint.ts +2 -1
  30. package/src/ref-utils.ts +2 -2
  31. package/src/resolve.ts +13 -1
  32. package/src/types/index.ts +7 -12
  33. package/src/types/json-schema-adapter.ts +217 -0
  34. package/src/types/oas2.ts +5 -2
  35. package/src/types/oas3.ts +6 -2
  36. package/src/types/oas3_1.ts +5 -2
  37. package/src/types/portal-config-schema.ts +111 -61
  38. package/src/types/redocly-yaml.ts +118 -43
  39. package/src/types/theme-config.ts +125 -27
  40. package/src/utils.ts +2 -2
  41. package/src/visitors.ts +1 -1
  42. package/src/walk.ts +7 -1
  43. package/tsconfig.tsbuildinfo +1 -1
@@ -1,3 +1,5 @@
1
+ import type { FromSchema } from 'json-schema-to-ts';
2
+
1
3
  const logoConfigSchema = {
2
4
  type: 'object',
3
5
  properties: {
@@ -68,6 +70,11 @@ const markdownConfigSchema = {
68
70
  items: { type: 'string' },
69
71
  default: ['image', 'links'],
70
72
  },
73
+ partialsFolders: {
74
+ type: 'array',
75
+ items: { type: 'string' },
76
+ default: ['_partials'],
77
+ },
71
78
  lastUpdatedBlock: {
72
79
  type: 'object',
73
80
  properties: {
@@ -76,7 +83,7 @@ const markdownConfigSchema = {
76
83
  enum: ['timeago', 'iso', 'long', 'short'],
77
84
  default: 'timeago',
78
85
  },
79
- locale: { type: 'string', default: 'en-US' },
86
+ locale: { type: 'string' },
80
87
  ...hideConfigSchema.properties,
81
88
  },
82
89
  additionalProperties: false,
@@ -187,6 +194,21 @@ const gtmAnalyticsConfigSchema = {
187
194
  required: ['trackingId'],
188
195
  } as const;
189
196
 
197
+ const productGoogleAnalyticsConfigSchema = {
198
+ type: 'object',
199
+ properties: {
200
+ includeInDevelopment: { type: 'boolean' },
201
+ trackingId: { type: 'string' },
202
+
203
+ conversionId: { type: 'string' },
204
+ floodlightId: { type: 'string' },
205
+ optimizeId: { type: 'string' },
206
+ exclude: { type: 'array', items: { type: 'string' } },
207
+ },
208
+ additionalProperties: false,
209
+ required: ['trackingId'],
210
+ } as const;
211
+
190
212
  const googleAnalyticsConfigSchema = {
191
213
  type: 'object',
192
214
  properties: {
@@ -203,6 +225,12 @@ const googleAnalyticsConfigSchema = {
203
225
  optimizeId: { type: 'string' },
204
226
  anonymizeIp: { type: 'boolean' },
205
227
  cookieExpires: { type: 'number' },
228
+
229
+ // All enabled tracking configs
230
+ trackers: {
231
+ type: 'object',
232
+ additionalProperties: productGoogleAnalyticsConfigSchema,
233
+ },
206
234
  },
207
235
  additionalProperties: false,
208
236
  required: ['trackingId'],
@@ -224,6 +252,7 @@ const navItemSchema = {
224
252
  properties: {
225
253
  page: { type: 'string' },
226
254
  directory: { type: 'string' },
255
+ disconnect: { type: 'boolean', default: false },
227
256
  group: { type: 'string' },
228
257
  label: { type: 'string' },
229
258
  separator: { type: 'string' },
@@ -264,7 +293,7 @@ const productConfigSchema = {
264
293
  folder: { type: 'string' },
265
294
  },
266
295
  additionalProperties: false,
267
- required: ['name', 'icon', 'folder'],
296
+ required: ['name', 'folder'],
268
297
  } as const;
269
298
 
270
299
  const suggestedPageSchema = {
@@ -287,6 +316,7 @@ const catalogFilterSchema = {
287
316
  titleTranslationKey: { type: 'string' },
288
317
  property: { type: 'string' },
289
318
  parentFilter: { type: 'string' },
319
+ valuesMapping: { type: 'object', additionalProperties: { type: 'string' } },
290
320
  missingCategoryName: { type: 'string' },
291
321
  missingCategoryNameTranslationKey: { type: 'string' },
292
322
  options: { type: 'array', items: { type: 'string' } },
@@ -296,9 +326,9 @@ const catalogFilterSchema = {
296
326
  const scorecardConfigSchema = {
297
327
  type: 'object',
298
328
  additionalProperties: true,
299
- required: ['levels'],
329
+ required: [],
300
330
  properties: {
301
- failBuildIfBelowMinimum: { type: 'boolean', default: false },
331
+ ignoreNonCompliant: { type: 'boolean', default: false },
302
332
  teamMetadataProperty: {
303
333
  type: 'object',
304
334
  properties: {
@@ -314,11 +344,12 @@ const scorecardConfigSchema = {
314
344
  required: ['name'],
315
345
  properties: {
316
346
  name: { type: 'string' },
347
+ color: { type: 'string' },
317
348
  extends: { type: 'array', items: { type: 'string' } },
318
349
  rules: {
319
350
  type: 'object',
320
351
  additionalProperties: {
321
- type: ['object', 'string'],
352
+ oneOf: [{ type: 'string' }, { type: 'object' }],
322
353
  },
323
354
  },
324
355
  },
@@ -420,12 +451,6 @@ export const themeConfigSchema = {
420
451
  },
421
452
  additionalProperties: false,
422
453
  },
423
- seo: {
424
- type: 'object',
425
- properties: {
426
- title: { type: 'string' },
427
- },
428
- },
429
454
  scripts: {
430
455
  type: 'object',
431
456
  properties: {
@@ -444,7 +469,7 @@ export const themeConfigSchema = {
444
469
  },
445
470
  type: {
446
471
  type: 'string',
447
- enum: ['rating', 'sentiment', 'comment', 'reasons'],
472
+ enum: ['rating', 'sentiment', 'comment', 'reasons', 'mood', 'scale'],
448
473
  default: 'sentiment',
449
474
  },
450
475
  settings: {
@@ -452,15 +477,27 @@ export const themeConfigSchema = {
452
477
  properties: {
453
478
  label: { type: 'string' },
454
479
  submitText: { type: 'string' },
455
- max: { type: 'number' },
456
480
  buttonText: { type: 'string' },
457
- multi: { type: 'boolean' },
481
+ component: {
482
+ type: 'string',
483
+ enum: ['radio', 'checkbox'],
484
+ default: 'checkbox',
485
+ },
458
486
  items: { type: 'array', items: { type: 'string' }, minItems: 1 },
487
+ leftScaleLabel: { type: 'string' },
488
+ rightScaleLabel: { type: 'string' },
459
489
  reasons: {
460
490
  type: 'object',
461
491
  properties: {
462
- enable: { type: 'boolean', default: true },
463
- multi: { type: 'boolean' },
492
+ hide: {
493
+ type: 'boolean',
494
+ default: false,
495
+ },
496
+ component: {
497
+ type: 'string',
498
+ enum: ['radio', 'checkbox'],
499
+ default: 'checkbox',
500
+ },
464
501
  label: { type: 'string' },
465
502
  items: { type: 'array', items: { type: 'string' } },
466
503
  },
@@ -469,10 +506,16 @@ export const themeConfigSchema = {
469
506
  comment: {
470
507
  type: 'object',
471
508
  properties: {
472
- enable: { type: 'boolean', default: true },
509
+ hide: {
510
+ type: 'boolean',
511
+ default: false,
512
+ },
473
513
  label: { type: 'string' },
474
514
  likeLabel: { type: 'string' },
475
515
  dislikeLabel: { type: 'string' },
516
+ satisfiedLabel: { type: 'string' },
517
+ neutralLabel: { type: 'string' },
518
+ dissatisfiedLabel: { type: 'string' },
476
519
  },
477
520
  additionalProperties: false,
478
521
  },
@@ -525,7 +568,7 @@ export const themeConfigSchema = {
525
568
  nextButton: {
526
569
  type: 'object',
527
570
  properties: {
528
- text: { type: 'string', default: 'Next to {label}' },
571
+ text: { type: 'string', default: 'Next to {{label}}' },
529
572
  ...hideConfigSchema.properties,
530
573
  },
531
574
  additionalProperties: false,
@@ -534,7 +577,7 @@ export const themeConfigSchema = {
534
577
  previousButton: {
535
578
  type: 'object',
536
579
  properties: {
537
- text: { type: 'string', default: 'Back to {label}' },
580
+ text: { type: 'string', default: 'Back to {{label}}' },
538
581
  ...hideConfigSchema.properties,
539
582
  },
540
583
  additionalProperties: false,
@@ -547,7 +590,7 @@ export const themeConfigSchema = {
547
590
  codeSnippet: {
548
591
  type: 'object',
549
592
  properties: {
550
- controlsStyle: { type: 'string', default: 'icon' },
593
+ elementFormat: { type: 'string', default: 'icon' },
551
594
  copy: {
552
595
  type: 'object',
553
596
  properties: {
@@ -559,10 +602,13 @@ export const themeConfigSchema = {
559
602
  report: {
560
603
  type: 'object',
561
604
  properties: {
605
+ tooltipText: { type: 'string' },
606
+ buttonText: { type: 'string' },
607
+ label: { type: 'string' },
562
608
  ...hideConfigSchema.properties,
563
609
  },
564
610
  additionalProperties: false,
565
- default: { hide: true },
611
+ default: { hide: false },
566
612
  },
567
613
  expand: {
568
614
  type: 'object',
@@ -585,7 +631,7 @@ export const themeConfigSchema = {
585
631
  default: {},
586
632
  },
587
633
  markdown: markdownConfigSchema,
588
- openapi: { type: 'object', additionalProperties: true },
634
+ openapi: { type: 'object', additionalProperties: true }, // TODO: put the real schema here @Viacheslav
589
635
  graphql: { type: 'object', additionalProperties: true },
590
636
  analytics: {
591
637
  type: 'object',
@@ -671,13 +717,65 @@ export const productThemeOverrideSchema = {
671
717
  search: themeConfigSchema.properties.search,
672
718
  codeSnippet: themeConfigSchema.properties.codeSnippet,
673
719
  breadcrumbs: themeConfigSchema.properties.breadcrumbs,
720
+ analytics: {
721
+ type: 'object',
722
+ properties: {
723
+ ga: productGoogleAnalyticsConfigSchema,
724
+ },
725
+ },
674
726
  },
675
727
  additionalProperties: true,
676
728
  default: {},
677
729
  } as const;
678
730
 
679
- export enum ScorecardStatus {
680
- BelowMinimum = 'Below minimum',
681
- Highest = 'Highest',
682
- Minimum = 'Minimum',
683
- }
731
+ export type ThemeConfig = FromSchema<typeof themeConfigSchema>;
732
+
733
+ // TODO: cannot export as it relies on external types
734
+ // export type ThemeUIConfig = ThemeConfig & {
735
+ // auth?: {
736
+ // // used by portal dev login emulator
737
+ // idpsInfo?: {
738
+ // idpId: string;
739
+ // type: string; // AuthProviderType
740
+ // title: string | undefined;
741
+ // }[];
742
+ // devLogin?: boolean;
743
+ // loginUrls?: Record<string, string>;
744
+ // };
745
+ // search?: {
746
+ // shortcuts?: string[];
747
+ // suggestedPages?: any[];
748
+ // };
749
+ // breadcrumbs?: {
750
+ // prefixItems?: ResolvedNavLinkItem[];
751
+ // };
752
+ // products?: {
753
+ // [key: string]: ProductUiConfig;
754
+ // };
755
+ // };
756
+
757
+ export type ProductConfig = FromSchema<typeof productConfigSchema>;
758
+
759
+ export type ProductGoogleAnalyticsConfig = FromSchema<typeof productGoogleAnalyticsConfigSchema>;
760
+ // TODO: cannot export as it relies on external types
761
+ // export type ProductThemeOverrideConfig = Pick<
762
+ // ThemeUIConfig,
763
+ // 'logo' | 'navbar' | 'footer' | 'sidebar' | 'search' | 'codeSnippet' | 'breadcrumbs'
764
+ // > & { analytics?: { ga?: ProductGoogleAnalyticsConfig } };
765
+ // export type ProductUiConfig = ProductConfig & {
766
+ // slug: string;
767
+ // link: string;
768
+ // [REDOCLY_TEAMS_RBAC]?: { [key: string]: string };
769
+ // themeOverride?: ProductThemeOverrideConfig;
770
+ // };
771
+
772
+ export type MarkdownConfig = FromSchema<typeof markdownConfigSchema>;
773
+
774
+ export type AmplitudeAnalyticsConfig = FromSchema<typeof amplitudeAnalyticsConfigSchema>;
775
+ export type RudderstackAnalyticsConfig = FromSchema<typeof rudderstackAnalyticsConfigSchema>;
776
+ export type SegmentAnalyticsConfig = FromSchema<typeof segmentAnalyticsConfigSchema>;
777
+ export type GtmAnalyticsConfig = FromSchema<typeof gtmAnalyticsConfigSchema>;
778
+ export type GoogleAnalyticsConfig = FromSchema<typeof googleAnalyticsConfigSchema>;
779
+ export type CatalogConfig = FromSchema<typeof catalogSchema>;
780
+ export type CatalogFilterConfig = FromSchema<typeof catalogFilterSchema>;
781
+ export type ScorecardConfig = FromSchema<typeof scorecardConfigSchema>;
package/src/utils.ts CHANGED
@@ -37,11 +37,11 @@ export function isDefined<T>(x: T | undefined): x is T {
37
37
  return x !== undefined;
38
38
  }
39
39
 
40
- export function isPlainObject(value: any): value is object {
40
+ export function isPlainObject(value: any): value is Record<string, unknown> {
41
41
  return value !== null && typeof value === 'object' && !Array.isArray(value);
42
42
  }
43
43
 
44
- export function isEmptyObject(value: any): value is object {
44
+ export function isEmptyObject(value: any): value is Record<string, unknown> {
45
45
  return isPlainObject(value) && Object.keys(value).length === 0;
46
46
  }
47
47
 
package/src/visitors.ts CHANGED
@@ -359,7 +359,7 @@ export function normalizeVisitors<T extends BaseVisitor>(
359
359
  possibleChildren.add(from.additionalProperties);
360
360
  }
361
361
  }
362
- if (from.items) {
362
+ if (from.items && typeof from.items !== 'function') {
363
363
  if (from.items === to) {
364
364
  addWeakFromStack(ruleConf, stack);
365
365
  } else if (from.items.name !== undefined) {
package/src/walk.ts CHANGED
@@ -271,8 +271,14 @@ export function walkDocument<T extends BaseVisitor>(opts: {
271
271
  if (Array.isArray(resolvedNode)) {
272
272
  const itemsType = type.items;
273
273
  if (itemsType !== undefined) {
274
+ const isTypeAFunction = typeof itemsType === 'function';
274
275
  for (let i = 0; i < resolvedNode.length; i++) {
275
- walkNode(resolvedNode[i], itemsType, resolvedLocation.child([i]), resolvedNode, i);
276
+ const itemType = isTypeAFunction
277
+ ? itemsType(resolvedNode[i], resolvedLocation.child([i]).absolutePointer)
278
+ : itemsType;
279
+ if (isNamedType(itemType)) {
280
+ walkNode(resolvedNode[i], itemType, resolvedLocation.child([i]), resolvedNode, i);
281
+ }
276
282
  }
277
283
  }
278
284
  } else if (typeof resolvedNode === 'object' && resolvedNode !== null) {