@redocly/openapi-core 1.5.0 → 1.6.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.
- package/CHANGELOG.md +6 -0
- package/lib/bundle.d.ts +8 -6
- package/lib/bundle.js +48 -14
- package/lib/config/config-resolvers.d.ts +9 -1
- package/lib/config/config-resolvers.js +22 -1
- package/lib/config/load.d.ts +11 -3
- package/lib/config/load.js +12 -6
- package/lib/lint.d.ts +6 -3
- package/lib/lint.js +14 -3
- package/lib/types/portal-config-schema.d.ts +22 -2465
- package/lib/types/portal-config-schema.js +56 -38
- package/lib/types/redocly-yaml.js +4 -4
- package/lib/visitors.d.ts +5 -5
- package/lib/visitors.js +4 -6
- package/lib/walk.d.ts +3 -3
- package/lib/walk.js +2 -2
- package/package.json +1 -1
- package/src/__tests__/lint.test.ts +2 -2
- package/src/bundle.ts +67 -26
- package/src/config/__tests__/fixtures/resolve-refs-in-config/config-with-refs.yaml +8 -0
- package/src/config/__tests__/fixtures/resolve-refs-in-config/rules.yaml +2 -0
- package/src/config/__tests__/fixtures/resolve-refs-in-config/seo.yaml +1 -0
- package/src/config/__tests__/load.test.ts +80 -1
- package/src/config/config-resolvers.ts +41 -11
- package/src/config/load.ts +36 -19
- package/src/lint.ts +32 -10
- package/src/types/portal-config-schema.ts +65 -42
- package/src/types/redocly-yaml.ts +2 -4
- package/src/visitors.ts +20 -22
- package/src/walk.ts +8 -8
- package/tsconfig.tsbuildinfo +1 -1
package/src/config/load.ts
CHANGED
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
import * as fs from 'fs';
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import { RedoclyClient } from '../redocly';
|
|
4
|
-
import { isEmptyObject,
|
|
4
|
+
import { isEmptyObject, doesYamlFileExist } from '../utils';
|
|
5
5
|
import { parseYaml } from '../js-yaml';
|
|
6
6
|
import { Config, DOMAINS } from './config';
|
|
7
7
|
import { ConfigValidationError, transformConfig } from './utils';
|
|
8
|
-
import { resolveConfig } from './config-resolvers';
|
|
8
|
+
import { resolveConfig, resolveConfigFileAndRefs } from './config-resolvers';
|
|
9
|
+
import { bundleConfig } from '../bundle';
|
|
9
10
|
|
|
10
|
-
import type {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
RawUniversalConfig,
|
|
15
|
-
Region,
|
|
16
|
-
} from './types';
|
|
17
|
-
import { RegionalTokenWithValidity } from '../redocly/redocly-client-types';
|
|
11
|
+
import type { Document } from '../resolve';
|
|
12
|
+
import type { RegionalTokenWithValidity } from '../redocly/redocly-client-types';
|
|
13
|
+
import type { RawConfig, RawUniversalConfig, Region } from './types';
|
|
14
|
+
import type { BaseResolver, ResolvedRefMap } from '../resolve';
|
|
18
15
|
|
|
19
16
|
async function addConfigMetadata({
|
|
20
17
|
rawConfig,
|
|
@@ -73,17 +70,30 @@ async function addConfigMetadata({
|
|
|
73
70
|
);
|
|
74
71
|
}
|
|
75
72
|
|
|
73
|
+
export type RawConfigProcessor = (
|
|
74
|
+
rawConfig: Document,
|
|
75
|
+
resolvedRefMap: ResolvedRefMap
|
|
76
|
+
) => void | Promise<void>;
|
|
77
|
+
|
|
76
78
|
export async function loadConfig(
|
|
77
79
|
options: {
|
|
78
80
|
configPath?: string;
|
|
79
81
|
customExtends?: string[];
|
|
80
|
-
processRawConfig?:
|
|
82
|
+
processRawConfig?: RawConfigProcessor;
|
|
83
|
+
externalRefResolver?: BaseResolver;
|
|
81
84
|
files?: string[];
|
|
82
85
|
region?: Region;
|
|
83
86
|
} = {}
|
|
84
87
|
): Promise<Config> {
|
|
85
|
-
const {
|
|
86
|
-
|
|
88
|
+
const {
|
|
89
|
+
configPath = findConfig(),
|
|
90
|
+
customExtends,
|
|
91
|
+
processRawConfig,
|
|
92
|
+
files,
|
|
93
|
+
region,
|
|
94
|
+
externalRefResolver,
|
|
95
|
+
} = options;
|
|
96
|
+
const rawConfig = await getConfig({ configPath, processRawConfig, externalRefResolver });
|
|
87
97
|
|
|
88
98
|
const redoclyClient = new RedoclyClient();
|
|
89
99
|
const tokens = await redoclyClient.getTokens();
|
|
@@ -116,17 +126,24 @@ export function findConfig(dir?: string): string | undefined {
|
|
|
116
126
|
}
|
|
117
127
|
|
|
118
128
|
export async function getConfig(
|
|
119
|
-
|
|
120
|
-
|
|
129
|
+
options: {
|
|
130
|
+
configPath?: string;
|
|
131
|
+
processRawConfig?: RawConfigProcessor;
|
|
132
|
+
externalRefResolver?: BaseResolver;
|
|
133
|
+
} = {}
|
|
121
134
|
): Promise<RawConfig> {
|
|
135
|
+
const { configPath = findConfig(), processRawConfig, externalRefResolver } = options;
|
|
122
136
|
if (!configPath || !doesYamlFileExist(configPath)) return {};
|
|
123
137
|
try {
|
|
124
|
-
const
|
|
125
|
-
|
|
138
|
+
const { document, resolvedRefMap } = await resolveConfigFileAndRefs({
|
|
139
|
+
configPath,
|
|
140
|
+
externalRefResolver,
|
|
141
|
+
});
|
|
126
142
|
if (typeof processRawConfig === 'function') {
|
|
127
|
-
await processRawConfig(
|
|
143
|
+
await processRawConfig(document, resolvedRefMap);
|
|
128
144
|
}
|
|
129
|
-
|
|
145
|
+
const bundledConfig = await bundleConfig(document, resolvedRefMap);
|
|
146
|
+
return transformConfig(bundledConfig);
|
|
130
147
|
} catch (e) {
|
|
131
148
|
if (e instanceof ConfigValidationError) {
|
|
132
149
|
throw e;
|
package/src/lint.ts
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
|
-
import { BaseResolver, resolveDocument,
|
|
1
|
+
import { BaseResolver, resolveDocument, makeDocumentFromString } from './resolve';
|
|
2
2
|
import { normalizeVisitors } from './visitors';
|
|
3
|
-
import {
|
|
4
|
-
import { ProblemSeverity, WalkContext, walkDocument } from './walk';
|
|
3
|
+
import { walkDocument } from './walk';
|
|
5
4
|
import { StyleguideConfig, Config, initRules, defaultPlugin, resolvePlugins } from './config';
|
|
6
5
|
import { normalizeTypes } from './types';
|
|
7
6
|
import { releaseAjvInstance } from './rules/ajv';
|
|
8
7
|
import { SpecVersion, getMajorSpecVersion, detectSpec, getTypes } from './oas-types';
|
|
9
8
|
import { ConfigTypes } from './types/redocly-yaml';
|
|
10
9
|
import { Spec } from './rules/common/spec';
|
|
10
|
+
import { NoUnresolvedRefs } from './rules/no-unresolved-refs';
|
|
11
|
+
|
|
12
|
+
import type { Document, ResolvedRefMap } from './resolve';
|
|
13
|
+
import type { ProblemSeverity, WalkContext } from './walk';
|
|
14
|
+
import type { NodeType } from './types';
|
|
15
|
+
import type { NestedVisitObject, Oas3Visitor, RuleInstanceConfig } from './visitors';
|
|
11
16
|
|
|
12
17
|
export async function lint(opts: {
|
|
13
18
|
ref: string;
|
|
@@ -102,8 +107,13 @@ export async function lintDocument(opts: {
|
|
|
102
107
|
return ctx.problems.map((problem) => config.addProblemToIgnore(problem));
|
|
103
108
|
}
|
|
104
109
|
|
|
105
|
-
export async function lintConfig(opts: {
|
|
106
|
-
|
|
110
|
+
export async function lintConfig(opts: {
|
|
111
|
+
document: Document;
|
|
112
|
+
resolvedRefMap?: ResolvedRefMap;
|
|
113
|
+
severity?: ProblemSeverity;
|
|
114
|
+
externalRefResolver?: BaseResolver;
|
|
115
|
+
}) {
|
|
116
|
+
const { document, severity, externalRefResolver = new BaseResolver() } = opts;
|
|
107
117
|
|
|
108
118
|
const ctx: WalkContext = {
|
|
109
119
|
problems: [],
|
|
@@ -117,21 +127,33 @@ export async function lintConfig(opts: { document: Document; severity?: ProblemS
|
|
|
117
127
|
});
|
|
118
128
|
|
|
119
129
|
const types = normalizeTypes(ConfigTypes, config);
|
|
120
|
-
const rules
|
|
130
|
+
const rules: (RuleInstanceConfig & {
|
|
131
|
+
visitor: NestedVisitObject<unknown, Oas3Visitor | Oas3Visitor[]>;
|
|
132
|
+
})[] = [
|
|
121
133
|
{
|
|
122
134
|
severity: severity || 'error',
|
|
123
135
|
ruleId: 'configuration spec',
|
|
124
136
|
visitor: Spec({ severity: 'error' }),
|
|
125
137
|
},
|
|
138
|
+
{
|
|
139
|
+
severity: severity || 'error',
|
|
140
|
+
ruleId: 'configuration no-unresolved-refs',
|
|
141
|
+
visitor: NoUnresolvedRefs({ severity: 'error' }),
|
|
142
|
+
},
|
|
126
143
|
];
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
|
|
144
|
+
const normalizedVisitors = normalizeVisitors(rules, types);
|
|
145
|
+
const resolvedRefMap =
|
|
146
|
+
opts.resolvedRefMap ||
|
|
147
|
+
(await resolveDocument({
|
|
148
|
+
rootDocument: document,
|
|
149
|
+
rootType: types.ConfigRoot,
|
|
150
|
+
externalRefResolver,
|
|
151
|
+
}));
|
|
130
152
|
walkDocument({
|
|
131
153
|
document,
|
|
132
154
|
rootType: types.ConfigRoot,
|
|
133
155
|
normalizedVisitors,
|
|
134
|
-
resolvedRefMap
|
|
156
|
+
resolvedRefMap,
|
|
135
157
|
ctx,
|
|
136
158
|
});
|
|
137
159
|
|
|
@@ -4,6 +4,8 @@ import {
|
|
|
4
4
|
DEFAULT_TEAM_CLAIM_NAME,
|
|
5
5
|
} from '../config';
|
|
6
6
|
|
|
7
|
+
import type { NodeType } from '.';
|
|
8
|
+
|
|
7
9
|
const oidcIssuerMetadataSchema = {
|
|
8
10
|
type: 'object',
|
|
9
11
|
properties: {
|
|
@@ -87,8 +89,9 @@ const authProviderConfigSchema = {
|
|
|
87
89
|
|
|
88
90
|
export const ssoConfigSchema = {
|
|
89
91
|
type: 'object',
|
|
92
|
+
properties: {},
|
|
90
93
|
additionalProperties: authProviderConfigSchema,
|
|
91
|
-
} as
|
|
94
|
+
} as NodeType;
|
|
92
95
|
|
|
93
96
|
const redirectConfigSchema = {
|
|
94
97
|
type: 'object',
|
|
@@ -97,8 +100,14 @@ const redirectConfigSchema = {
|
|
|
97
100
|
type: { type: 'number', default: 301 },
|
|
98
101
|
},
|
|
99
102
|
required: ['to'],
|
|
100
|
-
|
|
101
|
-
|
|
103
|
+
} as NodeType;
|
|
104
|
+
|
|
105
|
+
const redirectsConfigSchema = {
|
|
106
|
+
type: 'object',
|
|
107
|
+
properties: {},
|
|
108
|
+
additionalProperties: 'redirectConfigSchema',
|
|
109
|
+
default: {},
|
|
110
|
+
} as NodeType;
|
|
102
111
|
|
|
103
112
|
export const apiConfigSchema = {
|
|
104
113
|
type: 'object',
|
|
@@ -147,18 +156,21 @@ const seoConfigSchema = {
|
|
|
147
156
|
},
|
|
148
157
|
},
|
|
149
158
|
},
|
|
150
|
-
additionalProperties: false,
|
|
151
159
|
} as const;
|
|
152
160
|
|
|
153
|
-
const rbacScopeItemsSchema = {
|
|
161
|
+
const rbacScopeItemsSchema = {
|
|
162
|
+
type: 'object',
|
|
163
|
+
properties: {},
|
|
164
|
+
additionalProperties: { type: 'string' },
|
|
165
|
+
} as NodeType;
|
|
154
166
|
|
|
155
167
|
const rbacConfigSchema = {
|
|
156
168
|
type: 'object',
|
|
157
169
|
properties: {
|
|
158
|
-
defaults: rbacScopeItemsSchema,
|
|
170
|
+
defaults: 'rbacScopeItemsSchema',
|
|
159
171
|
},
|
|
160
172
|
additionalProperties: rbacScopeItemsSchema,
|
|
161
|
-
} as
|
|
173
|
+
} as NodeType;
|
|
162
174
|
|
|
163
175
|
const graviteeAdapterConfigSchema = {
|
|
164
176
|
type: 'object',
|
|
@@ -234,14 +246,38 @@ const devOnboardingAdapterConfigSchema = {
|
|
|
234
246
|
const devOnboardingConfigSchema = {
|
|
235
247
|
type: 'object',
|
|
236
248
|
required: ['adapters'],
|
|
237
|
-
additionalProperties: false,
|
|
238
249
|
properties: {
|
|
239
250
|
adapters: {
|
|
240
251
|
type: 'array',
|
|
241
252
|
items: devOnboardingAdapterConfigSchema,
|
|
242
253
|
},
|
|
243
254
|
},
|
|
244
|
-
} as
|
|
255
|
+
} as NodeType;
|
|
256
|
+
|
|
257
|
+
const i18ConfigSchema = {
|
|
258
|
+
type: 'object',
|
|
259
|
+
properties: {
|
|
260
|
+
defaultLocale: {
|
|
261
|
+
type: 'string',
|
|
262
|
+
},
|
|
263
|
+
locales: {
|
|
264
|
+
type: 'array',
|
|
265
|
+
items: {
|
|
266
|
+
type: 'object',
|
|
267
|
+
properties: {
|
|
268
|
+
code: {
|
|
269
|
+
type: 'string',
|
|
270
|
+
},
|
|
271
|
+
name: {
|
|
272
|
+
type: 'string',
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
required: ['code'],
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
required: ['defaultLocale', 'locales'],
|
|
280
|
+
} as NodeType;
|
|
245
281
|
|
|
246
282
|
const responseHeaderSchema = {
|
|
247
283
|
type: 'object',
|
|
@@ -253,14 +289,25 @@ const responseHeaderSchema = {
|
|
|
253
289
|
required: ['name', 'value'],
|
|
254
290
|
} as const;
|
|
255
291
|
|
|
292
|
+
export const PortalConfigNodeTypes: Record<string, NodeType> = {
|
|
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
|
+
|
|
256
304
|
export const redoclyConfigSchema = {
|
|
257
305
|
type: 'object',
|
|
258
306
|
properties: {
|
|
259
307
|
licenseKey: { type: 'string' },
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
rbac: rbacConfigSchema,
|
|
308
|
+
redirects: 'redirectsConfigSchema',
|
|
309
|
+
seo: 'seoConfigSchema',
|
|
310
|
+
rbac: 'rbacConfigSchema',
|
|
264
311
|
responseHeaders: {
|
|
265
312
|
type: 'object',
|
|
266
313
|
additionalProperties: {
|
|
@@ -282,38 +329,13 @@ export const redoclyConfigSchema = {
|
|
|
282
329
|
type: 'object',
|
|
283
330
|
additionalProperties: apiConfigSchema,
|
|
284
331
|
},
|
|
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
|
-
},
|
|
332
|
+
sso: 'ssoConfigSchema',
|
|
333
|
+
developerOnboarding: 'devOnboardingConfigSchema',
|
|
334
|
+
i18n: 'i18ConfigSchema',
|
|
312
335
|
metadata: metadataConfigSchema,
|
|
313
336
|
},
|
|
314
337
|
default: {},
|
|
315
|
-
|
|
316
|
-
} as const;
|
|
338
|
+
} as NodeType;
|
|
317
339
|
|
|
318
340
|
export const environmentSchema = {
|
|
319
341
|
oneOf: [
|
|
@@ -335,6 +357,7 @@ export const rootRedoclyConfigSchema = {
|
|
|
335
357
|
...redoclyConfigSchema.properties,
|
|
336
358
|
env: {
|
|
337
359
|
type: 'object',
|
|
360
|
+
properties: {},
|
|
338
361
|
additionalProperties: environmentSchema,
|
|
339
362
|
},
|
|
340
363
|
},
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { rootRedoclyConfigSchema, apiConfigSchema } from './portal-config-schema';
|
|
2
2
|
import { themeConfigSchema } from './theme-config';
|
|
3
3
|
import { NodeType, listOf } from '.';
|
|
4
|
-
import { Oas3_1Types } from './oas3_1';
|
|
5
4
|
import { omitObjectProps, pickObjectProps, isCustomRuleId } from '../utils';
|
|
5
|
+
import { PortalConfigNodeTypes } from './portal-config-schema';
|
|
6
6
|
|
|
7
7
|
const builtInCommonRules = [
|
|
8
8
|
'spec',
|
|
@@ -236,8 +236,6 @@ const ConfigApisProperties: NodeType = {
|
|
|
236
236
|
type: 'string',
|
|
237
237
|
},
|
|
238
238
|
},
|
|
239
|
-
lint: 'ConfigStyleguide', // deprecated
|
|
240
|
-
styleguide: 'ConfigStyleguide', // deprecated
|
|
241
239
|
...ConfigStyleguide.properties,
|
|
242
240
|
'features.openapi': 'ConfigReferenceDocs', // deprecated
|
|
243
241
|
'features.mockServer': 'ConfigMockServer', // deprecated
|
|
@@ -997,7 +995,6 @@ const ConfigMockServer: NodeType = {
|
|
|
997
995
|
};
|
|
998
996
|
|
|
999
997
|
export const ConfigTypes: Record<string, NodeType> = {
|
|
1000
|
-
...Oas3_1Types,
|
|
1001
998
|
Assert,
|
|
1002
999
|
ConfigRoot,
|
|
1003
1000
|
ConfigApis,
|
|
@@ -1062,4 +1059,5 @@ export const ConfigTypes: Record<string, NodeType> = {
|
|
|
1062
1059
|
Typography,
|
|
1063
1060
|
AssertionDefinitionAssertions,
|
|
1064
1061
|
AssertionDefinitionSubject,
|
|
1062
|
+
...PortalConfigNodeTypes,
|
|
1065
1063
|
};
|
package/src/visitors.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import { SpecExtension } from './types';
|
|
2
|
+
|
|
3
|
+
import type { NormalizedNodeType } from './types';
|
|
4
|
+
import type { Stack } from './utils';
|
|
5
|
+
import type { UserContext, ResolveResult, ProblemSeverity } from './walk';
|
|
6
|
+
import type { Location } from './ref-utils';
|
|
1
7
|
import type {
|
|
2
8
|
Oas3Definition,
|
|
3
9
|
Oas3ExternalDocs,
|
|
@@ -26,7 +32,6 @@ import type {
|
|
|
26
32
|
Oas3Discriminator,
|
|
27
33
|
Oas3Callback,
|
|
28
34
|
} from './typings/openapi';
|
|
29
|
-
|
|
30
35
|
import type {
|
|
31
36
|
Oas2Definition,
|
|
32
37
|
Oas2Tag,
|
|
@@ -44,12 +49,7 @@ import type {
|
|
|
44
49
|
Oas2Parameter,
|
|
45
50
|
Oas2SecurityScheme,
|
|
46
51
|
} from './typings/swagger';
|
|
47
|
-
|
|
48
|
-
import { NormalizedNodeType, SpecExtension } from './types';
|
|
49
|
-
import type { Stack } from './utils';
|
|
50
|
-
import type { UserContext, ResolveResult, ProblemSeverity } from './walk';
|
|
51
|
-
import type { Location } from './ref-utils';
|
|
52
|
-
import { Async2Definition } from './typings/asyncapi';
|
|
52
|
+
import type { Async2Definition } from './typings/asyncapi';
|
|
53
53
|
|
|
54
54
|
export type SkipFunctionContext = Pick<
|
|
55
55
|
UserContext,
|
|
@@ -297,7 +297,7 @@ export type RuleInstanceConfig = {
|
|
|
297
297
|
};
|
|
298
298
|
|
|
299
299
|
export function normalizeVisitors<T extends BaseVisitor>(
|
|
300
|
-
visitorsConfig: (RuleInstanceConfig & { visitor: NestedVisitObject<
|
|
300
|
+
visitorsConfig: (RuleInstanceConfig & { visitor: NestedVisitObject<unknown, T> })[],
|
|
301
301
|
types: Record<keyof T, NormalizedNodeType>
|
|
302
302
|
): NormalizedOasVisitors<T> {
|
|
303
303
|
const normalizedVisitors: NormalizedOasVisitors<T> = {} as any;
|
|
@@ -377,12 +377,10 @@ export function normalizeVisitors<T extends BaseVisitor>(
|
|
|
377
377
|
|
|
378
378
|
function addWeakFromStack(ruleConf: RuleInstanceConfig, stack: NormalizedNodeType[]) {
|
|
379
379
|
for (const interType of stack.slice(1)) {
|
|
380
|
-
(normalizedVisitors as any)[interType.name] =
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
leave: [],
|
|
385
|
-
} as any);
|
|
380
|
+
(normalizedVisitors as any)[interType.name] = normalizedVisitors[interType.name] || {
|
|
381
|
+
enter: [],
|
|
382
|
+
leave: [],
|
|
383
|
+
};
|
|
386
384
|
normalizedVisitors[interType.name].enter.push({
|
|
387
385
|
...ruleConf,
|
|
388
386
|
visit: () => undefined,
|
|
@@ -398,7 +396,7 @@ export function normalizeVisitors<T extends BaseVisitor>(
|
|
|
398
396
|
}
|
|
399
397
|
|
|
400
398
|
function findLegacyVisitorNode<T>(
|
|
401
|
-
visitor: NestedVisitObject<
|
|
399
|
+
visitor: NestedVisitObject<unknown, T>,
|
|
402
400
|
typeName: keyof T | Array<keyof T>
|
|
403
401
|
) {
|
|
404
402
|
if (Array.isArray(typeName)) {
|
|
@@ -411,7 +409,7 @@ export function normalizeVisitors<T extends BaseVisitor>(
|
|
|
411
409
|
|
|
412
410
|
function normalizeVisitorLevel(
|
|
413
411
|
ruleConf: RuleInstanceConfig,
|
|
414
|
-
visitor: NestedVisitObject<
|
|
412
|
+
visitor: NestedVisitObject<unknown, T>,
|
|
415
413
|
parentContext: VisitorLevelContext | null,
|
|
416
414
|
depth = 0
|
|
417
415
|
) {
|
|
@@ -434,14 +432,14 @@ export function normalizeVisitors<T extends BaseVisitor>(
|
|
|
434
432
|
findLegacyVisitorNode(
|
|
435
433
|
visitor,
|
|
436
434
|
legacyTypesMap[typeName as keyof typeof legacyTypesMap] as keyof T
|
|
437
|
-
)) as
|
|
435
|
+
)) as NestedVisitObject<unknown, T>;
|
|
438
436
|
const normalizedTypeVisitor = normalizedVisitors[typeName];
|
|
439
437
|
|
|
440
438
|
if (!typeVisitor) continue;
|
|
441
439
|
|
|
442
|
-
let visitorEnter: VisitFunction<
|
|
443
|
-
let visitorLeave: VisitFunction<
|
|
444
|
-
let visitorSkip: SkipFunction<
|
|
440
|
+
let visitorEnter: VisitFunction<unknown> | undefined;
|
|
441
|
+
let visitorLeave: VisitFunction<unknown> | undefined;
|
|
442
|
+
let visitorSkip: SkipFunction<unknown> | undefined;
|
|
445
443
|
|
|
446
444
|
const isObjectVisitor = typeof typeVisitor === 'object';
|
|
447
445
|
|
|
@@ -450,7 +448,7 @@ export function normalizeVisitors<T extends BaseVisitor>(
|
|
|
450
448
|
}
|
|
451
449
|
|
|
452
450
|
if (typeof typeVisitor === 'function') {
|
|
453
|
-
visitorEnter = typeVisitor
|
|
451
|
+
visitorEnter = typeVisitor;
|
|
454
452
|
} else if (isObjectVisitor) {
|
|
455
453
|
visitorEnter = typeVisitor.enter;
|
|
456
454
|
visitorLeave = typeVisitor.leave;
|
|
@@ -465,7 +463,7 @@ export function normalizeVisitors<T extends BaseVisitor>(
|
|
|
465
463
|
};
|
|
466
464
|
|
|
467
465
|
if (typeof typeVisitor === 'object') {
|
|
468
|
-
normalizeVisitorLevel(ruleConf, typeVisitor
|
|
466
|
+
normalizeVisitorLevel(ruleConf, typeVisitor, context, depth + 1);
|
|
469
467
|
}
|
|
470
468
|
|
|
471
469
|
if (parentContext) {
|
package/src/walk.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import { Location, isRef } from './ref-utils';
|
|
2
|
+
import { pushStack, popStack } from './utils';
|
|
3
|
+
import { ResolveError, YamlParseError, Source, makeRefId } from './resolve';
|
|
4
|
+
import { SpecVersion } from './oas-types';
|
|
5
|
+
import { isNamedType, SpecExtension } from './types';
|
|
6
|
+
|
|
1
7
|
import type { Referenced } from './typings/openapi';
|
|
2
8
|
import type {
|
|
3
9
|
VisitorLevelContext,
|
|
@@ -12,12 +18,6 @@ import type { ResolvedRefMap, Document } from './resolve';
|
|
|
12
18
|
import type { NormalizedNodeType } from './types';
|
|
13
19
|
import type { RuleSeverity } from './config';
|
|
14
20
|
|
|
15
|
-
import { Location, isRef } from './ref-utils';
|
|
16
|
-
import { pushStack, popStack } from './utils';
|
|
17
|
-
import { ResolveError, YamlParseError, Source, makeRefId } from './resolve';
|
|
18
|
-
import { SpecVersion } from './oas-types';
|
|
19
|
-
import { isNamedType, SpecExtension } from './types';
|
|
20
|
-
|
|
21
21
|
export type NonUndefined =
|
|
22
22
|
| string
|
|
23
23
|
| number
|
|
@@ -204,7 +204,7 @@ export function walkDocument<T extends BaseVisitor>(opts: {
|
|
|
204
204
|
const activatedContexts: Array<VisitorSkippedLevelContext | VisitorLevelContext> = [];
|
|
205
205
|
|
|
206
206
|
for (const { context, visit, skip, ruleId, severity } of currentEnterVisitors) {
|
|
207
|
-
if (ignoredNodes.has(currentLocation.pointer)) break;
|
|
207
|
+
if (ignoredNodes.has(`${currentLocation.absolutePointer}${currentLocation.pointer}`)) break;
|
|
208
208
|
|
|
209
209
|
if (context.isSkippedLevel) {
|
|
210
210
|
if (
|
|
@@ -413,7 +413,7 @@ export function walkDocument<T extends BaseVisitor>(opts: {
|
|
|
413
413
|
parentLocations: collectParentsLocations(context),
|
|
414
414
|
oasVersion: ctx.oasVersion,
|
|
415
415
|
ignoreNextVisitorsOnNode: () => {
|
|
416
|
-
ignoredNodes.add(currentLocation.pointer);
|
|
416
|
+
ignoredNodes.add(`${currentLocation.absolutePointer}${currentLocation.pointer}`);
|
|
417
417
|
},
|
|
418
418
|
getVisitorData: getVisitorDataFn.bind(undefined, ruleId),
|
|
419
419
|
},
|