@redocly/openapi-core 1.0.2 → 1.2.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 (80) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/lib/bundle.d.ts +2 -2
  3. package/lib/bundle.js +24 -22
  4. package/lib/config/builtIn.js +4 -0
  5. package/lib/config/config-resolvers.js +19 -6
  6. package/lib/config/config.d.ts +9 -9
  7. package/lib/config/config.js +32 -17
  8. package/lib/config/rules.d.ts +2 -2
  9. package/lib/config/types.d.ts +9 -3
  10. package/lib/format/codeframes.d.ts +1 -1
  11. package/lib/index.d.ts +1 -1
  12. package/lib/index.js +7 -6
  13. package/lib/lint.js +10 -16
  14. package/lib/oas-types.d.ts +16 -10
  15. package/lib/oas-types.js +52 -26
  16. package/lib/rules/async2/channels-kebab-case.d.ts +2 -0
  17. package/lib/rules/async2/channels-kebab-case.js +19 -0
  18. package/lib/rules/async2/index.d.ts +12 -0
  19. package/lib/rules/async2/index.js +22 -0
  20. package/lib/rules/async2/no-channel-trailing-slash.d.ts +2 -0
  21. package/lib/rules/async2/no-channel-trailing-slash.js +16 -0
  22. package/lib/rules/common/no-path-trailing-slash.js +2 -2
  23. package/lib/rules/common/scalar-property-missing-example.js +1 -1
  24. package/lib/rules/common/spec.d.ts +2 -2
  25. package/lib/rules/common/spec.js +3 -3
  26. package/lib/rules/common/tags-alphabetical.js +5 -2
  27. package/lib/rules/oas2/index.js +1 -1
  28. package/lib/rules/oas2/remove-unused-components.js +4 -1
  29. package/lib/rules/oas3/index.js +1 -1
  30. package/lib/rules/oas3/remove-unused-components.js +4 -1
  31. package/lib/rules/utils.d.ts +1 -1
  32. package/lib/types/asyncapi.d.ts +2 -0
  33. package/lib/types/asyncapi.js +1027 -0
  34. package/lib/types/portal-config-schema.d.ts +2533 -0
  35. package/lib/types/portal-config-schema.js +304 -0
  36. package/lib/types/redocly-yaml.js +26 -20
  37. package/lib/types/{config-external-schemas.d.ts → theme-config.d.ts} +140 -575
  38. package/lib/types/{config-external-schemas.js → theme-config.js} +55 -261
  39. package/lib/typings/asyncapi.d.ts +21 -0
  40. package/lib/typings/asyncapi.js +2 -0
  41. package/lib/visitors.d.ts +12 -0
  42. package/lib/walk.d.ts +3 -3
  43. package/package.json +3 -2
  44. package/src/__tests__/lint.test.ts +38 -6
  45. package/src/bundle.ts +27 -28
  46. package/src/config/__tests__/__snapshots__/config.test.ts.snap +24 -0
  47. package/src/config/__tests__/config.test.ts +15 -4
  48. package/src/config/builtIn.ts +4 -0
  49. package/src/config/config-resolvers.ts +25 -6
  50. package/src/config/config.ts +51 -27
  51. package/src/config/rules.ts +2 -2
  52. package/src/config/types.ts +14 -4
  53. package/src/index.ts +7 -1
  54. package/src/lint.ts +13 -22
  55. package/src/oas-types.ts +59 -21
  56. package/src/rules/async2/__tests__/channels-kebab-case.test.ts +141 -0
  57. package/src/rules/async2/__tests__/no-channel-trailing-slash.test.ts +97 -0
  58. package/src/rules/async2/channels-kebab-case.ts +18 -0
  59. package/src/rules/async2/index.ts +22 -0
  60. package/src/rules/async2/no-channel-trailing-slash.ts +15 -0
  61. package/src/rules/common/__tests__/no-path-trailing-slash.test.ts +41 -0
  62. package/src/rules/common/__tests__/tags-alphabetical.test.ts +58 -0
  63. package/src/rules/common/no-path-trailing-slash.ts +2 -2
  64. package/src/rules/common/scalar-property-missing-example.ts +2 -2
  65. package/src/rules/common/spec.ts +2 -2
  66. package/src/rules/common/tags-alphabetical.ts +8 -4
  67. package/src/rules/oas2/__tests__/remove-unused-components.test.ts +155 -0
  68. package/src/rules/oas2/index.ts +2 -2
  69. package/src/rules/oas2/remove-unused-components.ts +6 -1
  70. package/src/rules/oas3/__tests__/remove-unused-components.test.ts +171 -0
  71. package/src/rules/oas3/index.ts +2 -2
  72. package/src/rules/oas3/remove-unused-components.ts +6 -1
  73. package/src/types/asyncapi.ts +1136 -0
  74. package/src/types/portal-config-schema.ts +343 -0
  75. package/src/types/redocly-yaml.ts +23 -34
  76. package/src/types/{config-external-schemas.ts → theme-config.ts} +60 -294
  77. package/src/typings/asyncapi.ts +26 -0
  78. package/src/visitors.ts +22 -0
  79. package/src/walk.ts +3 -3
  80. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,343 @@
