@redocly/openapi-core 1.8.2 → 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.
- package/CHANGELOG.md +16 -0
- package/lib/bundle.d.ts +1 -1
- package/lib/config/all.js +1 -0
- package/lib/config/minimal.js +1 -0
- package/lib/config/recommended-strict.js +1 -0
- package/lib/config/recommended.js +1 -0
- package/lib/lint.d.ts +1 -0
- package/lib/lint.js +1 -1
- package/lib/oas-types.d.ts +1 -1
- package/lib/ref-utils.js +4 -4
- package/lib/resolve.js +9 -1
- package/lib/rules/common/no-required-schema-properties-undefined.d.ts +2 -0
- package/lib/rules/common/no-required-schema-properties-undefined.js +37 -0
- package/lib/rules/oas2/index.js +2 -0
- package/lib/rules/oas3/index.js +2 -0
- package/lib/types/index.d.ts +7 -7
- package/lib/types/json-schema-adapter.d.ts +3 -0
- package/lib/types/json-schema-adapter.js +173 -0
- package/lib/types/oas2.d.ts +3 -2
- package/lib/types/oas3.d.ts +3 -2
- package/lib/types/oas3_1.d.ts +3 -2
- package/lib/types/portal-config-schema.d.ts +5261 -52
- package/lib/types/portal-config-schema.js +71 -55
- package/lib/types/redocly-yaml.d.ts +14 -2
- package/lib/types/redocly-yaml.js +102 -39
- package/lib/types/theme-config.d.ts +819 -36
- package/lib/types/theme-config.js +67 -29
- package/lib/utils.d.ts +2 -2
- package/lib/visitors.js +1 -1
- package/lib/walk.js +7 -1
- package/package.json +1 -1
- package/src/__tests__/lint.test.ts +1218 -36
- package/src/__tests__/ref-utils.test.ts +22 -0
- package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +2 -0
- package/src/config/__tests__/load.test.ts +13 -13
- package/src/config/all.ts +1 -0
- package/src/config/minimal.ts +1 -0
- package/src/config/recommended-strict.ts +1 -0
- package/src/config/recommended.ts +1 -0
- package/src/decorators/oas2/remove-unused-components.ts +3 -2
- package/src/decorators/oas3/remove-unused-components.ts +3 -2
- package/src/lint.ts +2 -1
- package/src/ref-utils.ts +4 -4
- package/src/resolve.ts +13 -1
- package/src/rules/common/__tests__/no-required-schema-properties-undefined.test.ts +550 -0
- package/src/rules/common/no-required-schema-properties-undefined.ts +53 -0
- package/src/rules/oas2/index.ts +2 -0
- package/src/rules/oas3/index.ts +2 -0
- package/src/types/index.ts +7 -12
- package/src/types/json-schema-adapter.ts +217 -0
- package/src/types/oas2.ts +5 -2
- package/src/types/oas3.ts +6 -2
- package/src/types/oas3_1.ts +5 -2
- package/src/types/portal-config-schema.ts +111 -61
- package/src/types/redocly-yaml.ts +119 -43
- package/src/types/theme-config.ts +125 -27
- package/src/utils.ts +2 -2
- package/src/visitors.ts +1 -1
- package/src/walk.ts +7 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
// For internal usage only
|
|
2
|
+
|
|
3
|
+
import Ajv from '@redocly/ajv/dist/2020';
|
|
4
|
+
import { isPlainObject } from '../utils';
|
|
5
|
+
|
|
6
|
+
import type { NodeType, PropType, ResolveTypeFn } from '.';
|
|
7
|
+
import type { JSONSchema } from 'json-schema-to-ts';
|
|
8
|
+
import { Oas3Schema } from '../typings/openapi';
|
|
9
|
+
|
|
10
|
+
const ajv = new Ajv({
|
|
11
|
+
strictSchema: false,
|
|
12
|
+
allowUnionTypes: true,
|
|
13
|
+
useDefaults: true,
|
|
14
|
+
allErrors: true,
|
|
15
|
+
discriminator: true,
|
|
16
|
+
strictTypes: false,
|
|
17
|
+
verbose: true,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
function findOneOf(schemaOneOf: JSONSchema[], oneOfs: (PropType | ResolveTypeFn)[]): ResolveTypeFn {
|
|
21
|
+
if (oneOfs.some((option) => typeof option === 'function')) {
|
|
22
|
+
throw new Error('Unexpected oneOf inside oneOf.');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return (value: unknown) => {
|
|
26
|
+
let index = schemaOneOf.findIndex((option) => ajv.validate(option, value));
|
|
27
|
+
if (index === -1) {
|
|
28
|
+
index = 0;
|
|
29
|
+
}
|
|
30
|
+
return oneOfs[index] as PropType;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function transformJSONSchemaToNodeType(
|
|
35
|
+
propertyName: string,
|
|
36
|
+
schema: JSONSchema,
|
|
37
|
+
ctx: Record<string, NodeType>
|
|
38
|
+
): PropType | ResolveTypeFn {
|
|
39
|
+
if (!schema || typeof schema === 'boolean') {
|
|
40
|
+
throw new Error(`Unexpected schema in ${propertyName}.`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (schema instanceof Array) {
|
|
44
|
+
throw new Error(`Unexpected array schema in ${propertyName}. Try using oneOf instead.`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (schema.type === 'null') {
|
|
48
|
+
throw new Error(`Unexpected null schema type in ${propertyName} schema.`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (schema.type instanceof Array) {
|
|
52
|
+
throw new Error(
|
|
53
|
+
`Unexpected array schema type in ${propertyName} schema. Try using oneOf instead.`
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (
|
|
58
|
+
schema.type === 'string' ||
|
|
59
|
+
schema.type === 'number' ||
|
|
60
|
+
schema.type === 'integer' ||
|
|
61
|
+
schema.type === 'boolean'
|
|
62
|
+
) {
|
|
63
|
+
const { default: _, format: _format, ...rest } = schema;
|
|
64
|
+
return rest as PropType;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (schema.type === 'object' && !schema.properties && !schema.oneOf) {
|
|
68
|
+
if (schema.additionalProperties === undefined || schema.additionalProperties === true) {
|
|
69
|
+
return { type: 'object' };
|
|
70
|
+
} else if (schema.additionalProperties === false) {
|
|
71
|
+
return { type: 'object', properties: {} };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (schema.allOf) {
|
|
76
|
+
throw new Error(`Unexpected allOf in ${propertyName}.`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (schema.anyOf) {
|
|
80
|
+
throw new Error(`Unexpected anyOf in ${propertyName}.`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (
|
|
84
|
+
isPlainObject(schema.properties) ||
|
|
85
|
+
isPlainObject(schema.additionalProperties) ||
|
|
86
|
+
(isPlainObject(schema.items) &&
|
|
87
|
+
(isPlainObject(schema.items.properties) ||
|
|
88
|
+
isPlainObject(schema.items.additionalProperties) ||
|
|
89
|
+
schema.items.oneOf)) // exclude scalar array types
|
|
90
|
+
) {
|
|
91
|
+
return extractNodeToContext(propertyName, schema, ctx);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (schema.oneOf) {
|
|
95
|
+
if ((schema as Oas3Schema).discriminator) {
|
|
96
|
+
const discriminatedPropertyName = (schema as Oas3Schema).discriminator?.propertyName;
|
|
97
|
+
if (!discriminatedPropertyName) {
|
|
98
|
+
throw new Error(`Unexpected discriminator without a propertyName in ${propertyName}.`);
|
|
99
|
+
}
|
|
100
|
+
const oneOfs = schema.oneOf.map((option, i) => {
|
|
101
|
+
if (typeof option === 'boolean') {
|
|
102
|
+
throw new Error(
|
|
103
|
+
`Unexpected boolean schema in ${propertyName} at position ${i} in oneOf.`
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
const discriminatedProperty = option?.properties?.[discriminatedPropertyName];
|
|
107
|
+
if (!discriminatedProperty || typeof discriminatedProperty === 'boolean') {
|
|
108
|
+
throw new Error(
|
|
109
|
+
`Unexpected property '${discriminatedProperty}' schema in ${propertyName} at position ${i} in oneOf.`
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
const name = discriminatedProperty.const as string;
|
|
113
|
+
return transformJSONSchemaToNodeType(name, option, ctx);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
return (value: unknown, key: string) => {
|
|
117
|
+
if (isPlainObject(value)) {
|
|
118
|
+
const discriminatedTypeName = value[discriminatedPropertyName];
|
|
119
|
+
if (typeof discriminatedTypeName === 'string' && ctx[discriminatedTypeName]) {
|
|
120
|
+
return discriminatedTypeName;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return findOneOf(schema.oneOf as JSONSchema[], oneOfs)(value, key);
|
|
124
|
+
};
|
|
125
|
+
} else {
|
|
126
|
+
const oneOfs = schema.oneOf.map((option, i) =>
|
|
127
|
+
transformJSONSchemaToNodeType(propertyName + '_' + i, option, ctx)
|
|
128
|
+
);
|
|
129
|
+
return findOneOf(schema.oneOf as JSONSchema[], oneOfs);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return schema as PropType;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function extractNodeToContext(
|
|
137
|
+
propertyName: string,
|
|
138
|
+
schema: JSONSchema,
|
|
139
|
+
ctx: Record<string, NodeType>
|
|
140
|
+
): string {
|
|
141
|
+
if (!schema || typeof schema === 'boolean') {
|
|
142
|
+
throw new Error(`Unexpected schema in ${propertyName}.`);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (schema instanceof Array) {
|
|
146
|
+
throw new Error(`Unexpected array schema in ${propertyName}. Try using oneOf instead.`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (schema.type === 'null') {
|
|
150
|
+
throw new Error(`Unexpected null schema type in ${propertyName} schema.`);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (schema.type instanceof Array) {
|
|
154
|
+
throw new Error(
|
|
155
|
+
`Unexpected array schema type in ${propertyName} schema. Try using oneOf instead.`
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const properties: Record<string, PropType | ResolveTypeFn> = {};
|
|
160
|
+
for (const [name, property] of Object.entries(schema.properties || {})) {
|
|
161
|
+
properties[name] = transformJSONSchemaToNodeType(propertyName + '.' + name, property, ctx);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
let additionalProperties;
|
|
165
|
+
if (isPlainObject(schema.additionalProperties)) {
|
|
166
|
+
additionalProperties = transformJSONSchemaToNodeType(
|
|
167
|
+
propertyName + '_additionalProperties',
|
|
168
|
+
schema.additionalProperties,
|
|
169
|
+
ctx
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
if (schema.additionalProperties === true) {
|
|
173
|
+
additionalProperties = {};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
let items;
|
|
177
|
+
if (
|
|
178
|
+
isPlainObject(schema.items) &&
|
|
179
|
+
(isPlainObject(schema.items.properties) ||
|
|
180
|
+
isPlainObject(schema.items.additionalProperties) ||
|
|
181
|
+
schema.items.oneOf) // exclude scalar array types
|
|
182
|
+
) {
|
|
183
|
+
items = transformJSONSchemaToNodeType(propertyName + '_items', schema.items, ctx);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
let required = schema.required as NodeType['required'];
|
|
187
|
+
// Translate required in oneOfs into a ResolveTypeFn.
|
|
188
|
+
if (schema.oneOf && schema.oneOf.every((option) => !!(option as Oas3Schema).required)) {
|
|
189
|
+
required = (value): string[] => {
|
|
190
|
+
const requiredList: string[][] = schema.oneOf!.map((option) => [
|
|
191
|
+
...(schema.required || []),
|
|
192
|
+
...(option as Oas3Schema).required!,
|
|
193
|
+
]);
|
|
194
|
+
|
|
195
|
+
let index = requiredList.findIndex((r) =>
|
|
196
|
+
r.every((requiredProp) => value[requiredProp] !== undefined)
|
|
197
|
+
);
|
|
198
|
+
if (index === -1) {
|
|
199
|
+
index = 0;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return requiredList[index];
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
ctx[propertyName] = { properties, additionalProperties, items, required };
|
|
207
|
+
return propertyName;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function getNodeTypesFromJSONSchema(
|
|
211
|
+
schemaName: string,
|
|
212
|
+
entrySchema: JSONSchema
|
|
213
|
+
): Record<string, NodeType> {
|
|
214
|
+
const ctx: Record<string, NodeType> = {};
|
|
215
|
+
transformJSONSchemaToNodeType(schemaName, entrySchema, ctx);
|
|
216
|
+
return ctx;
|
|
217
|
+
}
|
package/src/types/oas2.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { listOf, mapOf } from '.';
|
|
2
|
+
|
|
3
|
+
import type { NodeType } from '.';
|
|
4
|
+
import type { Oas2NodeType } from './redocly-yaml';
|
|
2
5
|
|
|
3
6
|
const responseCodeRegexp = /^[0-9][0-9Xx]{2}$/;
|
|
4
7
|
|
|
@@ -437,7 +440,7 @@ const Example: NodeType = {
|
|
|
437
440
|
extensionsPrefix: 'x-',
|
|
438
441
|
};
|
|
439
442
|
|
|
440
|
-
export const Oas2Types: Record<
|
|
443
|
+
export const Oas2Types: Record<Oas2NodeType, NodeType> = {
|
|
441
444
|
Root,
|
|
442
445
|
Tag,
|
|
443
446
|
TagList: listOf('Tag'),
|
package/src/types/oas3.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { listOf, mapOf } from '.';
|
|
2
2
|
import { isMappingRef } from '../ref-utils';
|
|
3
|
+
|
|
4
|
+
import type { NodeType } from '.';
|
|
5
|
+
import type { Oas3NodeType } from './redocly-yaml';
|
|
6
|
+
|
|
3
7
|
const responseCodeRegexp = /^[0-9][0-9Xx]{2}$/;
|
|
4
8
|
|
|
5
9
|
const Root: NodeType = {
|
|
@@ -531,7 +535,7 @@ const XUsePkce: NodeType = {
|
|
|
531
535
|
},
|
|
532
536
|
};
|
|
533
537
|
|
|
534
|
-
export const Oas3Types: Record<
|
|
538
|
+
export const Oas3Types: Record<Oas3NodeType, NodeType> = {
|
|
535
539
|
Root,
|
|
536
540
|
Tag,
|
|
537
541
|
TagList: listOf('Tag'),
|
package/src/types/oas3_1.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { listOf, mapOf } from '.';
|
|
2
2
|
import { Oas3Types } from './oas3';
|
|
3
3
|
|
|
4
|
+
import type { NodeType } from '.';
|
|
5
|
+
import type { Oas3_1NodeType } from './redocly-yaml';
|
|
6
|
+
|
|
4
7
|
const Root: NodeType = {
|
|
5
8
|
properties: {
|
|
6
9
|
openapi: null,
|
|
@@ -262,7 +265,7 @@ const SecurityScheme: NodeType = {
|
|
|
262
265
|
extensionsPrefix: 'x-',
|
|
263
266
|
};
|
|
264
267
|
|
|
265
|
-
export const Oas3_1Types: Record<
|
|
268
|
+
export const Oas3_1Types: Record<Oas3_1NodeType, NodeType> = {
|
|
266
269
|
...Oas3Types,
|
|
267
270
|
Info,
|
|
268
271
|
Root,
|
|
@@ -3,8 +3,10 @@ import {
|
|
|
3
3
|
AuthProviderType,
|
|
4
4
|
DEFAULT_TEAM_CLAIM_NAME,
|
|
5
5
|
} from '../config';
|
|
6
|
+
import { themeConfigSchema } from './theme-config';
|
|
6
7
|
|
|
7
|
-
import type {
|
|
8
|
+
import type { FromSchema } from 'json-schema-to-ts';
|
|
9
|
+
import type { ThemeConfig } from './theme-config';
|
|
8
10
|
|
|
9
11
|
const oidcIssuerMetadataSchema = {
|
|
10
12
|
type: 'object',
|
|
@@ -23,10 +25,11 @@ const oidcProviderConfigSchema = {
|
|
|
23
25
|
properties: {
|
|
24
26
|
type: { type: 'string', const: AuthProviderType.OIDC },
|
|
25
27
|
title: { type: 'string' },
|
|
28
|
+
pkce: { type: 'boolean', default: false },
|
|
26
29
|
configurationUrl: { type: 'string', minLength: 1 },
|
|
27
30
|
configuration: oidcIssuerMetadataSchema,
|
|
28
31
|
clientId: { type: 'string', minLength: 1 },
|
|
29
|
-
clientSecret: { type: 'string', minLength:
|
|
32
|
+
clientSecret: { type: 'string', minLength: 0 },
|
|
30
33
|
teamsClaimName: { type: 'string' },
|
|
31
34
|
teamsClaimMap: { type: 'object', additionalProperties: { type: 'string' } },
|
|
32
35
|
defaultTeams: { type: 'array', items: { type: 'string' } },
|
|
@@ -36,7 +39,7 @@ const oidcProviderConfigSchema = {
|
|
|
36
39
|
tokenRequestCustomParams: { type: 'object', additionalProperties: { type: 'string' } },
|
|
37
40
|
audience: { type: 'array', items: { type: 'string' } },
|
|
38
41
|
},
|
|
39
|
-
required: ['type', 'clientId'
|
|
42
|
+
required: ['type', 'clientId'],
|
|
40
43
|
oneOf: [{ required: ['configurationUrl'] }, { required: ['configuration'] }],
|
|
41
44
|
additionalProperties: false,
|
|
42
45
|
} as const;
|
|
@@ -87,11 +90,27 @@ const authProviderConfigSchema = {
|
|
|
87
90
|
discriminator: { propertyName: 'type' },
|
|
88
91
|
} as const;
|
|
89
92
|
|
|
90
|
-
|
|
93
|
+
const ssoOnPremConfigSchema = {
|
|
91
94
|
type: 'object',
|
|
92
|
-
properties: {},
|
|
93
95
|
additionalProperties: authProviderConfigSchema,
|
|
94
|
-
} as
|
|
96
|
+
} as const;
|
|
97
|
+
|
|
98
|
+
const ssoConfigSchema = {
|
|
99
|
+
oneOf: [
|
|
100
|
+
{
|
|
101
|
+
type: 'array',
|
|
102
|
+
items: {
|
|
103
|
+
type: 'string',
|
|
104
|
+
enum: ['REDOCLY', 'CORPORATE', 'GUEST'],
|
|
105
|
+
},
|
|
106
|
+
uniqueItems: true,
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
type: 'string',
|
|
110
|
+
enum: ['REDOCLY', 'CORPORATE', 'GUEST'],
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
} as const;
|
|
95
114
|
|
|
96
115
|
const redirectConfigSchema = {
|
|
97
116
|
type: 'object',
|
|
@@ -99,32 +118,34 @@ const redirectConfigSchema = {
|
|
|
99
118
|
to: { type: 'string' },
|
|
100
119
|
type: { type: 'number', default: 301 },
|
|
101
120
|
},
|
|
102
|
-
|
|
103
|
-
} as
|
|
121
|
+
additionalProperties: false,
|
|
122
|
+
} as const;
|
|
104
123
|
|
|
105
124
|
const redirectsConfigSchema = {
|
|
106
125
|
type: 'object',
|
|
107
|
-
|
|
108
|
-
additionalProperties: 'redirectConfigSchema',
|
|
126
|
+
additionalProperties: redirectConfigSchema,
|
|
109
127
|
default: {},
|
|
110
|
-
} as
|
|
128
|
+
} as const;
|
|
111
129
|
|
|
112
|
-
|
|
130
|
+
const apiConfigSchema = {
|
|
113
131
|
type: 'object',
|
|
114
132
|
properties: {
|
|
115
133
|
root: { type: 'string' },
|
|
134
|
+
output: { type: 'string', pattern: '(.ya?ml|.json)$' },
|
|
116
135
|
rbac: { type: 'object', additionalProperties: true },
|
|
117
136
|
theme: {
|
|
118
137
|
type: 'object',
|
|
119
138
|
properties: {
|
|
120
|
-
openapi:
|
|
139
|
+
openapi: themeConfigSchema.properties.openapi,
|
|
140
|
+
graphql: themeConfigSchema.properties.graphql,
|
|
121
141
|
},
|
|
122
142
|
additionalProperties: false,
|
|
123
143
|
},
|
|
124
144
|
title: { type: 'string' },
|
|
125
145
|
metadata: { type: 'object', additionalProperties: true },
|
|
146
|
+
rules: { type: 'object', additionalProperties: true },
|
|
147
|
+
decorators: { type: 'object', additionalProperties: true },
|
|
126
148
|
},
|
|
127
|
-
additionalProperties: true,
|
|
128
149
|
required: ['root'],
|
|
129
150
|
} as const;
|
|
130
151
|
|
|
@@ -140,7 +161,9 @@ const seoConfigSchema = {
|
|
|
140
161
|
description: { type: 'string' },
|
|
141
162
|
siteUrl: { type: 'string' },
|
|
142
163
|
image: { type: 'string' },
|
|
143
|
-
keywords: {
|
|
164
|
+
keywords: {
|
|
165
|
+
oneOf: [{ type: 'array', items: { type: 'string' } }, { type: 'string' }],
|
|
166
|
+
},
|
|
144
167
|
lang: { type: 'string' },
|
|
145
168
|
jsonLd: { type: 'object' },
|
|
146
169
|
meta: {
|
|
@@ -156,21 +179,25 @@ const seoConfigSchema = {
|
|
|
156
179
|
},
|
|
157
180
|
},
|
|
158
181
|
},
|
|
182
|
+
additionalProperties: false,
|
|
159
183
|
} as const;
|
|
160
184
|
|
|
161
|
-
const rbacScopeItemsSchema = {
|
|
162
|
-
type: 'object',
|
|
163
|
-
properties: {},
|
|
164
|
-
additionalProperties: { type: 'string' },
|
|
165
|
-
} as NodeType;
|
|
185
|
+
const rbacScopeItemsSchema = { type: 'object', additionalProperties: { type: 'string' } } as const;
|
|
166
186
|
|
|
167
187
|
const rbacConfigSchema = {
|
|
168
188
|
type: 'object',
|
|
169
189
|
properties: {
|
|
170
|
-
|
|
190
|
+
cms: rbacScopeItemsSchema,
|
|
191
|
+
content: {
|
|
192
|
+
type: 'object',
|
|
193
|
+
properties: {
|
|
194
|
+
'**': rbacScopeItemsSchema,
|
|
195
|
+
},
|
|
196
|
+
additionalProperties: rbacScopeItemsSchema,
|
|
197
|
+
},
|
|
171
198
|
},
|
|
172
199
|
additionalProperties: rbacScopeItemsSchema,
|
|
173
|
-
} as
|
|
200
|
+
} as const;
|
|
174
201
|
|
|
175
202
|
const graviteeAdapterConfigSchema = {
|
|
176
203
|
type: 'object',
|
|
@@ -246,13 +273,14 @@ const devOnboardingAdapterConfigSchema = {
|
|
|
246
273
|
const devOnboardingConfigSchema = {
|
|
247
274
|
type: 'object',
|
|
248
275
|
required: ['adapters'],
|
|
276
|
+
additionalProperties: false,
|
|
249
277
|
properties: {
|
|
250
278
|
adapters: {
|
|
251
279
|
type: 'array',
|
|
252
280
|
items: devOnboardingAdapterConfigSchema,
|
|
253
281
|
},
|
|
254
282
|
},
|
|
255
|
-
} as
|
|
283
|
+
} as const;
|
|
256
284
|
|
|
257
285
|
const i18ConfigSchema = {
|
|
258
286
|
type: 'object',
|
|
@@ -276,8 +304,9 @@ const i18ConfigSchema = {
|
|
|
276
304
|
},
|
|
277
305
|
},
|
|
278
306
|
},
|
|
279
|
-
|
|
280
|
-
|
|
307
|
+
additionalProperties: false,
|
|
308
|
+
required: ['defaultLocale'],
|
|
309
|
+
} as const;
|
|
281
310
|
|
|
282
311
|
const responseHeaderSchema = {
|
|
283
312
|
type: 'object',
|
|
@@ -289,25 +318,13 @@ const responseHeaderSchema = {
|
|
|
289
318
|
required: ['name', 'value'],
|
|
290
319
|
} as const;
|
|
291
320
|
|
|
292
|
-
|
|
293
|
-
seoConfigSchema,
|
|
294
|
-
rbacConfigSchema,
|
|
295
|
-
rbacScopeItemsSchema,
|
|
296
|
-
ssoConfigSchema,
|
|
297
|
-
devOnboardingConfigSchema,
|
|
298
|
-
i18ConfigSchema,
|
|
299
|
-
redirectsConfigSchema,
|
|
300
|
-
redirectConfigSchema,
|
|
301
|
-
// TODO: Extract other types that need to be linted in the config
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
export const redoclyConfigSchema = {
|
|
321
|
+
const redoclyConfigSchema = {
|
|
305
322
|
type: 'object',
|
|
306
323
|
properties: {
|
|
307
324
|
licenseKey: { type: 'string' },
|
|
308
|
-
redirects:
|
|
309
|
-
seo:
|
|
310
|
-
rbac:
|
|
325
|
+
redirects: redirectsConfigSchema,
|
|
326
|
+
seo: seoConfigSchema,
|
|
327
|
+
rbac: rbacConfigSchema,
|
|
311
328
|
responseHeaders: {
|
|
312
329
|
type: 'object',
|
|
313
330
|
additionalProperties: {
|
|
@@ -329,38 +346,71 @@ export const redoclyConfigSchema = {
|
|
|
329
346
|
type: 'object',
|
|
330
347
|
additionalProperties: apiConfigSchema,
|
|
331
348
|
},
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
349
|
+
ssoOnPrem: ssoOnPremConfigSchema,
|
|
350
|
+
sso: ssoConfigSchema,
|
|
351
|
+
residency: { type: 'string' },
|
|
352
|
+
developerOnboarding: devOnboardingConfigSchema,
|
|
353
|
+
i18n: i18ConfigSchema,
|
|
335
354
|
metadata: metadataConfigSchema,
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
export const environmentSchema = {
|
|
341
|
-
oneOf: [
|
|
342
|
-
{ ...redoclyConfigSchema, additionalProperties: false },
|
|
343
|
-
{
|
|
344
|
-
type: 'object',
|
|
345
|
-
properties: {
|
|
346
|
-
$ref: { type: 'string' },
|
|
355
|
+
ignore: {
|
|
356
|
+
type: 'array',
|
|
357
|
+
items: {
|
|
358
|
+
type: 'string',
|
|
347
359
|
},
|
|
348
|
-
required: ['$ref'],
|
|
349
|
-
additionalProperties: false,
|
|
350
360
|
},
|
|
351
|
-
|
|
361
|
+
theme: themeConfigSchema,
|
|
362
|
+
},
|
|
363
|
+
default: { redirects: {} },
|
|
364
|
+
additionalProperties: true,
|
|
365
|
+
} as const;
|
|
366
|
+
|
|
367
|
+
const environmentSchema = {
|
|
368
|
+
...redoclyConfigSchema,
|
|
369
|
+
additionalProperties: false,
|
|
352
370
|
} as const;
|
|
353
371
|
|
|
354
372
|
export const rootRedoclyConfigSchema = {
|
|
355
373
|
...redoclyConfigSchema,
|
|
356
374
|
properties: {
|
|
375
|
+
plugins: {
|
|
376
|
+
type: 'array',
|
|
377
|
+
items: { type: 'string' },
|
|
378
|
+
},
|
|
357
379
|
...redoclyConfigSchema.properties,
|
|
358
380
|
env: {
|
|
359
381
|
type: 'object',
|
|
360
|
-
|
|
361
|
-
additionalProperties: environmentSchema,
|
|
382
|
+
additionalProperties: environmentSchema, // TODO: if we want full validation we need to override apis, theme and the root
|
|
362
383
|
},
|
|
363
384
|
},
|
|
364
385
|
default: {},
|
|
365
|
-
|
|
386
|
+
additionalProperties: false,
|
|
366
387
|
} as const;
|
|
388
|
+
|
|
389
|
+
export type RedoclyConfig<T = ThemeConfig> = FromSchema<typeof rootRedoclyConfigSchema> & {
|
|
390
|
+
theme?: T;
|
|
391
|
+
};
|
|
392
|
+
export type RedirectConfig = FromSchema<typeof redirectConfigSchema>;
|
|
393
|
+
export type RedirectsConfig = FromSchema<typeof redirectsConfigSchema>;
|
|
394
|
+
|
|
395
|
+
export type AuthProviderConfig = FromSchema<typeof authProviderConfigSchema>;
|
|
396
|
+
export type BasicAuthProviderConfig = FromSchema<typeof basicAuthProviderConfigSchema>;
|
|
397
|
+
export type OidcProviderConfig = FromSchema<typeof oidcProviderConfigSchema>;
|
|
398
|
+
export type Saml2ProviderConfig = FromSchema<typeof saml2ProviderConfigSchema>;
|
|
399
|
+
export type SeoConfig = FromSchema<typeof seoConfigSchema>;
|
|
400
|
+
export type RbacConfig = FromSchema<typeof rbacConfigSchema>;
|
|
401
|
+
export type RbacScopeItems = FromSchema<typeof rbacScopeItemsSchema>;
|
|
402
|
+
export type OidcIssuerMetadata = FromSchema<typeof oidcIssuerMetadataSchema>;
|
|
403
|
+
|
|
404
|
+
export type DevOnboardingAdapterConfig = FromSchema<typeof devOnboardingAdapterConfigSchema>;
|
|
405
|
+
export type GraviteeAdapterConfig = FromSchema<typeof graviteeAdapterConfigSchema>;
|
|
406
|
+
export type ApigeeAdapterConfig = FromSchema<
|
|
407
|
+
typeof apigeeXAdapterConfigSchema | typeof apigeeEdgeAdapterConfigSchema
|
|
408
|
+
>;
|
|
409
|
+
export type ApigeeAdapterAuthOauth2 = FromSchema<typeof apigeeAdapterAuthOauth2Schema>;
|
|
410
|
+
export type ApigeeAdapterAuthServiceAccount = FromSchema<
|
|
411
|
+
typeof apigeeAdapterAuthServiceAccountSchema
|
|
412
|
+
>;
|
|
413
|
+
export type SsoConfig = FromSchema<typeof ssoOnPremConfigSchema>;
|
|
414
|
+
export type I18nConfig = FromSchema<typeof i18ConfigSchema>;
|
|
415
|
+
|
|
416
|
+
export type ApiConfig = FromSchema<typeof apiConfigSchema>;
|