@redocly/openapi-core 1.9.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/lib/bundle.d.ts +1 -1
  3. package/lib/bundle.js +2 -2
  4. package/lib/config/config.d.ts +0 -6
  5. package/lib/config/config.js +1 -19
  6. package/lib/config/load.js +2 -2
  7. package/lib/decorators/common/registry-dependencies.js +2 -2
  8. package/lib/index.d.ts +3 -2
  9. package/lib/index.js +17 -2
  10. package/lib/lint.d.ts +1 -0
  11. package/lib/lint.js +1 -1
  12. package/lib/oas-types.d.ts +1 -1
  13. package/lib/redocly/domains.d.ts +14 -0
  14. package/lib/redocly/domains.js +41 -0
  15. package/lib/redocly/index.d.ts +1 -2
  16. package/lib/redocly/index.js +14 -24
  17. package/lib/redocly/registry-api.d.ts +2 -2
  18. package/lib/redocly/registry-api.js +9 -9
  19. package/lib/ref-utils.js +2 -2
  20. package/lib/resolve.js +9 -1
  21. package/lib/types/index.d.ts +7 -7
  22. package/lib/types/json-schema-adapter.d.ts +3 -0
  23. package/lib/types/json-schema-adapter.js +173 -0
  24. package/lib/types/oas2.d.ts +3 -2
  25. package/lib/types/oas3.d.ts +3 -2
  26. package/lib/types/oas3_1.d.ts +3 -2
  27. package/lib/types/portal-config-schema.d.ts +5261 -52
  28. package/lib/types/portal-config-schema.js +71 -55
  29. package/lib/types/redocly-yaml.d.ts +13 -1
  30. package/lib/types/redocly-yaml.js +101 -39
  31. package/lib/types/theme-config.d.ts +819 -36
  32. package/lib/types/theme-config.js +67 -29
  33. package/lib/utils.d.ts +4 -2
  34. package/lib/utils.js +7 -1
  35. package/lib/visitors.js +1 -1
  36. package/lib/walk.js +7 -1
  37. package/package.json +2 -1
  38. package/src/__tests__/lint.test.ts +1218 -36
  39. package/src/__tests__/ref-utils.test.ts +22 -0
  40. package/src/bundle.ts +1 -1
  41. package/src/config/__tests__/load.test.ts +13 -13
  42. package/src/config/config.ts +1 -23
  43. package/src/config/load.ts +2 -1
  44. package/src/decorators/common/registry-dependencies.ts +1 -1
  45. package/src/decorators/oas2/remove-unused-components.ts +3 -2
  46. package/src/decorators/oas3/remove-unused-components.ts +3 -2
  47. package/src/index.ts +11 -2
  48. package/src/lint.ts +2 -1
  49. package/src/redocly/__tests__/domains.test.ts +52 -0
  50. package/src/redocly/__tests__/redocly-client.test.ts +5 -3
  51. package/src/redocly/domains.ts +48 -0
  52. package/src/redocly/index.ts +14 -24
  53. package/src/redocly/registry-api.ts +25 -31
  54. package/src/ref-utils.ts +2 -2
  55. package/src/resolve.ts +13 -1
  56. package/src/types/index.ts +7 -12
  57. package/src/types/json-schema-adapter.ts +217 -0
  58. package/src/types/oas2.ts +5 -2
  59. package/src/types/oas3.ts +6 -2
  60. package/src/types/oas3_1.ts +5 -2
  61. package/src/types/portal-config-schema.ts +111 -61
  62. package/src/types/redocly-yaml.ts +118 -43
  63. package/src/types/theme-config.ts +125 -27
  64. package/src/utils.ts +9 -3
  65. package/src/visitors.ts +1 -1
  66. package/src/walk.ts +7 -1
  67. package/tsconfig.tsbuildinfo +1 -1
@@ -1,8 +1,10 @@
1
- import { rootRedoclyConfigSchema, apiConfigSchema } from './portal-config-schema';
2
- import { themeConfigSchema } from './theme-config';
3
- import { NodeType, listOf } from '.';
1
+ import { rootRedoclyConfigSchema } from './portal-config-schema';
2
+ import { listOf } from '.';
4
3
  import { omitObjectProps, pickObjectProps, isCustomRuleId } from '../utils';
