@redocly/openapi-core 1.0.2 → 1.1.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.
@@ -1,242 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.productThemeOverrideSchema = exports.themeConfigSchema = exports.mockServerConfigSchema = exports.i18nConfigSchema = exports.responseHeaderSchema = exports.devOnboardingConfigSchema = exports.seoConfigSchema = exports.redirectConfigSchema = exports.ssoConfigSchema = exports.rbacConfigSchema = void 0;
4
- const config_1 = require("../config");
5
- const oidcIssuerMetadataSchema = {
6
- type: 'object',
7
- properties: {
8
- end_session_endpoint: { type: 'string' },
9
- token_endpoint: { type: 'string' },
10
- authorization_endpoint: { type: 'string' },
11
- },
12
- required: ['token_endpoint', 'authorization_endpoint'],
13
- additionalProperties: true,
14
- };
15
- const oidcProviderConfigSchema = {
16
- type: 'object',
17
- properties: {
18
- type: { type: 'string', const: config_1.AuthProviderType.OIDC },
19
- title: { type: 'string' },
20
- configurationUrl: { type: 'string', minLength: 1 },
21
- configuration: oidcIssuerMetadataSchema,
22
- clientId: { type: 'string', minLength: 1 },
23
- clientSecret: { type: 'string', minLength: 1 },
24
- teamsClaimName: { type: 'string' },
25
- defaultTeams: { type: 'array', items: { type: 'string' } },
26
- scopes: { type: 'array', items: { type: 'string' } },
27
- tokenExpirationTime: { type: 'number' },
28
- authorizationRequestCustomParams: { type: 'object', additionalProperties: { type: 'string' } },
29
- tokenRequestCustomParams: { type: 'object', additionalProperties: { type: 'string' } },
30
- },
31
- required: ['type', 'clientId', 'clientSecret'],
32
- oneOf: [{ required: ['configurationUrl'] }, { required: ['configuration'] }],
33
- additionalProperties: false,
34
- };
35
- const saml2ProviderConfigSchema = {
36
- type: 'object',
37
- properties: {
38
- type: { type: 'string', const: config_1.AuthProviderType.SAML2 },
39
- title: { type: 'string' },
40
- issuerId: { type: 'string' },
41
- entityId: { type: 'string' },
42
- ssoUrl: { type: 'string' },
43
- x509PublicCert: { type: 'string' },
44
- teamsAttributeName: { type: 'string', default: config_1.DEFAULT_TEAM_CLAIM_NAME },
45
- teamsAttributeMap: { type: 'object', additionalProperties: { type: 'string' } },
46
- defaultTeams: { type: 'array', items: { type: 'string' } },
47
- },
48
- additionalProperties: false,
49
- required: ['type', 'issuerId', 'ssoUrl', 'x509PublicCert'],
50
- };
51
- const basicAuthProviderConfigSchema = {
52
- type: 'object',
53
- properties: {
54
- type: { type: 'string', const: config_1.AuthProviderType.BASIC },
55
- title: { type: 'string' },
56
- credentials: {
57
- type: 'array',
58
- items: {
59
- type: 'object',
60
- properties: {
61
- username: { type: 'string' },
62
- password: { type: 'string' },
63
- passwordHash: { type: 'string' },
64
- teams: { type: 'array', items: { type: 'string' } },
65
- },
66
- required: ['username'],
67
- additionalProperties: false,
68
- },
69
- },
70
- },
71
- required: ['type', 'credentials'],
72
- additionalProperties: false,
73
- };
74
- const authProviderConfigSchema = {
75
- oneOf: [oidcProviderConfigSchema, saml2ProviderConfigSchema, basicAuthProviderConfigSchema],
76
- discriminator: { propertyName: 'type' },
77
- };
78
- const rbacScopeItemsSchema = { type: 'object', additionalProperties: { type: 'string' } };
79
- exports.rbacConfigSchema = {
80
- type: 'object',
81
- properties: {
82
- defaults: rbacScopeItemsSchema,
83
- },
84
- additionalProperties: rbacScopeItemsSchema,
85
- };
86
- exports.ssoConfigSchema = {
87
- type: 'object',
88
- additionalProperties: authProviderConfigSchema,
89
- };
90
- exports.redirectConfigSchema = {
91
- type: 'object',
92
- properties: {
93
- to: { type: 'string' },
94
- type: { type: 'number', default: 301 },
95
- },
96
- required: ['to'],
97
- additionalProperties: false,
98
- };
99
- exports.seoConfigSchema = {
100
- type: 'object',
101
- properties: {
102
- title: { type: 'string' },
103
- description: { type: 'string' },
104
- siteUrl: { type: 'string' },
105
- image: { type: 'string' },
106
- keywords: { type: 'array', items: { type: 'string' } },
107
- lang: { type: 'string' },
108
- jsonLd: { type: 'object' },
109
- meta: {
110
- type: 'array',
111
- items: {
112
- type: 'object',
113
- properties: {
114
- name: { type: 'string' },
115
- content: { type: 'string' },
116
- },
117
- required: ['name', 'content'],
118
- additionalProperties: false,
119
- },
120
- },
121
- },
122
- additionalProperties: false,
123
- };
124
- const apigeeAdapterAuthOauth2Schema = {
125
- type: 'object',
126
- properties: {
127
- type: { type: 'string', const: config_1.ApigeeDevOnboardingIntegrationAuthType.OAUTH2 },
128
- tokenEndpoint: { type: 'string' },
129
- clientId: { type: 'string' },
130
- clientSecret: { type: 'string' },
131
- },
132
- additionalProperties: false,
133
- required: ['type', 'tokenEndpoint', 'clientId', 'clientSecret'],
134
- };
135
- const apigeeAdapterAuthServiceAccountSchema = {
136
- type: 'object',
137
- properties: {
138
- type: { type: 'string', const: config_1.ApigeeDevOnboardingIntegrationAuthType.SERVICE_ACCOUNT },
139
- serviceAccountEmail: { type: 'string' },
140
- serviceAccountPrivateKey: { type: 'string' },
141
- },
142
- additionalProperties: false,
143
- required: ['type', 'serviceAccountEmail', 'serviceAccountPrivateKey'],
144
- };
145
- const apigeeXAdapterConfigSchema = {
146
- type: 'object',
147
- properties: {
148
- type: { type: 'string', const: 'APIGEE_X' },
149
- apiUrl: { type: 'string' },
150
- stage: { type: 'string', default: 'non-production' },
151
- organizationName: { type: 'string' },
152
- ignoreApiProducts: { type: 'array', items: { type: 'string' } },
153
- allowApiProductsOutsideCatalog: { type: 'boolean', default: false },
154
- auth: {
155
- type: 'object',
156
- oneOf: [apigeeAdapterAuthOauth2Schema, apigeeAdapterAuthServiceAccountSchema],
157
- discriminator: { propertyName: 'type' },
158
- },
159
- },
160
- additionalProperties: false,
161
- required: ['type', 'organizationName', 'auth'],
162
- };
163
- const apigeeEdgeAdapterConfigSchema = Object.assign(Object.assign({}, apigeeXAdapterConfigSchema), { properties: Object.assign(Object.assign({}, apigeeXAdapterConfigSchema.properties), { type: { type: 'string', const: 'APIGEE_EDGE' } }) });
164
- const graviteeAdapterConfigSchema = {
165
- type: 'object',
166
- properties: {
167
- type: { type: 'string', const: 'GRAVITEE' },
168
- apiBaseUrl: { type: 'string' },
169
- env: { type: 'string' },
170
- allowApiProductsOutsideCatalog: { type: 'boolean', default: false },
171
- stage: { type: 'string', default: 'non-production' },
172
- auth: { type: 'object', properties: { static: { type: 'string' } } },
173
- },
174
- additionalProperties: false,
175
- required: ['type', 'apiBaseUrl'],
176
- };
177
- const devOnboardingAdapterConfigSchema = {
178
- type: 'object',
179
- oneOf: [apigeeXAdapterConfigSchema, apigeeEdgeAdapterConfigSchema, graviteeAdapterConfigSchema],
180
- discriminator: { propertyName: 'type' },
181
- };
182
- exports.devOnboardingConfigSchema = {
183
- type: 'object',
184
- required: ['adapters'],
185
- additionalProperties: false,
186
- properties: {
187
- adapters: {
188
- type: 'array',
189
- items: devOnboardingAdapterConfigSchema,
190
- },
191
- },
192
- };
193
- exports.responseHeaderSchema = {
194
- type: 'object',
195
- properties: {
196
- name: { type: 'string' },
197
- value: { type: 'string' },
198
- },
199
- additionalProperties: false,
200
- required: ['name', 'value'],
201
- };
202
- exports.i18nConfigSchema = {
203
- type: 'object',
204
- properties: {
205
- defaultLocale: {
206
- type: 'string',
207
- },
208
- locales: {
209
- type: 'array',
210
- items: {
211
- type: 'object',
212
- properties: {
213
- code: {
214
- type: 'string',
215
- },
216
- name: {
217
- type: 'string',
218
- },
219
- },
220
- required: ['code'],
221
- },
222
- },
223
- },
224
- required: ['defaultLocale', 'locales'],
225
- };
226
- exports.mockServerConfigSchema = {
227
- type: 'object',
228
- properties: {
229
- off: { type: 'boolean', default: false },
230
- position: { type: 'string', enum: ['first', 'last', 'replace', 'off'], default: 'first' },
231
- strictExamples: { type: 'boolean', default: false },
232
- errorIfForcedExampleNotFound: { type: 'boolean', default: false },
233
- description: { type: 'string' },
234
- },
235
- };
3
+ exports.ScorecardStatus = exports.productThemeOverrideSchema = exports.themeConfigSchema = void 0;
236
4
  const logoConfigSchema = {
237
5
  type: 'object',
238
6
  properties: {
239
7
  image: { type: 'string' },
8
+ srcSet: { type: 'string' },
240
9
  altText: { type: 'string' },
241
10
  link: { type: 'string' },
242
11
  favicon: { type: 'string' },
@@ -316,7 +85,7 @@ const markdownConfigSchema = {
316
85
  },
317
86
  editPage: {
318
87
  type: 'object',
319
- properties: Object.assign({ baseUrl: { type: 'string' }, icon: { type: 'string' }, text: { type: 'string', default: 'Edit this page' } }, hideConfigSchema.properties),
88
+ properties: Object.assign({ baseUrl: { type: 'string' } }, hideConfigSchema.properties),
320
89
  additionalProperties: false,
321
90
  default: {},
322
91
  },
@@ -404,35 +173,14 @@ const googleAnalyticsConfigSchema = {
404
173
  properties: {
405
174
  includeInDevelopment: { type: 'boolean' },
406
175
  trackingId: { type: 'string' },
176
+ conversionId: { type: 'string' },
177
+ floodlightId: { type: 'string' },
407
178
  head: { type: 'boolean' },
408
179
  respectDNT: { type: 'boolean' },
409
- anonymize: { type: 'boolean' },
410
180
  exclude: { type: 'array', items: { type: 'string' } },
411
181
  optimizeId: { type: 'string' },
412
- experimentId: { type: 'string' },
413
- variationId: { type: 'string' },
414
- enableWebVitalsTracking: { type: 'boolean' },
415
- defer: { type: 'boolean' },
416
- sampleRate: { type: 'number' },
417
- name: { type: 'string' },
418
- clientId: { type: 'string' },
419
- siteSpeedSampleRate: { type: 'number' },
420
- alwaysSendReferrer: { type: 'boolean' },
421
- allowAnchor: { type: 'boolean' },
422
- cookieName: { type: 'string' },
423
- cookieFlags: { type: 'string' },
424
- cookieDomain: { type: 'string' },
182
+ anonymizeIp: { type: 'boolean' },
425
183
  cookieExpires: { type: 'number' },
426
- storeGac: { type: 'boolean' },
427
- legacyCookieDomain: { type: 'string' },
428
- legacyHistoryImport: { type: 'boolean' },
429
- allowLinker: { type: 'boolean' },
430
- storage: { type: 'string' },
431
- allowAdFeatures: { type: 'boolean' },
432
- dataSource: { type: 'string' },
433
- queueTime: { type: 'number' },
434
- forceSSL: { type: 'boolean' },
435
- transport: { type: 'string' },
436
184
  },
437
185
  additionalProperties: false,
438
186
  required: ['trackingId'],
@@ -456,6 +204,11 @@ const navItemSchema = {
456
204
  label: { type: 'string' },
457
205
  separator: { type: 'string' },
458
206
  separatorLine: { type: 'boolean' },
207
+ linePosition: {
208
+ type: 'string',
209
+ enum: ['top', 'bottom'],
210
+ default: 'top',
211
+ },
459
212
  version: { type: 'string' },
460
213
  menuStyle: { type: 'string', enum: ['drilldown'] },
461
214
  expanded: { type: 'string', const: 'always' },
@@ -511,6 +264,14 @@ const scorecardConfigSchema = {
511
264
  required: ['levels'],
512
265
  properties: {
513
266
  failBuildIfBelowMinimum: { type: 'boolean', default: false },
267
+ teamMetadataProperty: {
268
+ type: 'object',
269
+ properties: {
270
+ property: { type: 'string' },
271
+ label: { type: 'string' },
272
+ default: { type: 'string' },
273
+ },
274
+ },
514
275
  levels: {
515
276
  type: 'array',
516
277
  items: {
@@ -553,11 +314,15 @@ const scorecardConfigSchema = {
553
314
  const catalogSchema = {
554
315
  type: 'object',
555
316
  additionalProperties: true,
556
- required: ['slug', 'filters', 'groupByFirstFilter', 'items'],
317
+ required: ['slug', 'items'],
557
318
  properties: {
558
319
  slug: { type: 'string' },
559
320
  filters: { type: 'array', items: catalogFilterSchema },
560
321
  groupByFirstFilter: { type: 'boolean' },
322
+ filterValuesCasing: {
323
+ type: 'string',
324
+ enum: ['sentence', 'original', 'lowercase', 'uppercase'],
325
+ },
561
326
  items: navItemsSchema,
562
327
  requiredPermission: { type: 'string' },
563
328
  separateVersions: { type: 'boolean' },
@@ -593,10 +358,24 @@ exports.themeConfigSchema = {
593
358
  },
594
359
  footer: {
595
360
  type: 'object',
596
- properties: Object.assign({ items: navItemsSchema, copyrightText: { type: 'string' } }, hideConfigSchema.properties),
361
+ properties: Object.assign({ items: navItemsSchema, copyrightText: { type: 'string' }, logo: hideConfigSchema }, hideConfigSchema.properties),
597
362
  additionalProperties: false,
598
363
  },
599
- sidebar: hideConfigSchema,
364
+ sidebar: {
365
+ type: 'object',
366
+ properties: Object.assign({ separatorLine: { type: 'boolean' }, linePosition: {
367
+ type: 'string',
368
+ enum: ['top', 'bottom'],
369
+ default: 'bottom',
370
+ } }, hideConfigSchema.properties),
371
+ additionalProperties: false,
372
+ },
373
+ seo: {
374
+ type: 'object',
375
+ properties: {
376
+ title: { type: 'string' },
377
+ },
378
+ },
600
379
  scripts: {
601
380
  type: 'object',
602
381
  properties: {
@@ -762,6 +541,15 @@ exports.themeConfigSchema = {
762
541
  additionalProperties: false,
763
542
  default: {},
764
543
  },
544
+ versionPicker: {
545
+ type: 'object',
546
+ properties: {
547
+ hide: { type: 'boolean' },
548
+ showForUnversioned: {
549
+ type: 'boolean',
550
+ },
551
+ },
552
+ },
765
553
  breadcrumbs: {
766
554
  type: 'object',
767
555
  properties: {
@@ -803,3 +591,9 @@ exports.productThemeOverrideSchema = {
803
591
  additionalProperties: true,
804
592
  default: {},
805
593
  };
594
+ var ScorecardStatus;
595
+ (function (ScorecardStatus) {
596
+ ScorecardStatus["BelowMinimum"] = "Below minimum";
597
+ ScorecardStatus["Highest"] = "Highest";
598
+ ScorecardStatus["Minimum"] = "Minimum";
599
+ })(ScorecardStatus = exports.ScorecardStatus || (exports.ScorecardStatus = {}));
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@redocly/openapi-core",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "engines": {
7
- "node": ">=12.0.0"
7
+ "node": ">=14.0.0"
8
8
  },
9
9
  "engineStrict": true,
10
10
  "license": "MIT",
@@ -111,6 +111,7 @@ describe('lint', () => {
111
111
  "severity": "error",
112
112
  "suggest": Array [
113
113
  "theme",
114
+ "env",
114
115
  "seo",
115
116
  "sso",
116
117
  ],
@@ -178,6 +179,7 @@ describe('lint', () => {
178
179
  "apis",
179
180
  "seo",
180
181
  "sso",
182
+ "env",
181
183
  ],
182
184
  },
183
185
  ]
@@ -41,6 +41,47 @@ describe('no-path-trailing-slash', () => {
41
41
  `);
42
42
  });
43
43
 
44
+ it('should report on trailing slash in path on key when referencing', async () => {
45
+ const document = parseYamlToDocument(
46
+ outdent`
47
+ openapi: 3.0.0
48
+ paths:
49
+ '/bad/':
50
+ $ref: '#/components/pathItems/MyItem'
51
+ components:
52
+ pathItems:
53
+ MyItem:
54
+ get:
55
+ summary: List all pets
56
+ `,
57
+ 'foobar.yaml'
58
+ );
59
+
60
+ const results = await lintDocument({
61
+ externalRefResolver: new BaseResolver(),
62
+ document,
63
+ config: await makeConfig({ 'no-path-trailing-slash': 'error' }),
64
+ });
65
+
66
+ expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
67
+ Array [
68
+ Object {
69
+ "location": Array [
70
+ Object {
71
+ "pointer": "#/paths/~1bad~1",
72
+ "reportOnKey": true,
73
+ "source": "foobar.yaml",
74
+ },
75
+ ],
76
+ "message": "\`/bad/\` should not have a trailing slash.",
77
+ "ruleId": "no-path-trailing-slash",
78
+ "severity": "error",
79
+ "suggest": Array [],
80
+ },
81
+ ]
82
+ `);
83
+ });
84
+
44
85
  it('should not report on if no trailing slash in path', async () => {
45
86
  const document = parseYamlToDocument(
46
87
  outdent`
@@ -61,4 +61,62 @@ describe('Oas3 tags-alphabetical', () => {
61
61
 
62
62
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`Array []`);
63
63
  });
64
+
65
+ it('should report on tags object if not sorted alphabetically not ignoring case', async () => {
66
+ const document = parseYamlToDocument(
67
+ outdent`
68
+ openapi: 3.0.0
69
+ paths: {}
70
+ tags:
71
+ - name: a
72
+ - name: B
73
+ `,
74
+ 'foobar.yaml'
75
+ );
76
+
77
+ const results = await lintDocument({
78
+ externalRefResolver: new BaseResolver(),
79
+ document,
80
+ config: await makeConfig({ 'tags-alphabetical': 'error' }),
81
+ });
82
+
83
+ expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
84
+ Array [
85
+ Object {
86
+ "location": Array [
87
+ Object {
88
+ "pointer": "#/tags/0",
89
+ "reportOnKey": false,
90
+ "source": "foobar.yaml",
91
+ },
92
+ ],
93
+ "message": "The \`tags\` array should be in alphabetical order.",
94
+ "ruleId": "tags-alphabetical",
95
+ "severity": "error",
96
+ "suggest": Array [],
97
+ },
98
+ ]
99
+ `);
100
+ });
101
+
102
+ it('should not report on tags object if sorted alphabetically ignoring case', async () => {
103
+ const document = parseYamlToDocument(
104
+ outdent`
105
+ openapi: 3.0.0
106
+ paths: {}
107
+ tags:
108
+ - name: a
109
+ - name: B
110
+ `,
111
+ 'foobar.yaml'
112
+ );
113
+
114
+ const results = await lintDocument({
115
+ externalRefResolver: new BaseResolver(),
116
+ document,
117
+ config: await makeConfig({ 'tags-alphabetical': { severity: 'error', ignoreCase: true } }),
118
+ });
119
+
120
+ expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`Array []`);
121
+ });
64
122
  });
@@ -3,11 +3,11 @@ import { UserContext } from '../../walk';
3
3
 
4
4
  export const NoPathTrailingSlash: Oas3Rule | Oas2Rule = () => {
5
5
  return {
6
- PathItem(_path: any, { report, key, location }: UserContext) {
6
+ PathItem(_path: any, { report, key, rawLocation }: UserContext) {
7
7
  if ((key as string).endsWith('/') && key !== '/') {
8
8
  report({
9
9
  message: `\`${key}\` should not have a trailing slash.`,
10
- location: location.key(),
10
+ location: rawLocation.key(),
11
11
  });
12
12
  }
13
13
  },
@@ -1,14 +1,14 @@
1
1
  import { Oas3Rule, Oas2Rule } from '../../visitors';
2
- import { Oas2Definition } from '../../typings/swagger';
3
- import { Oas3Definition } from '../../typings/openapi';
2
+ import { Oas2Definition, Oas2Tag } from '../../typings/swagger';
3
+ import { Oas3Definition, Oas3Tag } from '../../typings/openapi';
4
4
  import { UserContext } from '../../walk';
5
5
 
6
- export const TagsAlphabetical: Oas3Rule | Oas2Rule = () => {
6
+ export const TagsAlphabetical: Oas3Rule | Oas2Rule = ({ ignoreCase = false }) => {
7
7
  return {
8
8
  Root(root: Oas2Definition | Oas3Definition, { report, location }: UserContext) {
9
9
  if (!root.tags) return;
10
10
  for (let i = 0; i < root.tags.length - 1; i++) {
11
- if (root.tags[i].name > root.tags[i + 1].name) {
11
+ if (getTagName(root.tags[i], ignoreCase) > getTagName(root.tags[i + 1], ignoreCase)) {
12
12
  report({
13
13
  message: 'The `tags` array should be in alphabetical order.',
14
14
  location: location.child(['tags', i]),
@@ -18,3 +18,7 @@ export const TagsAlphabetical: Oas3Rule | Oas2Rule = () => {
18
18
  },
19
19
  };
20
20
  };
21
+
22
+ function getTagName(tag: Oas2Tag | Oas3Tag, ignoreCase: boolean): string {
23
+ return ignoreCase ? tag.name.toLowerCase() : tag.name;
24
+ }