1
+ import {
2
+ ApigeeDevOnboardingIntegrationAuthType,
3
+ AuthProviderType,
4
+ DEFAULT_TEAM_CLAIM_NAME,
5
+ } from '../config';
6
+
7
+ const oidcIssuerMetadataSchema = {
8
+ type: 'object',
9
+ properties: {
10
+ end_session_endpoint: { type: 'string' },
11
+ token_endpoint: { type: 'string' },
12
+ authorization_endpoint: { type: 'string' },
13
+ jwks_uri: { type: 'string' },
14
+ },
15
+ required: ['token_endpoint', 'authorization_endpoint'],
16
+ additionalProperties: true,
17
+ } as const;
18
+
19
+ const oidcProviderConfigSchema = {
20
+ type: 'object',
21
+ properties: {
22
+ type: { type: 'string', const: AuthProviderType.OIDC },
23
+ title: { type: 'string' },
24
+ configurationUrl: { type: 'string', minLength: 1 },
25
+ configuration: oidcIssuerMetadataSchema,
26
+ clientId: { type: 'string', minLength: 1 },
27
+ clientSecret: { type: 'string', minLength: 1 },
28
+ teamsClaimName: { type: 'string' },
29
+ teamsClaimMap: { type: 'object', additionalProperties: { type: 'string' } },
30
+ defaultTeams: { type: 'array', items: { type: 'string' } },
31
+ scopes: { type: 'array', items: { type: 'string' } },
32
+ tokenExpirationTime: { type: 'number' },
33
+ authorizationRequestCustomParams: { type: 'object', additionalProperties: { type: 'string' } },
34
+ tokenRequestCustomParams: { type: 'object', additionalProperties: { type: 'string' } },
35
+ audience: { type: 'array', items: { type: 'string' } },
36
+ },
37
+ required: ['type', 'clientId', 'clientSecret'],
38
+ oneOf: [{ required: ['configurationUrl'] }, { required: ['configuration'] }],
39
+ additionalProperties: false,
40
+ } as const;
41
+
42
+ const saml2ProviderConfigSchema = {
43
+ type: 'object',
44
+ properties: {
45
+ type: { type: 'string', const: AuthProviderType.SAML2 },
46
+ title: { type: 'string' },
47
+ issuerId: { type: 'string' },
48
+ entityId: { type: 'string' },
49
+ ssoUrl: { type: 'string' },
50
+ x509PublicCert: { type: 'string' },
51
+ teamsAttributeName: { type: 'string', default: DEFAULT_TEAM_CLAIM_NAME },
52
+ teamsAttributeMap: { type: 'object', additionalProperties: { type: 'string' } },
53
+ defaultTeams: { type: 'array', items: { type: 'string' } },
54
+ },
55
+ additionalProperties: false,
56
+ required: ['type', 'issuerId', 'ssoUrl', 'x509PublicCert'],
57
+ } as const;
58
+
59
+ const basicAuthProviderConfigSchema = {
60
+ type: 'object',
61
+ properties: {
62
+ type: { type: 'string', const: AuthProviderType.BASIC },
63
+ title: { type: 'string' },
64
+ credentials: {
65
+ type: 'array',
66
+ items: {
67
+ type: 'object',
68
+ properties: {
69
+ username: { type: 'string' },
70
+ password: { type: 'string' },
71
+ passwordHash: { type: 'string' },
72
+ teams: { type: 'array', items: { type: 'string' } },
73
+ },
74
+ required: ['username'],
75
+ additionalProperties: false,
76
+ },
77
+ },
78
+ },
79
+ required: ['type', 'credentials'],
80
+ additionalProperties: false,
81
+ } as const;
82
+
83
+ const authProviderConfigSchema = {
84
+ oneOf: [oidcProviderConfigSchema, saml2ProviderConfigSchema, basicAuthProviderConfigSchema],
85
+ discriminator: { propertyName: 'type' },
86
+ } as const;
87
+
88
+ export const ssoConfigSchema = {
89
+ type: 'object',
90
+ additionalProperties: authProviderConfigSchema,
91
+ } as const;
92
+
93
+ const redirectConfigSchema = {
94
+ type: 'object',
95
+ properties: {
96
+ to: { type: 'string' },
97
+ type: { type: 'number', default: 301 },
98
+ },
99
+ required: ['to'],
100
+ additionalProperties: false,
101
+ } as const;
102
+
103
+ export const apiConfigSchema = {
104
+ type: 'object',
105
+ properties: {
106
+ root: { type: 'string' },
107
+ rbac: { type: 'object', additionalProperties: true },
108
+ theme: {
109
+ type: 'object',
110
+ properties: {
111
+ openapi: { type: 'object', additionalProperties: true },
112
+ },
113
+ additionalProperties: false,
114
+ },
115
+ title: { type: 'string' },
116
+ metadata: { type: 'object', additionalProperties: true },
117
+ },
118
+ additionalProperties: true,
119
+ required: ['root'],
120
+ } as const;
121
+
122
+ const metadataConfigSchema = {
123
+ type: 'object',
124
+ additionalProperties: true,
125
+ } as const;
126
+
127
+ const seoConfigSchema = {
128
+ type: 'object',
129
+ properties: {
130
+ title: { type: 'string' },
131
+ description: { type: 'string' },
132
+ siteUrl: { type: 'string' },
133
+ image: { type: 'string' },
134
+ keywords: { type: 'array', items: { type: 'string' } },
135
+ lang: { type: 'string' },
136
+ jsonLd: { type: 'object' },
137
+ meta: {
138
+ type: 'array',
139
+ items: {
140
+ type: 'object',
141
+ properties: {
142
+ name: { type: 'string' },
143
+ content: { type: 'string' },
144
+ },
145
+ required: ['name', 'content'],
146
+ additionalProperties: false,
147
+ },
148
+ },
149
+ },
150
+ additionalProperties: false,
151
+ } as const;
152
+
153
+ const rbacScopeItemsSchema = { type: 'object', additionalProperties: { type: 'string' } } as const;
154
+
155
+ const rbacConfigSchema = {
156
+ type: 'object',
157
+ properties: {
158
+ defaults: rbacScopeItemsSchema,
159
+ },
160
+ additionalProperties: rbacScopeItemsSchema,
161
+ } as const;
162
+
163
+ const graviteeAdapterConfigSchema = {
164
+ type: 'object',
165
+ properties: {
166
+ type: { type: 'string', const: 'GRAVITEE' },
167
+ apiBaseUrl: { type: 'string' },
168
+ env: { type: 'string' },
169
+ allowApiProductsOutsideCatalog: { type: 'boolean', default: false },
170
+ stage: { type: 'string', default: 'non-production' },
171
+
172
+ auth: { type: 'object', properties: { static: { type: 'string' } } },
173
+ },
174
+ additionalProperties: false,
175
+ required: ['type', 'apiBaseUrl'],
176
+ } as const;
177
+
178
+ const apigeeAdapterAuthOauth2Schema = {
179
+ type: 'object',
180
+ properties: {
181
+ type: { type: 'string', const: ApigeeDevOnboardingIntegrationAuthType.OAUTH2 },
182
+ tokenEndpoint: { type: 'string' },
183
+ clientId: { type: 'string' },
184
+ clientSecret: { type: 'string' },
185
+ },
186
+ additionalProperties: false,
187
+ required: ['type', 'tokenEndpoint', 'clientId', 'clientSecret'],
188
+ } as const;
189
+
190
+ const apigeeAdapterAuthServiceAccountSchema = {
191
+ type: 'object',
192
+ properties: {
193
+ type: { type: 'string', const: ApigeeDevOnboardingIntegrationAuthType.SERVICE_ACCOUNT },
194
+ serviceAccountEmail: { type: 'string' },
195
+ serviceAccountPrivateKey: { type: 'string' },
196
+ },
197
+ additionalProperties: false,
198
+ required: ['type', 'serviceAccountEmail', 'serviceAccountPrivateKey'],
199
+ } as const;
200
+
201
+ const apigeeXAdapterConfigSchema = {
202
+ type: 'object',
203
+ properties: {
204
+ type: { type: 'string', const: 'APIGEE_X' },
205
+ apiUrl: { type: 'string' },
206
+ stage: { type: 'string', default: 'non-production' },
207
+ organizationName: { type: 'string' },
208
+ ignoreApiProducts: { type: 'array', items: { type: 'string' } },
209
+ allowApiProductsOutsideCatalog: { type: 'boolean', default: false },
210
+ auth: {
211
+ type: 'object',
212
+ oneOf: [apigeeAdapterAuthOauth2Schema, apigeeAdapterAuthServiceAccountSchema],
213
+ discriminator: { propertyName: 'type' },
214
+ },
215
+ },
216
+ additionalProperties: false,
217
+ required: ['type', 'organizationName', 'auth'],
218
+ } as const;
219
+
220
+ const apigeeEdgeAdapterConfigSchema = {
221
+ ...apigeeXAdapterConfigSchema,
222
+ properties: {
223
+ ...apigeeXAdapterConfigSchema.properties,
224
+ type: { type: 'string', const: 'APIGEE_EDGE' },
225
+ },
226
+ } as const;
227
+
228
+ const devOnboardingAdapterConfigSchema = {
229
+ type: 'object',
230
+ oneOf: [apigeeXAdapterConfigSchema, apigeeEdgeAdapterConfigSchema, graviteeAdapterConfigSchema],
231
+ discriminator: { propertyName: 'type' },
232
+ } as const;
233
+
234
+ const devOnboardingConfigSchema = {
235
+ type: 'object',
236
+ required: ['adapters'],
237
+ additionalProperties: false,
238
+ properties: {
239
+ adapters: {
240
+ type: 'array',
241
+ items: devOnboardingAdapterConfigSchema,
242
+ },
243
+ },
244
+ } as const;
245
+
246
+ const responseHeaderSchema = {
247
+ type: 'object',
248
+ properties: {
249
+ name: { type: 'string' },
250
+ value: { type: 'string' },
251
+ },
252
+ additionalProperties: false,
253
+ required: ['name', 'value'],
254
+ } as const;
255
+
256
+ export const redoclyConfigSchema = {
257
+ type: 'object',
258
+ properties: {
259
+ licenseKey: { type: 'string' },
260
+ theme: { type: 'object', default: {} }, // ThemeConfig
261
+ redirects: { type: 'object', additionalProperties: redirectConfigSchema, default: {} },
262
+ seo: seoConfigSchema,
263
+ rbac: rbacConfigSchema,
264
+ responseHeaders: {
265
+ type: 'object',
266
+ additionalProperties: {
267
+ type: 'array',
268
+ items: responseHeaderSchema,
269
+ },
270
+ },
271
+ mockServer: {
272
+ type: 'object',
273
+ properties: {
274
+ off: { type: 'boolean', default: false },
275
+ position: { type: 'string', enum: ['first', 'last', 'replace', 'off'], default: 'first' },
276
+ strictExamples: { type: 'boolean', default: false },
277
+ errorIfForcedExampleNotFound: { type: 'boolean', default: false },
278
+ description: { type: 'string' },
279
+ },
280
+ },
281
+ apis: {
282
+ type: 'object',
283
+ additionalProperties: apiConfigSchema,
284
+ },
285
+ sso: ssoConfigSchema,
286
+ developerOnboarding: devOnboardingConfigSchema,
287
+ i18n: {
288
+ type: 'object',
289
+ properties: {
290
+ defaultLocale: {
291
+ type: 'string',
292
+ },
293
+ locales: {
294
+ type: 'array',
295
+ items: {
296
+ type: 'object',
297
+ properties: {
298
+ code: {
299
+ type: 'string',
300
+ },
301
+ name: {
302
+ type: 'string',
303
+ },
304
+ },
305
+ required: ['code'],
306
+ },
307
+ },
308
+ },
309
+ additionalProperties: false,
310
+ required: ['defaultLocale', 'locales'],
311
+ },
312
+ metadata: metadataConfigSchema,
313
+ },
314
+ default: {},
315
+ additionalProperties: true,
316
+ } as const;
317
+
318
+ export const environmentSchema = {
319
+ oneOf: [
320
+ { ...redoclyConfigSchema, additionalProperties: false },
321
+ {
322
+ type: 'object',
323
+ properties: {
324
+ $ref: { type: 'string' },
325
+ },
326
+ required: ['$ref'],
327
+ additionalProperties: false,
328
+ },
329
+ ],
330
+ } as const;
331
+
332
+ export const rootRedoclyConfigSchema = {
333
+ ...redoclyConfigSchema,
334
+ properties: {
335
+ ...redoclyConfigSchema.properties,
336
+ env: {
337
+ type: 'object',
338
+ additionalProperties: environmentSchema,
339
+ },
340
+ },
341
+ default: {},
342
+ required: ['redirects'],
343
+ } as const;
@@ -1,15 +1,7 @@
1
- import {
2
- devOnboardingConfigSchema,
3
- i18nConfigSchema,
4
- mockServerConfigSchema,
5
- rbacConfigSchema,
6
- redirectConfigSchema,
7
- responseHeaderSchema,
8
- seoConfigSchema,
9
- ssoConfigSchema,
10
- themeConfigSchema,
11
- } from './config-external-schemas';
1
+ import { rootRedoclyConfigSchema, apiConfigSchema } from './portal-config-schema';
2
+ import { themeConfigSchema } from './theme-config';
12
3
  import { NodeType, listOf } from '.';
