@redocly/openapi-core 1.16.0 → 1.17.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 +17 -0
- package/lib/bundle.d.ts +1 -1
- package/lib/config/load.d.ts +12 -3
- package/lib/config/load.js +32 -12
- package/lib/config/utils.d.ts +1 -0
- package/lib/config/utils.js +5 -1
- package/lib/lint.d.ts +1 -0
- package/lib/lint.js +3 -7
- package/lib/oas-types.d.ts +1 -1
- package/lib/types/oas3_1.js +8 -1
- package/lib/types/redocly-yaml.d.ts +4 -2
- package/lib/types/redocly-yaml.js +35 -36
- package/package.json +2 -2
- package/src/__tests__/lint.test.ts +146 -12
- package/src/config/__tests__/load.test.ts +86 -61
- package/src/config/load.ts +49 -23
- package/src/config/utils.ts +4 -0
- package/src/lint.ts +10 -9
- package/src/types/oas3_1.ts +8 -0
- package/src/types/redocly-yaml.ts +33 -33
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -58,6 +58,88 @@ describe('loadConfig', () => {
|
|
|
58
58
|
expect(mockFn).toHaveBeenCalled();
|
|
59
59
|
});
|
|
60
60
|
|
|
61
|
+
it('should resolve config and call processRawConfig', async () => {
|
|
62
|
+
let problems: NormalizedProblem[];
|
|
63
|
+
let doc: any;
|
|
64
|
+
|
|
65
|
+
await loadConfig({
|
|
66
|
+
configPath: path.join(__dirname, './fixtures/resolve-refs-in-config/config-with-refs.yaml'),
|
|
67
|
+
processRawConfig: async ({ document, parsed, resolvedRefMap, config }) => {
|
|
68
|
+
doc = parsed;
|
|
69
|
+
problems = await lintConfig({
|
|
70
|
+
document,
|
|
71
|
+
severity: 'warn',
|
|
72
|
+
resolvedRefMap,
|
|
73
|
+
config,
|
|
74
|
+
});
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
expect(replaceSourceWithRef(problems!, __dirname)).toMatchInlineSnapshot(`
|
|
79
|
+
[
|
|
80
|
+
{
|
|
81
|
+
"from": {
|
|
82
|
+
"pointer": "#/seo",
|
|
83
|
+
"source": "fixtures/resolve-refs-in-config/config-with-refs.yaml",
|
|
84
|
+
},
|
|
85
|
+
"location": [
|
|
86
|
+
{
|
|
87
|
+
"pointer": "#/title",
|
|
88
|
+
"reportOnKey": false,
|
|
89
|
+
"source": "fixtures/resolve-refs-in-config/seo.yaml",
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
"message": "Expected type \`string\` but got \`integer\`.",
|
|
93
|
+
"ruleId": "configuration spec",
|
|
94
|
+
"severity": "warn",
|
|
95
|
+
"suggest": [],
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"from": {
|
|
99
|
+
"pointer": "#/rules",
|
|
100
|
+
"source": "fixtures/resolve-refs-in-config/config-with-refs.yaml",
|
|
101
|
+
},
|
|
102
|
+
"location": [
|
|
103
|
+
{
|
|
104
|
+
"pointer": "#/non-existing-rule",
|
|
105
|
+
"reportOnKey": true,
|
|
106
|
+
"source": "fixtures/resolve-refs-in-config/rules.yaml",
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
"message": "Property \`non-existing-rule\` is not expected here.",
|
|
110
|
+
"ruleId": "configuration spec",
|
|
111
|
+
"severity": "warn",
|
|
112
|
+
"suggest": [],
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"location": [
|
|
116
|
+
{
|
|
117
|
+
"pointer": "#/theme",
|
|
118
|
+
"reportOnKey": false,
|
|
119
|
+
"source": "fixtures/resolve-refs-in-config/config-with-refs.yaml",
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
"message": "Can't resolve $ref: ENOENT: no such file or directory 'fixtures/resolve-refs-in-config/wrong-ref.yaml'",
|
|
123
|
+
"ruleId": "configuration no-unresolved-refs",
|
|
124
|
+
"severity": "warn",
|
|
125
|
+
"suggest": [],
|
|
126
|
+
},
|
|
127
|
+
]
|
|
128
|
+
`);
|
|
129
|
+
expect(doc).toMatchInlineSnapshot(`
|
|
130
|
+
{
|
|
131
|
+
"rules": {
|
|
132
|
+
"info-license": "error",
|
|
133
|
+
"non-existing-rule": "warn",
|
|
134
|
+
},
|
|
135
|
+
"seo": {
|
|
136
|
+
"title": 1,
|
|
137
|
+
},
|
|
138
|
+
"theme": undefined,
|
|
139
|
+
}
|
|
140
|
+
`);
|
|
141
|
+
});
|
|
142
|
+
|
|
61
143
|
it('should call externalRefResolver if such passed', async () => {
|
|
62
144
|
const externalRefResolver = new BaseResolver();
|
|
63
145
|
const resolverSpy = jest.spyOn(externalRefResolver, 'resolveDocument');
|
|
@@ -104,22 +186,16 @@ describe('findConfig', () => {
|
|
|
104
186
|
describe('getConfig', () => {
|
|
105
187
|
jest.spyOn(fs, 'hasOwnProperty').mockImplementation(() => false);
|
|
106
188
|
it('should return empty object if there is no configPath and config file is not found', () => {
|
|
107
|
-
expect(getConfig()).toEqual(Promise.resolve({}));
|
|
189
|
+
expect(getConfig()).toEqual(Promise.resolve({ rawConfig: {} }));
|
|
108
190
|
});
|
|
109
191
|
|
|
110
192
|
it('should resolve refs in config', async () => {
|
|
111
193
|
let problems: NormalizedProblem[];
|
|
112
|
-
|
|
194
|
+
|
|
195
|
+
const { rawConfig } = await getConfig({
|
|
113
196
|
configPath: path.join(__dirname, './fixtures/resolve-refs-in-config/config-with-refs.yaml'),
|
|
114
|
-
processRawConfig: async (config, resolvedRefMap) => {
|
|
115
|
-
problems = await lintConfig({
|
|
116
|
-
document: config,
|
|
117
|
-
severity: 'warn',
|
|
118
|
-
resolvedRefMap,
|
|
119
|
-
});
|
|
120
|
-
},
|
|
121
197
|
});
|
|
122
|
-
expect(
|
|
198
|
+
expect(rawConfig).toEqual({
|
|
123
199
|
seo: {
|
|
124
200
|
title: 1,
|
|
125
201
|
},
|
|
@@ -130,57 +206,6 @@ describe('getConfig', () => {
|
|
|
130
206
|
},
|
|
131
207
|
},
|
|
132
208
|
});
|
|
133
|
-
expect(replaceSourceWithRef(problems!, __dirname)).toMatchInlineSnapshot(`
|
|
134
|
-
[
|
|
135
|
-
{
|
|
136
|
-
"from": {
|
|
137
|
-
"pointer": "#/seo",
|
|
138
|
-
"source": "fixtures/resolve-refs-in-config/config-with-refs.yaml",
|
|
139
|
-
},
|
|
140
|
-
"location": [
|
|
141
|
-
{
|
|
142
|
-
"pointer": "#/title",
|
|
143
|
-
"reportOnKey": false,
|
|
144
|
-
"source": "fixtures/resolve-refs-in-config/seo.yaml",
|
|
145
|
-
},
|
|
146
|
-
],
|
|
147
|
-
"message": "Expected type \`string\` but got \`integer\`.",
|
|
148
|
-
"ruleId": "configuration spec",
|
|
149
|
-
"severity": "warn",
|
|
150
|
-
"suggest": [],
|
|
151
|
-
},
|
|
152
|
-
{
|
|
153
|
-
"from": {
|
|
154
|
-
"pointer": "#/rules",
|
|
155
|
-
"source": "fixtures/resolve-refs-in-config/config-with-refs.yaml",
|
|
156
|
-
},
|
|
157
|
-
"location": [
|
|
158
|
-
{
|
|
159
|
-
"pointer": "#/non-existing-rule",
|
|
160
|
-
"reportOnKey": true,
|
|
161
|
-
"source": "fixtures/resolve-refs-in-config/rules.yaml",
|
|
162
|
-
},
|
|
163
|
-
],
|
|
164
|
-
"message": "Property \`non-existing-rule\` is not expected here.",
|
|
165
|
-
"ruleId": "configuration spec",
|
|
166
|
-
"severity": "warn",
|
|
167
|
-
"suggest": [],
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
"location": [
|
|
171
|
-
{
|
|
172
|
-
"pointer": "#/theme",
|
|
173
|
-
"reportOnKey": false,
|
|
174
|
-
"source": "fixtures/resolve-refs-in-config/config-with-refs.yaml",
|
|
175
|
-
},
|
|
176
|
-
],
|
|
177
|
-
"message": "Can't resolve $ref: ENOENT: no such file or directory 'fixtures/resolve-refs-in-config/wrong-ref.yaml'",
|
|
178
|
-
"ruleId": "configuration no-unresolved-refs",
|
|
179
|
-
"severity": "warn",
|
|
180
|
-
"suggest": [],
|
|
181
|
-
},
|
|
182
|
-
]
|
|
183
|
-
`);
|
|
184
209
|
});
|
|
185
210
|
});
|
|
186
211
|
|
package/src/config/load.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { RedoclyClient } from '../redocly';
|
|
|
4
4
|
import { isEmptyObject } from '../utils';
|
|
5
5
|
import { parseYaml } from '../js-yaml';
|
|
6
6
|
import { Config } from './config';
|
|
7
|
-
import { ConfigValidationError, transformConfig } from './utils';
|
|
7
|
+
import { ConfigValidationError, transformConfig, deepCloneMapWithJSON } from './utils';
|
|
8
8
|
import { resolveConfig, resolveConfigFileAndRefs } from './config-resolvers';
|
|
9
9
|
import { bundleConfig } from '../bundle';
|
|
10
10
|
import { BaseResolver } from '../resolve';
|
|
@@ -80,10 +80,12 @@ async function addConfigMetadata({
|
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
export type RawConfigProcessor = (
|
|
84
|
-
|
|
85
|
-
resolvedRefMap: ResolvedRefMap
|
|
86
|
-
|
|
83
|
+
export type RawConfigProcessor = (params: {
|
|
84
|
+
document: Document;
|
|
85
|
+
resolvedRefMap: ResolvedRefMap;
|
|
86
|
+
config: Config;
|
|
87
|
+
parsed: Document['parsed'];
|
|
88
|
+
}) => void | Promise<void>;
|
|
87
89
|
|
|
88
90
|
export async function loadConfig(
|
|
89
91
|
options: {
|
|
@@ -103,12 +105,16 @@ export async function loadConfig(
|
|
|
103
105
|
region,
|
|
104
106
|
externalRefResolver,
|
|
105
107
|
} = options;
|
|
106
|
-
|
|
108
|
+
|
|
109
|
+
const { rawConfig, document, parsed, resolvedRefMap } = await getConfig({
|
|
110
|
+
configPath,
|
|
111
|
+
externalRefResolver,
|
|
112
|
+
});
|
|
107
113
|
|
|
108
114
|
const redoclyClient = isBrowser ? undefined : new RedoclyClient();
|
|
109
115
|
const tokens = redoclyClient && redoclyClient.hasTokens() ? redoclyClient.getAllTokens() : [];
|
|
110
116
|
|
|
111
|
-
|
|
117
|
+
const config = await addConfigMetadata({
|
|
112
118
|
rawConfig,
|
|
113
119
|
customExtends,
|
|
114
120
|
configPath,
|
|
@@ -117,6 +123,24 @@ export async function loadConfig(
|
|
|
117
123
|
region,
|
|
118
124
|
externalRefResolver,
|
|
119
125
|
});
|
|
126
|
+
|
|
127
|
+
if (document && parsed && resolvedRefMap && typeof processRawConfig === 'function') {
|
|
128
|
+
try {
|
|
129
|
+
await processRawConfig({
|
|
130
|
+
document,
|
|
131
|
+
resolvedRefMap,
|
|
132
|
+
config,
|
|
133
|
+
parsed,
|
|
134
|
+
});
|
|
135
|
+
} catch (e) {
|
|
136
|
+
if (e instanceof ConfigValidationError) {
|
|
137
|
+
throw e;
|
|
138
|
+
}
|
|
139
|
+
throw new Error(`Error parsing config file at '${configPath}': ${e.message}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return config;
|
|
120
144
|
}
|
|
121
145
|
|
|
122
146
|
export const CONFIG_FILE_NAMES = ['redocly.yaml', 'redocly.yml', '.redocly.yaml', '.redocly.yml'];
|
|
@@ -139,31 +163,33 @@ export function findConfig(dir?: string): string | undefined {
|
|
|
139
163
|
export async function getConfig(
|
|
140
164
|
options: {
|
|
141
165
|
configPath?: string;
|
|
142
|
-
processRawConfig?: RawConfigProcessor;
|
|
143
166
|
externalRefResolver?: BaseResolver;
|
|
144
167
|
} = {}
|
|
145
|
-
): Promise<
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
168
|
+
): Promise<{
|
|
169
|
+
rawConfig: RawConfig;
|
|
170
|
+
document?: Document;
|
|
171
|
+
parsed?: Document['parsed'];
|
|
172
|
+
resolvedRefMap?: ResolvedRefMap;
|
|
173
|
+
}> {
|
|
174
|
+
const { configPath = findConfig(), externalRefResolver = new BaseResolver() } = options;
|
|
175
|
+
if (!configPath) return { rawConfig: {} };
|
|
152
176
|
|
|
153
177
|
try {
|
|
154
178
|
const { document, resolvedRefMap } = await resolveConfigFileAndRefs({
|
|
155
179
|
configPath,
|
|
156
180
|
externalRefResolver,
|
|
157
181
|
});
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
return
|
|
182
|
+
|
|
183
|
+
const bundledRefMap = deepCloneMapWithJSON(resolvedRefMap);
|
|
184
|
+
const parsed = await bundleConfig(JSON.parse(JSON.stringify(document)), bundledRefMap);
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
rawConfig: transformConfig(parsed),
|
|
188
|
+
document,
|
|
189
|
+
parsed,
|
|
190
|
+
resolvedRefMap,
|
|
191
|
+
};
|
|
163
192
|
} catch (e) {
|
|
164
|
-
if (e instanceof ConfigValidationError) {
|
|
165
|
-
throw e;
|
|
166
|
-
}
|
|
167
193
|
throw new Error(`Error parsing config file at '${configPath}': ${e.message}`);
|
|
168
194
|
}
|
|
169
195
|
}
|
package/src/config/utils.ts
CHANGED
|
@@ -364,3 +364,7 @@ export function getUniquePlugins(plugins: Plugin[]): Plugin[] {
|
|
|
364
364
|
}
|
|
365
365
|
|
|
366
366
|
export class ConfigValidationError extends Error {}
|
|
367
|
+
|
|
368
|
+
export function deepCloneMapWithJSON<K, V>(originalMap: Map<K, V>): Map<K, V> {
|
|
369
|
+
return new Map(JSON.parse(JSON.stringify([...originalMap])));
|
|
370
|
+
}
|
package/src/lint.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { BaseResolver, resolveDocument, makeDocumentFromString } from './resolve';
|
|
2
2
|
import { normalizeVisitors } from './visitors';
|
|
3
3
|
import { walkDocument } from './walk';
|
|
4
|
-
import { StyleguideConfig, Config, initRules
|
|
4
|
+
import { StyleguideConfig, Config, initRules } from './config';
|
|
5
5
|
import { normalizeTypes } from './types';
|
|
6
6
|
import { releaseAjvInstance } from './rules/ajv';
|
|
7
7
|
import { SpecVersion, getMajorSpecVersion, detectSpec, getTypes } from './oas-types';
|
|
8
|
-
import {
|
|
8
|
+
import { createConfigTypes } from './types/redocly-yaml';
|
|
9
9
|
import { Spec } from './rules/common/spec';
|
|
10
10
|
import { NoUnresolvedRefs } from './rules/no-unresolved-refs';
|
|
11
11
|
|
|
@@ -13,6 +13,7 @@ import type { Document, ResolvedRefMap } from './resolve';
|
|
|
13
13
|
import type { ProblemSeverity, WalkContext } from './walk';
|
|
14
14
|
import type { NodeType } from './types';
|
|
15
15
|
import type { NestedVisitObject, Oas3Visitor, RuleInstanceConfig } from './visitors';
|
|
16
|
+
import { rootRedoclyConfigSchema } from '@redocly/config';
|
|
16
17
|
|
|
17
18
|
export async function lint(opts: {
|
|
18
19
|
ref: string;
|
|
@@ -109,25 +110,25 @@ export async function lintDocument(opts: {
|
|
|
109
110
|
|
|
110
111
|
export async function lintConfig(opts: {
|
|
111
112
|
document: Document;
|
|
113
|
+
config: Config;
|
|
112
114
|
resolvedRefMap?: ResolvedRefMap;
|
|
113
115
|
severity?: ProblemSeverity;
|
|
114
116
|
externalRefResolver?: BaseResolver;
|
|
115
117
|
externalConfigTypes?: Record<string, NodeType>;
|
|
116
118
|
}) {
|
|
117
|
-
const { document, severity, externalRefResolver = new BaseResolver() } = opts;
|
|
119
|
+
const { document, severity, externalRefResolver = new BaseResolver(), config } = opts;
|
|
118
120
|
|
|
119
121
|
const ctx: WalkContext = {
|
|
120
122
|
problems: [],
|
|
121
123
|
oasVersion: SpecVersion.OAS3_0,
|
|
122
124
|
visitorsData: {},
|
|
123
125
|
};
|
|
124
|
-
const plugins = resolvePlugins([defaultPlugin]);
|
|
125
|
-
const config = new StyleguideConfig({
|
|
126
|
-
plugins,
|
|
127
|
-
rules: { spec: 'error' },
|
|
128
|
-
});
|
|
129
126
|
|
|
130
|
-
const types = normalizeTypes(
|
|
127
|
+
const types = normalizeTypes(
|
|
128
|
+
opts.externalConfigTypes || createConfigTypes(rootRedoclyConfigSchema, config),
|
|
129
|
+
{ doNotResolveExamples: config.styleguide.doNotResolveExamples }
|
|
130
|
+
);
|
|
131
|
+
|
|
131
132
|
const rules: (RuleInstanceConfig & {
|
|
132
133
|
visitor: NestedVisitObject<unknown, Oas3Visitor | Oas3Visitor[]>;
|
|
133
134
|
})[] = [
|
package/src/types/oas3_1.ts
CHANGED
|
@@ -134,6 +134,7 @@ const Schema: NodeType = {
|
|
|
134
134
|
then: 'Schema',
|
|
135
135
|
else: 'Schema',
|
|
136
136
|
dependentSchemas: listOf('Schema'),
|
|
137
|
+
dependentRequired: 'DependentRequired',
|
|
137
138
|
prefixItems: listOf('Schema'),
|
|
138
139
|
contains: 'Schema',
|
|
139
140
|
minContains: { type: 'integer', minimum: 0 },
|
|
@@ -170,6 +171,7 @@ const Schema: NodeType = {
|
|
|
170
171
|
format: { type: 'string' },
|
|
171
172
|
contentEncoding: { type: 'string' },
|
|
172
173
|
contentMediaType: { type: 'string' },
|
|
174
|
+
contentSchema: 'Schema',
|
|
173
175
|
default: null,
|
|
174
176
|
readOnly: { type: 'boolean' },
|
|
175
177
|
writeOnly: { type: 'boolean' },
|
|
@@ -265,6 +267,11 @@ const SecurityScheme: NodeType = {
|
|
|
265
267
|
extensionsPrefix: 'x-',
|
|
266
268
|
};
|
|
267
269
|
|
|
270
|
+
const DependentRequired: NodeType = {
|
|
271
|
+
properties: {},
|
|
272
|
+
additionalProperties: { type: 'array', items: { type: 'string' } },
|
|
273
|
+
};
|
|
274
|
+
|
|
268
275
|
export const Oas3_1Types: Record<Oas3_1NodeType, NodeType> = {
|
|
269
276
|
...Oas3Types,
|
|
270
277
|
Info,
|
|
@@ -276,4 +283,5 @@ export const Oas3_1Types: Record<Oas3_1NodeType, NodeType> = {
|
|
|
276
283
|
NamedPathItems: mapOf('PathItem'),
|
|
277
284
|
SecurityScheme,
|
|
278
285
|
Operation,
|
|
286
|
+
DependentRequired,
|
|
279
287
|
};
|
|
@@ -5,6 +5,8 @@ import { getNodeTypesFromJSONSchema } from './json-schema-adapter';
|
|
|
5
5
|
|
|
6
6
|
import type { NodeType } from '.';
|
|
7
7
|
import type { JSONSchema } from 'json-schema-to-ts';
|
|
8
|
+
import { SpecVersion, getTypes } from '../oas-types';
|
|
9
|
+
import { Config } from '../config';
|
|
8
10
|
|
|
9
11
|
const builtInCommonRules = [
|
|
10
12
|
'spec',
|
|
@@ -218,12 +220,11 @@ const oas3_1NodeTypesList = [
|
|
|
218
220
|
'NamedPathItems',
|
|
219
221
|
'SecurityScheme',
|
|
220
222
|
'Operation',
|
|
223
|
+
'DependentRequired',
|
|
221
224
|
] as const;
|
|
222
225
|
|
|
223
226
|
export type Oas3_1NodeType = typeof oas3_1NodeTypesList[number];
|
|
224
227
|
|
|
225
|
-
const asyncNodeTypesList = ['Message'] as const;
|
|
226
|
-
|
|
227
228
|
const ConfigStyleguide: NodeType = {
|
|
228
229
|
properties: {
|
|
229
230
|
extends: {
|
|
@@ -350,35 +351,28 @@ const Schema: NodeType = {
|
|
|
350
351
|
additionalProperties: {},
|
|
351
352
|
};
|
|
352
353
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
...new Set([
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
return null;
|
|
372
|
-
} else {
|
|
373
|
-
return { type: 'string' };
|
|
374
|
-
}
|
|
354
|
+
function createAssertionDefinitionSubject(nodeNames: string[]): NodeType {
|
|
355
|
+
return {
|
|
356
|
+
properties: {
|
|
357
|
+
type: {
|
|
358
|
+
enum: [...new Set(['any', ...nodeNames, 'SpecExtension'])],
|
|
359
|
+
},
|
|
360
|
+
property: (value: unknown) => {
|
|
361
|
+
if (Array.isArray(value)) {
|
|
362
|
+
return { type: 'array', items: { type: 'string' } };
|
|
363
|
+
} else if (value === null) {
|
|
364
|
+
return null;
|
|
365
|
+
} else {
|
|
366
|
+
return { type: 'string' };
|
|
367
|
+
}
|
|
368
|
+
},
|
|
369
|
+
filterInParentKeys: { type: 'array', items: { type: 'string' } },
|
|
370
|
+
filterOutParentKeys: { type: 'array', items: { type: 'string' } },
|
|
371
|
+
matchParentKeys: { type: 'string' },
|
|
375
372
|
},
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
},
|
|
380
|
-
required: ['type'],
|
|
381
|
-
};
|
|
373
|
+
required: ['type'],
|
|
374
|
+
};
|
|
375
|
+
}
|
|
382
376
|
|
|
383
377
|
const AssertionDefinitionAssertions: NodeType = {
|
|
384
378
|
properties: {
|
|
@@ -1057,7 +1051,13 @@ const ConfigMockServer: NodeType = {
|
|
|
1057
1051
|
},
|
|
1058
1052
|
};
|
|
1059
1053
|
|
|
1060
|
-
export
|
|
1054
|
+
export function createConfigTypes(extraSchemas: JSONSchema, config?: Config) {
|
|
1055
|
+
const nodeNames = Object.values(SpecVersion).flatMap((version) => {
|
|
1056
|
+
const types = config?.styleguide
|
|
1057
|
+
? config.styleguide.extendTypes(getTypes(version), version)
|
|
1058
|
+
: getTypes(version);
|
|
1059
|
+
return Object.keys(types);
|
|
1060
|
+
});
|
|
1061
1061
|
// Create types based on external schemas
|
|
1062
1062
|
const nodeTypes = getNodeTypesFromJSONSchema('rootRedoclyConfigSchema', extraSchemas);
|
|
1063
1063
|
|
|
@@ -1065,9 +1065,10 @@ export const createConfigTypes = (extraSchemas: JSONSchema) => {
|
|
|
1065
1065
|
...CoreConfigTypes,
|
|
1066
1066
|
ConfigRoot: createConfigRoot(nodeTypes), // This is the REAL config root type
|
|
1067
1067
|
ConfigApisProperties: createConfigApisProperties(nodeTypes),
|
|
1068
|
+
AssertionDefinitionSubject: createAssertionDefinitionSubject(nodeNames),
|
|
1068
1069
|
...nodeTypes,
|
|
1069
1070
|
};
|
|
1070
|
-
}
|
|
1071
|
+
}
|
|
1071
1072
|
|
|
1072
1073
|
const CoreConfigTypes: Record<string, NodeType> = {
|
|
1073
1074
|
Assert,
|
|
@@ -1130,7 +1131,6 @@ const CoreConfigTypes: Record<string, NodeType> = {
|
|
|
1130
1131
|
Heading,
|
|
1131
1132
|
Typography,
|
|
1132
1133
|
AssertionDefinitionAssertions,
|
|
1133
|
-
AssertionDefinitionSubject,
|
|
1134
1134
|
};
|
|
1135
1135
|
|
|
1136
1136
|
export const ConfigTypes: Record<string, NodeType> = createConfigTypes(rootRedoclyConfigSchema);
|