@redocly/openapi-core 1.0.0-beta.61 → 1.0.0-beta.65

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 (47) hide show
  1. package/__tests__/lint.test.ts +17 -0
  2. package/__tests__/resolve.test.ts +10 -2
  3. package/__tests__/utils.ts +3 -5
  4. package/lib/benchmark/utils.js +2 -2
  5. package/lib/config/config.d.ts +1 -0
  6. package/lib/config/config.js +3 -3
  7. package/lib/index.d.ts +1 -0
  8. package/lib/index.js +4 -1
  9. package/lib/js-yaml/index.d.ts +3 -0
  10. package/lib/js-yaml/index.js +19 -0
  11. package/lib/oas-types.js +3 -0
  12. package/lib/resolve.d.ts +1 -1
  13. package/lib/resolve.js +3 -4
  14. package/lib/rules/builtin.d.ts +6 -0
  15. package/lib/rules/common/info-description-override.d.ts +2 -0
  16. package/lib/rules/common/info-description-override.js +24 -0
  17. package/lib/rules/common/operation-description-override.d.ts +2 -0
  18. package/lib/rules/common/operation-description-override.js +29 -0
  19. package/lib/rules/common/tag-description-override.d.ts +2 -0
  20. package/lib/rules/common/tag-description-override.js +25 -0
  21. package/lib/rules/oas2/index.d.ts +3 -0
  22. package/lib/rules/oas2/index.js +6 -0
  23. package/lib/rules/oas3/index.d.ts +3 -0
  24. package/lib/rules/oas3/index.js +7 -1
  25. package/lib/types/redocly-yaml.js +332 -21
  26. package/lib/utils.d.ts +5 -1
  27. package/lib/utils.js +18 -3
  28. package/package.json +3 -3
  29. package/src/__tests__/js-yaml.test.ts +47 -0
  30. package/src/__tests__/lint.test.ts +13 -0
  31. package/src/__tests__/utils.test.ts +56 -0
  32. package/src/benchmark/utils.ts +2 -2
  33. package/src/config/config.ts +4 -3
  34. package/src/index.ts +2 -0
  35. package/src/js-yaml/index.ts +19 -0
  36. package/src/oas-types.ts +4 -0
  37. package/src/resolve.ts +5 -5
  38. package/src/rules/__tests__/no-unresolved-refs.test.ts +2 -2
  39. package/src/rules/common/info-description-override.ts +24 -0
  40. package/src/rules/common/operation-description-override.ts +30 -0
  41. package/src/rules/common/tag-description-override.ts +25 -0
  42. package/src/rules/oas2/index.ts +6 -0
  43. package/src/rules/oas3/index.ts +8 -3
  44. package/src/types/redocly-yaml.ts +434 -22
  45. package/src/typings/swagger.ts +0 -1
  46. package/src/utils.ts +27 -3
  47. package/tsconfig.tsbuildinfo +1 -1
@@ -1,11 +1,12 @@
1
1
  import { NodeType, listOf } from '.';
2
+ import { omitObjectProps, pickObjectProps } from '../utils';
2
3
 