4
+ import { Oas3_1Types } from './oas3_1';
13
5
  import { omitObjectProps, pickObjectProps, isCustomRuleId } from '../utils';
14
6
 
15
7
  const builtInRulesList = [
@@ -67,7 +59,10 @@ const builtInRulesList = [
67
59
  'required-string-property-missing-min-length',
68
60
  'spec-strict-refs',
69
61
  'component-name-unique',
62
+ 'channels-kebab-case',
63
+ 'no-channel-trailing-slash',
70
64
  ];
65
+
71
66
  const nodeTypesList = [
72
67
  'any',
73
68
  'Root',
@@ -128,6 +123,7 @@ const nodeTypesList = [
128
123
  'XCodeSampleList',
129
124
  'WebhooksMap',
130
125
  'SpecExtension',
126
+ 'Message',
131
127
  ];
132
128
 
133
129
  const ConfigStyleguide: NodeType = {
@@ -165,12 +161,13 @@ const RootConfigStyleguide: NodeType = {
165
161
 
166
162
  const ConfigRoot: NodeType = {
167
163
  properties: {
168
- organization: { type: 'string' },
169
- apis: 'ConfigApis',
164
+ ...rootRedoclyConfigSchema.properties,
170
165
  ...RootConfigStyleguide.properties,
166
+ apis: 'ConfigApis',
171
167
  theme: 'ConfigRootTheme',
172
168
  'features.openapi': 'ConfigReferenceDocs', // deprecated
173
169
  'features.mockServer': 'ConfigMockServer', // deprecated
170
+ organization: { type: 'string' },
174
171
  region: { enum: ['us', 'eu'] },
175
172
  telemetry: { enum: ['on', 'off'] },
176
173
  resolve: {
@@ -185,15 +182,6 @@ const ConfigRoot: NodeType = {
185
182
  type: 'string',
186
183
  },
187
184
  },
188
- redirects: { type: 'object', additionalProperties: redirectConfigSchema },
189
- licenseKey: { type: 'string' },
190
- seo: seoConfigSchema,
191
- rbac: rbacConfigSchema,
192
- responseHeaders: responseHeaderSchema,
193
- mockServer: mockServerConfigSchema,
194
- sso: ssoConfigSchema,
195
- developerOnboarding: devOnboardingConfigSchema,
196
- i18n: i18nConfigSchema,
197
185
  },
198
186
  };
199
187
 
@@ -204,6 +192,7 @@ const ConfigApis: NodeType = {
204
192
 
205
193
  const ConfigApisProperties: NodeType = {
206
194
  properties: {
195
+ ...apiConfigSchema.properties,
207
196
  root: { type: 'string' },
208
197
  labels: {
209
198
  type: 'array',
@@ -223,9 +212,6 @@ const ConfigApisProperties: NodeType = {
223
212
  type: 'string',
224
213
  },
225
214
  },
226
- title: { type: 'string' },
227
- rbac: { type: 'object' },
228
- metadata: { type: 'object' },
229
215
  },
230
216
  required: ['root'],
231
217
  };
@@ -263,6 +249,8 @@ const Rules: NodeType = {
263
249
  } else {
264
250
  return 'ObjectRule';
265
251
  }
252
+ } else if (key === 'metadata-schema' || key === 'custom-fields-schema') {
253
+ return 'Schema';
266
254
  }
267
255
  // Otherwise is considered as invalid
268
256
  return;
@@ -572,7 +560,7 @@ const TryItButton: NodeType = {
572
560
  },
573
561
  };
574
562
 
575
- const Components: NodeType = {
563
+ const ConfigThemeComponents: NodeType = {
576
564
  properties: {
577
565
  buttons: 'ButtonsConfig',
578
566
  httpBadges: 'HttpBadgesConfig',
@@ -619,7 +607,7 @@ const SchemaColorsConfig: NodeType = {
619
607
  },
620
608
  };
621
609
 
622
- const Schema: NodeType = {
610
+ const ConfigThemeSchema: NodeType = {
623
611
  properties: {
624
612
  breakFieldNames: { type: 'boolean' },
625
613
  caretColor: { type: 'string' },
@@ -759,7 +747,7 @@ const CodeBlock: NodeType = {
759
747
  },
760
748
  };
761
749
 
762
- const Logo: NodeType = {
750
+ const ConfigThemeLogo: NodeType = {
763
751
  properties: {
764
752
  gutter: { type: 'string' },
765
753
  maxHeight: { type: 'string' },
@@ -815,13 +803,13 @@ const ConfigTheme: NodeType = {
815
803
  breakpoints: 'Breakpoints',
816
804
  codeBlock: 'CodeBlock',
817
805
  colors: 'ThemeColors',
818
- components: 'Components',
806
+ components: 'ConfigThemeComponents',
819
807
  layout: 'Layout',
820
- logo: 'Logo',
808
+ logo: 'ConfigThemeLogo',
821
809
  fab: 'Fab',
822
810
  overrides: 'Overrides',
823
811
  rightPanel: 'RightPanel',
824
- schema: 'Schema',
812
+ schema: 'ConfigThemeSchema',
825
813
  shape: 'Shape',
826
814
  sidebar: 'Sidebar',
827
815
  spacing: 'ThemeSpacing',
@@ -973,6 +961,7 @@ const ConfigMockServer: NodeType = {
973
961
  };
974
962
 
975
963
  export const ConfigTypes: Record<string, NodeType> = {
964
+ ...Oas3_1Types,
976
965
  Assert,
977
966
  ConfigRoot,
978
967
  ConfigApis,
@@ -1018,7 +1007,7 @@ export const ConfigTypes: Record<string, NodeType> = {
1018
1007
  LinksConfig,
1019
1008
  TokenProps,
1020
1009
  CodeBlock,
1021
- Logo,
1010
+ ConfigThemeLogo,
1022
1011
  Fab,
1023
1012
  ButtonOverrides,
1024
1013
  Overrides,
@@ -1029,9 +1018,9 @@ export const ConfigTypes: Record<string, NodeType> = {
1029
1018
  ThemeSpacing,
1030
1019
  GenerateCodeSamples,
1031
1020
  GroupItemsConfig,
1032
- Components,
1021
+ ConfigThemeComponents,
1033
1022
  Layout,
1034
- Schema,
1023
+ ConfigThemeSchema,
1035
1024
  Sidebar,
1036
1025
  Heading,
1037
1026
  Typography,