5
- import { PortalConfigNodeTypes } from './portal-config-schema';
4
+ import { getNodeTypesFromJSONSchema } from './json-schema-adapter';
5
+
6
+ import type { NodeType } from '.';
7
+ import type { JSONSchema } from 'json-schema-to-ts';
6
8
 
7
9
  const builtInCommonRules = [
8
10
  'spec',
@@ -97,8 +99,49 @@ const builtInRules = [
97
99
 
98
100
  type BuiltInRuleId = typeof builtInRules[number];
99
101
 
100
- const nodeTypesList = [
101
- 'any',
102
+ const oas2NodeTypesList = [
103
+ 'Root',
104
+ 'Tag',
105
+ 'TagList',
106
+ 'ExternalDocs',
107
+ 'SecurityRequirement',
108
+ 'SecurityRequirementList',
109
+ 'Info',
110
+ 'Contact',
111
+ 'License',
112
+ 'Paths',
113
+ 'PathItem',
114
+ 'Parameter',
115
+ 'ParameterList',
116
+ 'ParameterItems',
117
+ 'Operation',
118
+ 'Example',
119
+ 'ExamplesMap',
120
+ 'Examples',
121
+ 'Header',
122
+ 'Responses',
123
+ 'Response',
124
+ 'Schema',
125
+ 'Xml',
126
+ 'SchemaProperties',
127
+ 'NamedSchemas',
128
+ 'NamedResponses',
129
+ 'NamedParameters',
130
+ 'NamedSecuritySchemes',
131
+ 'SecurityScheme',
132
+ 'TagGroup',
133
+ 'TagGroups',
134
+ 'EnumDescriptions',
135
+ 'Logo',
136
+ 'XCodeSample',
137
+ 'XCodeSampleList',
138
+ 'XServer',
139
+ 'XServerList',
140
+ ] as const;
141
+
142
+ export type Oas2NodeType = typeof oas2NodeTypesList[number];
143
+
144
+ const oas3NodeTypesList = [
102
145
  'Root',
103
146
  'Tag',
104
147
  'TagList',
@@ -153,12 +196,33 @@ const nodeTypesList = [
153
196
  'AuthorizationCode',
154
197
  'OAuth2Flows',
155
198
  'SecurityScheme',
199
+ 'TagGroup',
200
+ 'TagGroups',
201
+ 'EnumDescriptions',
202
+ 'Logo',
156
203
  'XCodeSample',
157
204
  'XCodeSampleList',
205
+ 'XUsePkce',
158
206
  'WebhooksMap',
159
- 'SpecExtension',
160
- 'Message',
161
- ];
207
+ ] as const;
208
+
209
+ export type Oas3NodeType = typeof oas3NodeTypesList[number];
210
+
211
+ const oas3_1NodeTypesList = [
212
+ 'Root',
213
+ 'Schema',
214
+ 'SchemaProperties',
215
+ 'Info',
216
+ 'License',
217
+ 'Components',
218
+ 'NamedPathItems',
219
+ 'SecurityScheme',
220
+ 'Operation',
221
+ ] as const;
222
+
223
+ export type Oas3_1NodeType = typeof oas3_1NodeTypesList[number];
224
+
225
+ const asyncNodeTypesList = ['Message'] as const;
162
226
 
163
227
  const ConfigStyleguide: NodeType = {
164
228
  properties: {
@@ -186,22 +250,13 @@ const ConfigStyleguide: NodeType = {
186
250
  },
187
251
  };
188
252
 
189
- const RootConfigStyleguide: NodeType = {
253
+ const createConfigRoot = (nodeTypes: Record<string, NodeType>): NodeType => ({
254
+ ...nodeTypes.rootRedoclyConfigSchema,
190
255
  properties: {
191
- plugins: {
192
- type: 'array',
193
- items: { type: 'string' },
194
- },
256
+ ...nodeTypes.rootRedoclyConfigSchema.properties,
195
257
  ...ConfigStyleguide.properties,
196
- },
197
- };
198
-
199
- const ConfigRoot: NodeType = {
200
- properties: {
201
- ...rootRedoclyConfigSchema.properties,
202
- ...RootConfigStyleguide.properties,
203
- apis: 'ConfigApis',
204
- theme: 'ConfigRootTheme',
258
+ apis: 'ConfigApis', // Override apis with internal format
259
+ theme: 'ConfigRootTheme', // Override theme with internal format
205
260
  'features.openapi': 'ConfigReferenceDocs', // deprecated
206
261
  'features.mockServer': 'ConfigMockServer', // deprecated
207
262
  organization: { type: 'string' },
@@ -220,17 +275,17 @@ const ConfigRoot: NodeType = {
220
275
  },
221
276
  },
222
277
  },
223
- };
278
+ });
224
279
 
225
280
  const ConfigApis: NodeType = {
226
281
  properties: {},
227
282
  additionalProperties: 'ConfigApisProperties',
228
283
  };
229
284
 
230
- const ConfigApisProperties: NodeType = {
285
+ const createConfigApisProperties = (nodeTypes: Record<string, NodeType>): NodeType => ({
286
+ ...nodeTypes['rootRedoclyConfigSchema.apis_additionalProperties'],
231
287
  properties: {
232
- ...apiConfigSchema.properties,
233
- root: { type: 'string' },
288
+ ...nodeTypes['rootRedoclyConfigSchema.apis_additionalProperties']?.properties,
234
289
  labels: {
235
290
  type: 'array',
236
291
  items: {
@@ -240,7 +295,6 @@ const ConfigApisProperties: NodeType = {
240
295
  ...ConfigStyleguide.properties,
241
296
  'features.openapi': 'ConfigReferenceDocs', // deprecated
242
297
  'features.mockServer': 'ConfigMockServer', // deprecated
243
- theme: 'ConfigRootTheme',
244
298
  files: {
245
299
  type: 'array',
246
300
  items: {
@@ -248,8 +302,7 @@ const ConfigApisProperties: NodeType = {
248
302
  },
249
303
  },
250
304
  },
251
- required: ['root'],
252
- };
305
+ });
253
306
 
254
307
  const ConfigHTTP: NodeType = {
255
308
  properties: {
@@ -262,13 +315,13 @@ const ConfigHTTP: NodeType = {
262
315
  },
263
316
  };
264
317
 
265
- const ConfigRootTheme: NodeType = {
318
+ const createConfigRootTheme = (nodeTypes: Record<string, NodeType>): NodeType => ({
319
+ ...nodeTypes['rootRedoclyConfigSchema.theme'],
266
320
  properties: {
267
- ...themeConfigSchema.properties,
268
- openapi: 'ConfigReferenceDocs',
269
- mockServer: 'ConfigMockServer',
321
+ ...nodeTypes['rootRedoclyConfigSchema.theme']?.properties,
322
+ openapi: 'ConfigReferenceDocs', // Override theme.openapi with internal format
270
323
  },
271
- };
324
+ });
272
325
 
273
326
  const Rules: NodeType = {
274
327
  properties: {},
@@ -302,7 +355,18 @@ const ObjectRule: NodeType = {
302
355
 
303
356
  const AssertionDefinitionSubject: NodeType = {
304
357
  properties: {
305
- type: { enum: nodeTypesList },
358
+ type: {
359
+ enum: [
360
+ ...new Set([
361
+ 'any',
362
+ ...oas2NodeTypesList,
363
+ ...oas3NodeTypesList,
364
+ ...oas3_1NodeTypesList,
365
+ ...asyncNodeTypesList,
366
+ 'SpecExtension',
367
+ ]),
368
+ ],
369
+ },
306
370
  property: (value: unknown) => {
307
371
  if (Array.isArray(value)) {
308
372
  return { type: 'array', items: { type: 'string' } };
@@ -863,8 +927,9 @@ const GenerateCodeSamples: NodeType = {
863
927
  };
864
928
 
865
929
  const ConfigReferenceDocs: NodeType = {
930
+ // TODO: partially invalid @Viacheslav
866
931
  properties: {
867
- theme: 'ConfigTheme',
932
+ theme: 'ConfigTheme', // TODO: deprecated @Viacheslav
868
933
  corsProxyUrl: { type: 'string' },
869
934
  ctrlFHijack: { type: 'boolean' },
870
935
  defaultSampleLanguage: { type: 'string' },
@@ -995,12 +1060,22 @@ const ConfigMockServer: NodeType = {
995
1060
  },
996
1061
  };
997
1062
 
998
- export const ConfigTypes: Record<string, NodeType> = {
1063
+ export const createConfigTypes = (extraSchemas: JSONSchema) => {
1064
+ // Create types based on external schemas
1065
+ const nodeTypes = getNodeTypesFromJSONSchema('rootRedoclyConfigSchema', extraSchemas);
1066
+
1067
+ return {
1068
+ ...CoreConfigTypes,
1069
+ ConfigRoot: createConfigRoot(nodeTypes),
1070
+ ConfigApisProperties: createConfigApisProperties(nodeTypes),
1071
+ ConfigRootTheme: createConfigRootTheme(nodeTypes),
1072
+ ...nodeTypes,
1073
+ };
1074
+ };
1075
+
1076
+ const CoreConfigTypes: Record<string, NodeType> = {
999
1077
  Assert,
1000
- ConfigRoot,
1001
1078
  ConfigApis,
1002
- ConfigApisProperties,
1003
- RootConfigStyleguide,
1004
1079
  ConfigStyleguide,
1005
1080
  ConfigReferenceDocs,
1006
1081
  ConfigMockServer,
@@ -1010,7 +1085,6 @@ export const ConfigTypes: Record<string, NodeType> = {
1010
1085
  ConfigSidebarLinks,
1011
1086
  CommonConfigSidebarLinks,
1012
1087
  ConfigTheme,
1013
- ConfigRootTheme,
1014
1088
  AssertDefinition,
1015
1089
  ThemeColors,
1016
1090
  CommonThemeColors,
@@ -1060,5 +1134,6 @@ export const ConfigTypes: Record<string, NodeType> = {
1060
1134
  Typography,
1061
1135
  AssertionDefinitionAssertions,
1062
1136
  AssertionDefinitionSubject,
1063
- ...PortalConfigNodeTypes,
1064
1137
  };
1138
+
1139
+ export const ConfigTypes: Record<string, NodeType> = createConfigTypes(rootRedoclyConfigSchema);
@@ -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
@@ -5,9 +5,10 @@ import fetch from 'node-fetch';
5
5
  import * as pluralize from 'pluralize';
6
6
  import { parseYaml } from './js-yaml';
7
7
  import { UserContext } from './walk';
8
- import { HttpResolveConfig } from './config';
9
8
  import { env } from './env';
10
9
  import { logger, colorize } from './logger';
10
+ import { HttpResolveConfig } from './config';
11
+ import { HttpsProxyAgent } from 'https-proxy-agent';
11
12
 
12
13
  export { parseYaml, stringifyYaml } from './js-yaml';
13
14
 
@@ -37,11 +38,11 @@ export function isDefined<T>(x: T | undefined): x is T {
37
38
  return x !== undefined;
38
39
  }
39
40
 
40
- export function isPlainObject(value: any): value is object {
41
+ export function isPlainObject(value: any): value is Record<string, unknown> {
41
42
  return value !== null && typeof value === 'object' && !Array.isArray(value);
42
43
  }
43
44
 
44
- export function isEmptyObject(value: any): value is object {
45
+ export function isEmptyObject(value: any): value is Record<string, unknown> {
45
46
  return isPlainObject(value) && Object.keys(value).length === 0;
46
47
  }
47
48
 
@@ -274,3 +275,8 @@ export function nextTick() {
274
275
  function getUpdatedFieldName(updatedField: string, updatedObject?: string) {
275
276
  return `${typeof updatedObject !== 'undefined' ? `${updatedObject}.` : ''}${updatedField}`;
276
277
  }
278
+
279
+ export function getProxyAgent() {
280
+ const proxy = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
281
+ return proxy ? new HttpsProxyAgent(proxy) : undefined;
282
+ }
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) {