3
4
  const ConfigRoot: NodeType = {
4
5
  properties: {
5
6
  apiDefinitions: {
6
7
  type: 'object',
7
8
  properties: {},
8
- additionalProperties: { properties: { type: 'string' } }
9
+ additionalProperties: { properties: { type: 'string' } },
9
10
  },
10
11
  lint: 'ConfigLint',
11
12
  referenceDocs: 'ConfigReferenceDocs',
@@ -91,25 +92,398 @@ const ConfigSidebarLinks: NodeType = {
91
92
  },
92
93
  };
93
94
 
95
+ const CommonThemeColors: NodeType = {
96
+ properties: {
97
+ main: { type: 'string' },
98
+ light: { type: 'string' },
99
+ dark: { type: 'string' },
100
+ contrastText: { type: 'string' },
101
+ },
102
+ };
103
+
104
+ const CommonColorProps: NodeType = {
105
+ properties: {
106
+ backgroundColor: { type: 'string' },
107
+ borderColor: { type: 'string' },
108
+ color: { type: 'string' },
109
+ tabTextColor: { type: 'string' },
110
+ },
111
+ };
112
+
113
+ const BorderThemeColors: NodeType = {
114
+ properties: pickObjectProps(CommonThemeColors.properties, ['light', 'dark']),
115
+ };
116
+
117
+ const HttpColors: NodeType = {
118
+ properties: {
119
+ basic: { type: 'string' },
120
+ delete: { type: 'string' },
121
+ get: { type: 'string' },
122
+ head: { type: 'string' },
123
+ link: { type: 'string' },
124
+ options: { type: 'string' },
125
+ patch: { type: 'string' },
126
+ post: { type: 'string' },
127
+ put: { type: 'string' },
128
+ },
129
+ };
130
+
131
+ const ResponseColors: NodeType = {
132
+ properties: {
133
+ errors: 'CommonColorProps',
134
+ info: 'CommonColorProps',
135
+ redirect: 'CommonColorProps',
136
+ success: 'CommonColorProps',
137
+ },
138
+ };
139
+
140
+ const SecondaryColors: NodeType = {
141
+ properties: omitObjectProps(CommonThemeColors.properties, ['dark']),
142
+ };
143
+
144
+ const TextThemeColors: NodeType = {
145
+ properties: {
146
+ primary: { type: 'string' },
147
+ secondary: { type: 'string' },
148
+ light: { type: 'string' },
149
+ },
150
+ };
151
+
152
+ const ThemeColors: NodeType = {
153
+ properties: {
154
+ accent: 'CommonThemeColors',
155
+ border: 'BorderThemeColors',
156
+ error: 'CommonThemeColors',
157
+ http: 'HttpColors',
158
+ primary: 'CommonThemeColors',
159
+ responses: 'ResponseColors',
160
+ secondary: 'SecondaryColors',
161
+ success: 'CommonThemeColors',
162
+ text: 'TextThemeColors',
163
+ tonalOffset: { type: 'number' },
164
+ warning: 'CommonThemeColors',
165
+ },
166
+ };
167
+
168
+ const SizeProps: NodeType = {
169
+ properties: {
170
+ fontSize: { type: 'string' },
171
+ padding: { type: 'string' },
172
+ minWidth: { type: 'string' },
173
+ },
174
+ };
175
+
176
+ const Sizes: NodeType = {
177
+ properties: {
178
+ small: 'SizeProps',
179
+ medium: 'SizeProps',
180
+ large: 'SizeProps',
181
+ xlarge: 'SizeProps',
182
+ },
183
+ };
184
+
185
+ const FontConfig: NodeType = {
186
+ properties: {
187
+ fontFamily: { type: 'string' },
188
+ fontSize: { type: 'string' },
189
+ fontWeight: { type: 'string' },
190
+ lineHeight: { type: 'string' },
191
+ },
192
+ };
193
+
194
+ const ButtonsConfig: NodeType = {
195
+ properties: {
196
+ ...omitObjectProps(FontConfig.properties, ['fontSize', 'lineHeight']),
197
+ borderRadius: { type: 'string' },
198
+ hoverStyle: { type: 'string' },
199
+ boxShadow: { type: 'string' },
200
+ hoverBoxShadow: { type: 'string' },
201
+ sizes: 'Sizes',
202
+ },
203
+ };
204
+
205
+ const BadgeFontConfig: NodeType = {
206
+ properties: pickObjectProps(FontConfig.properties, ['fontSize', 'lineHeight']),
207
+ };
208
+
209
+ const BadgeSizes: NodeType = {
210
+ properties: {
211
+ medium: 'BadgeFontConfig',
212
+ small: 'BadgeFontConfig',
213
+ },
214
+ };
215
+
216
+ const HttpBadgesConfig: NodeType = {
217
+ properties: {
218
+ ...omitObjectProps(FontConfig.properties, ['fontSize', 'lineHeight']),
219
+ borderRadius: { type: 'string' },
220
+ color: { type: 'string' },
221
+ sizes: 'BadgeSizes',
222
+ },
223
+ };
224
+
225
+ const LabelControls: NodeType = {
226
+ properties: {
227
+ top: { type: 'string' },
228
+ },
229
+ };
230
+
231
+ const Panels: NodeType = {
232
+ properties: {
233
+ borderRadius: { type: 'string' },
234
+ },
235
+ };
236
+
237
+ const TryItButton: NodeType = {
238
+ properties: {
239
+ fullWidth: { type: 'boolean' },
240
+ },
241
+ };
242
+
243
+ const Components: NodeType = {
244
+ properties: {
245
+ buttons: 'ButtonsConfig',
246
+ httpBadges: 'HttpBadgesConfig',
247
+ layoutControls: 'LabelControls',
248
+ panels: 'Panels',
249
+ tryItButton: 'TryItButton',
250
+ tryItSendButton: 'TryItButton',
251
+ },
252
+ };
253
+
254
+ const Breakpoints: NodeType = {
255
+ properties: {
256
+ small: { type: 'string' },
257
+ medium: { type: 'string' },
258
+ large: { type: 'string' },
259
+ },
260
+ };
261
+
262
+ const StackedConfig: NodeType = {
263
+ properties: {
264
+ maxWidth: 'Breakpoints',
265
+ },
266
+ };
267
+
268
+ const ThreePanelConfig: NodeType = {
269
+ properties: {
270
+ maxWidth: 'Breakpoints',
271
+ },
272
+ };
273
+
274
+ const Layout: NodeType = {
275
+ properties: {
276
+ showDarkRightPanel: { type: 'boolean' },
277
+ stacked: 'StackedConfig',
278
+ 'three-panel': 'ThreePanelConfig',
279
+ },
280
+ };
281
+
282
+ const SchemaColorsConfig: NodeType = {
283
+ properties: {
284
+ backgroundColor: { type: 'string' },
285
+ border: { type: 'string' },
286
+ },
287
+ };
288
+
289
+ const Schema: NodeType = {
290
+ properties: {
291
+ breakFieldNames: { type: 'boolean' },
292
+ caretColor: { type: 'string' },
293
+ caretSize: { type: 'string' },
294
+ constraints: 'SchemaColorsConfig',
295
+ defaultDetailsWidth: { type: 'string' },
296
+ examples: 'SchemaColorsConfig',
297
+ labelsTextSize: { type: 'string' },
298
+ linesColor: { type: 'string' },
299
+ nestedBackground: { type: 'string' },
300
+ nestingSpacing: { type: 'string' },
301
+ requireLabelColor: { type: 'string' },
302
+ typeNameColor: { type: 'string' },
303
+ typeTitleColor: { type: 'string' },
304
+ },
305
+ };
306
+
307
+ const GroupItemsConfig: NodeType = {
308
+ properties: {
309
+ subItemsColor: { type: 'string' },
310
+ textTransform: { type: 'string' },
311
+ fontWeight: { type: 'string' },
312
+ },
313
+ };
314
+
315
+ const Level1Items: NodeType = {
316
+ properties: pickObjectProps(GroupItemsConfig.properties, ['textTransform']),
317
+ };
318
+
319
+ const SpacingConfig: NodeType = {
320
+ properties: {
321
+ unit: { type: 'number' },
322
+ paddingHorizontal: { type: 'string' },
323
+ paddingVertical: { type: 'string' },
324
+ offsetTop: { type: 'string' },
325
+ offsetLeft: { type: 'string' },
326
+ offsetNesting: { type: 'string' },
327
+ },
328
+ };
329
+
330
+ const Sidebar: NodeType = {
331
+ properties: {
332
+ ...omitObjectProps(FontConfig.properties, ['fontWeight', 'lineHeight']),
333
+ activeBgColor: { type: 'string' },
334
+ activeTextColor: { type: 'string' },
335
+ backgroundColor: { type: 'string' },
336
+ borderRadius: { type: 'string' },
337
+ breakPath: { type: 'boolean' },
338
+ caretColor: { type: 'string' },
339
+ caretSize: { type: 'string' },
340
+ groupItems: 'GroupItemsConfig',
341
+ level1items: 'Level1Items',
342
+ rightLineColor: { type: 'string' },
343
+ separatorLabelColor: { type: 'string' },
344
+ showAtBreakpoint: { type: 'string' },
345
+ spacing: 'SpacingConfig',
346
+ textColor: { type: 'string' },
347
+ width: { type: 'string' },
348
+ },
349
+ };
350
+
351
+ const Heading: NodeType = {
352
+ properties: {
353
+ ...FontConfig.properties,
354
+ color: { type: 'string' },
355
+ transform: { type: 'string' },
356
+ },
357
+ };
358
+
359
+ const CodeConfig: NodeType = {
360
+ properties: {
361
+ ...FontConfig.properties,
362
+ backgroundColor: { type: 'string' },
363
+ color: { type: 'string' },
364
+ wordBreak: { type: 'string' },
365
+ wrap: { type: 'boolean' },
366
+ },
367
+ };
368
+
369
+ const HeadingsConfig: NodeType = {
370
+ properties: omitObjectProps(FontConfig.properties, ['fontSize']),
371
+ };
372
+
373
+ const LinksConfig: NodeType = {
374
+ properties: {
375
+ color: { type: 'string' },
376
+ hover: { type: 'string' },
377
+ textDecoration: { type: 'string' },
378
+ visited: { type: 'string' },
379
+ },
380
+ };
381
+
382
+ const Typography: NodeType = {
383
+ properties: {
384
+ code: 'CodeConfig',
385
+ fieldName: 'FontConfig',
386
+ ...pickObjectProps(FontConfig.properties, ['fontSize', 'fontFamily']),
387
+ fontWeightBold: { type: 'string' },
388
+ fontWeightLight: { type: 'string' },
389
+ fontWeightRegular: { type: 'string' },
390
+ heading1: 'Heading',
391
+ heading2: 'Heading',
392
+ heading3: 'Heading',
393
+ headings: 'HeadingsConfig',
394
+ lineHeight: { type: 'string' },
395
+ links: 'LinksConfig',
396
+ optimizeSpeed: { type: 'boolean' },
397
+ rightPanelHeading: 'Heading',
398
+ smoothing: { type: 'string' },
399
+ },
400
+ };
401
+
402
+ const TokenProps: NodeType = {
403
+ properties: {
404
+ color: { type: 'string' },
405
+ ...omitObjectProps(FontConfig.properties, ['fontWeight']),
406
+ },
407
+ };
408
+
409
+ const CodeBlock: NodeType = {
410
+ properties: {
411
+ backgroundColor: { type: 'string' },
412
+ borderRadius: { type: 'string' },
413
+ tokens: 'TokenProps',
414
+ },
415
+ };
416
+
417
+ const Logo: NodeType = {
418
+ properties: {
419
+ gutter: { type: 'string' },
420
+ maxHeight: { type: 'string' },
421
+ maxWidth: { type: 'string' },
422
+ },
423
+ };
424
+
425
+ const ButtonOverrides: NodeType = {
426
+ properties: {
427
+ custom: { type: 'string' },
428
+ },
429
+ };
430
+
431
+ const Overrides: NodeType = {
432
+ properties: {
433
+ DownloadButton: 'ButtonOverrides',
434
+ NextSectionButton: 'ButtonOverrides',
435
+ },
436
+ };
437
+
438
+ const RightPanel: NodeType = {
439
+ properties: {
440
+ backgroundColor: { type: 'string' },
441
+ panelBackgroundColor: { type: 'string' },
442
+ panelControlsBackgroundColor: { type: 'string' },
443
+ showAtBreakpoint: { type: 'string' },
444
+ textColor: { type: 'string' },
445
+ width: { type: 'string' },
446
+ },
447
+ };
448
+
449
+ const Shape: NodeType = {
450
+ properties: { borderRadius: { type: 'string' } },
451
+ };
452
+
453
+ const ThemeSpacing: NodeType = {
454
+ properties: {
455
+ sectionHorizontal: { type: 'number' },
456
+ sectionVertical: { type: 'number' },
457
+ unit: { type: 'number' },
458
+ },
459
+ };
460
+
94
461
  const ConfigTheme: NodeType = {
95
462
  properties: {
96
- breakpoints: { type: 'object', additionalProperties: { type: 'string' } },
97
- codeBlock: { type: 'object', additionalProperties: { type: 'string' } },
98
- colors: { type: 'object', additionalProperties: { type: 'string' } },
99
- components: { type: 'object', additionalProperties: { type: 'string' } },
100
- layout: { type: 'object', additionalProperties: { type: 'string' } },
101
- logo: { type: 'object', additionalProperties: { type: 'string' } },
102
- overrides: { type: 'object', additionalProperties: { type: 'string' } },
103
- rightPanel: { type: 'object', additionalProperties: { type: 'string' } },
104
- schema: { type: 'object', additionalProperties: { type: 'string' } },
105
- shape: { type: 'object', additionalProperties: { type: 'string' } },
106
- sidebar: { type: 'object', additionalProperties: { type: 'string' } },
107
- spacing: { type: 'object', additionalProperties: { type: 'string' } },
108
- typography: { type: 'object', additionalProperties: { type: 'string' } },
463
+ breakpoints: 'Breakpoints',
464
+ codeBlock: 'CodeBlock',
465
+ colors: 'ThemeColors',
466
+ components: 'Components',
467
+ layout: 'Layout',
468
+ logo: 'Logo',
469
+ overrides: 'Overrides',
470
+ rightPanel: 'RightPanel',
471
+ schema: 'Schema',
472
+ shape: 'Shape',
473
+ sidebar: 'Sidebar',
474
+ spacing: 'ThemeSpacing',
475
+ typography: 'Typography',
109
476
  links: { properties: { color: { type: 'string' } } },
110
477
  codeSample: { properties: { backgroundColor: { type: 'string' } } },
111
478
  },
112
- }
479
+ };
480
+
481
+ const GenerateCodeSamples: NodeType = {
482
+ properties: {
483
+ skipOptionalParameters: { type: 'boolean' },
484
+ languages: listOf('ConfigLanguage'),
485
+ },
486
+ };
113
487
 
114
488
  const ConfigReferenceDocs: NodeType = {
115
489
  properties: {
@@ -124,12 +498,7 @@ const ConfigReferenceDocs: NodeType = {
124
498
  expandDefaultServerVariables: { type: 'boolean' },
125
499
  expandResponses: { type: 'string' },
126
500
  expandSingleSchemaField: { type: 'boolean' },
127
- generateCodeSamples: {
128
- properties: {
129
- skipOptionalParameters: { type: 'boolean' },
130
- languages: listOf('ConfigLanguage'),
131
- },
132
- },
501
+ generateCodeSamples: 'GenerateCodeSamples',
133
502
  generatedPayloadSamplesMaxDepth: { type: 'number' },
134
503
  hideDownloadButton: { type: 'boolean' },
135
504
  hideHostname: { type: 'boolean' },
@@ -143,7 +512,7 @@ const ConfigReferenceDocs: NodeType = {
143
512
  htmlTemplate: { type: 'string' },
144
513
  jsonSampleExpandLevel: { type: 'string' },
145
514
  labels: 'ConfigLabels',
146
- layout: { type: 'object' },
515
+ layout: { type: 'string' },
147
516
  maxDisplayedEnumValues: { type: 'number' },
148
517
  menuToggle: { type: 'boolean' },
149
518
  nativeScrollbars: { type: 'boolean' },
@@ -192,4 +561,47 @@ export const ConfigTypes: Record<string, NodeType> = {
192
561
  ConfigLabels,
193
562
  ConfigSidebarLinks,
194
563
  ConfigTheme,
564
+ ThemeColors,
565
+ CommonThemeColors,
566
+ BorderThemeColors,
567
+ HttpColors,
568
+ ResponseColors,
569
+ SecondaryColors,
570
+ TextThemeColors,
571
+ Sizes,
572
+ ButtonsConfig,
573
+ CommonColorProps,
574
+ BadgeFontConfig,
575
+ BadgeSizes,
576
+ HttpBadgesConfig,
577
+ LabelControls,
578
+ Panels,
579
+ TryItButton,
580
+ Breakpoints,
581
+ StackedConfig,
582
+ ThreePanelConfig,
583
+ SchemaColorsConfig,
584
+ SizeProps,
585
+ Level1Items,
586
+ SpacingConfig,
587
+ FontConfig,
588
+ CodeConfig,
589
+ HeadingsConfig,
590
+ LinksConfig,
591
+ TokenProps,
592
+ CodeBlock,
593
+ Logo,
594
+ ButtonOverrides,
595
+ Overrides,
596
+ RightPanel,
597
+ Shape,
598
+ ThemeSpacing,
599
+ GenerateCodeSamples,
600
+ GroupItemsConfig,
601
+ Components,
602
+ Layout,
603
+ Schema,
604
+ Sidebar,
605
+ Heading,
606
+ Typography,
195
607
  };
@@ -1,5 +1,4 @@
1
1
  import { Referenced } from './openapi';
2
- //@ts-ignore
3
2
  import { Schema } from 'js-yaml';
4
3
 
5
4
  export interface Oas2Definition {
package/src/utils.ts CHANGED
@@ -1,9 +1,12 @@
1
- import * as yaml from 'js-yaml';
2
1
  import * as fs from 'fs';
3
2
  import * as minimatch from 'minimatch';
4
3
  import fetch from 'node-fetch';
4
+
5
+ import { parseYaml } from './js-yaml';
5
6
  import { HttpResolveConfig } from './config/config';
6
7
 
8
+ export { parseYaml, stringifyYaml } from './js-yaml';
9
+
7
10
  export type StackFrame<T> = {
8
11
  prev: StackFrame<T> | null;
9
12
  value: T;
@@ -23,7 +26,8 @@ export type BundleOutputFormat = 'json' | 'yml' | 'yaml';
23
26
 
24
27
  export async function loadYaml(filename: string) {
25
28
  const contents = await fs.promises.readFile(filename, 'utf-8');
26
- return yaml.safeLoad(contents);
29
+
30
+ return parseYaml(contents);
27
31
  }
28
32
 
29
33
  export function notUndefined<T>(x: T | undefined): x is T {
@@ -60,4 +64,24 @@ export function match(url: string, pattern: string) {
60
64
  url = url.replace(/^https?:\/\//, '');
61
65
  }
62
66
  return minimatch(url, pattern);
63
- }
67
+ }
68
+
69
+ export function pickObjectProps<T extends Record<string, unknown>>(
70
+ object: T,
71
+ keys: Array<string>,
72
+ ): T {
73
+ return Object.fromEntries(
74
+ keys.filter((key: string) => key in object).map((key: string) => [key, object[key]]),
75
+ ) as T;
76
+ }
77
+
78
+ export function omitObjectProps<T extends Record<string, unknown>>(
79
+ object: T,
80
+ keys: Array<string>,
81
+ ): T {
82
+ return Object.fromEntries(Object.entries(object).filter(([key]) => !keys.includes(key))) as T;
83
+ }
84
+
85
+ export function readFileAsStringSync(filePath: string) {
86
+ return fs.readFileSync(filePath, 'utf-8');
87
+ }