@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 CHANGED
@@ -1,5 +1,22 @@
1
1
  # @redocly/openapi-core
2
2
 
3
+ ## 1.17.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Added JSON Schema draft 2019-09+ validation keyword - `dependentRequired`.
8
+ - Updated @redocly/config to v0.6.2.
9
+
10
+ ## 1.17.0
11
+
12
+ ### Minor Changes
13
+
14
+ - Changed resolution process to include extendedTypes and plugins before linting.
15
+
16
+ ### Patch Changes
17
+
18
+ - Added support for the `contentSchema` keyword to parse as a schema instance.
19
+
3
20
  ## 1.16.0
4
21
 
5
22
  ### Minor Changes
package/lib/bundle.d.ts CHANGED
@@ -47,4 +47,4 @@ export declare function bundleDocument(opts: {
47
47
  removeUnusedComponents?: boolean;
48
48
  keepUrlRefs?: boolean;
49
49
  }): Promise<BundleResult>;
50
- export declare function mapTypeToComponent(typeName: string, version: SpecMajorVersion): "definitions" | "examples" | "links" | "responses" | "parameters" | "headers" | "schemas" | "requestBodies" | "securitySchemes" | "callbacks" | null;
50
+ export declare function mapTypeToComponent(typeName: string, version: SpecMajorVersion): "definitions" | "examples" | "parameters" | "headers" | "schemas" | "responses" | "requestBodies" | "securitySchemes" | "links" | "callbacks" | null;
@@ -4,7 +4,12 @@ import type { Document } from '../resolve';
4
4
  import type { RegionalTokenWithValidity } from '../redocly/redocly-client-types';
5
5
  import type { RawConfig, RawUniversalConfig, Region } from './types';
6
6
  import type { ResolvedRefMap } from '../resolve';
7
- export type RawConfigProcessor = (rawConfig: Document, resolvedRefMap: ResolvedRefMap) => void | Promise<void>;
7
+ export type RawConfigProcessor = (params: {
8
+ document: Document;
9
+ resolvedRefMap: ResolvedRefMap;
10
+ config: Config;
11
+ parsed: Document['parsed'];
12
+ }) => void | Promise<void>;
8
13
  export declare function loadConfig(options?: {
9
14
  configPath?: string;
10
15
  customExtends?: string[];
@@ -17,9 +22,13 @@ export declare const CONFIG_FILE_NAMES: string[];
17
22
  export declare function findConfig(dir?: string): string | undefined;
18
23
  export declare function getConfig(options?: {
19
24
  configPath?: string;
20
- processRawConfig?: RawConfigProcessor;
21
25
  externalRefResolver?: BaseResolver;
22
- }): Promise<RawConfig>;
26
+ }): Promise<{
27
+ rawConfig: RawConfig;
28
+ document?: Document;
29
+ parsed?: Document['parsed'];
30
+ resolvedRefMap?: ResolvedRefMap;
31
+ }>;
23
32
  type CreateConfigOptions = {
24
33
  extends?: string[];
25
34
  tokens?: RegionalTokenWithValidity[];
@@ -68,10 +68,13 @@ function addConfigMetadata({ rawConfig, customExtends, configPath, tokens, files
68
68
  function loadConfig(options = {}) {
69
69
  return __awaiter(this, void 0, void 0, function* () {
70
70
  const { configPath = findConfig(), customExtends, processRawConfig, files, region, externalRefResolver, } = options;
71
- const rawConfig = yield getConfig({ configPath, processRawConfig, externalRefResolver });
71
+ const { rawConfig, document, parsed, resolvedRefMap } = yield getConfig({
72
+ configPath,
73
+ externalRefResolver,
74
+ });
72
75
  const redoclyClient = env_1.isBrowser ? undefined : new redocly_1.RedoclyClient();
73
76
  const tokens = redoclyClient && redoclyClient.hasTokens() ? redoclyClient.getAllTokens() : [];
74
- return addConfigMetadata({
77
+ const config = yield addConfigMetadata({
75
78
  rawConfig,
76
79
  customExtends,
77
80
  configPath,
@@ -80,6 +83,23 @@ function loadConfig(options = {}) {
80
83
  region,
81
84
  externalRefResolver,
82
85
  });
86
+ if (document && parsed && resolvedRefMap && typeof processRawConfig === 'function') {
87
+ try {
88
+ yield processRawConfig({
89
+ document,
90
+ resolvedRefMap,
91
+ config,
92
+ parsed,
93
+ });
94
+ }
95
+ catch (e) {
96
+ if (e instanceof utils_2.ConfigValidationError) {
97
+ throw e;
98
+ }
99
+ throw new Error(`Error parsing config file at '${configPath}': ${e.message}`);
100
+ }
101
+ }
102
+ return config;
83
103
  });
84
104
  }
85
105
  exports.loadConfig = loadConfig;
@@ -101,24 +121,24 @@ function findConfig(dir) {
101
121
  exports.findConfig = findConfig;
102
122
  function getConfig(options = {}) {
103
123
  return __awaiter(this, void 0, void 0, function* () {
104
- const { configPath = findConfig(), processRawConfig, externalRefResolver = new resolve_1.BaseResolver(), } = options;
124
+ const { configPath = findConfig(), externalRefResolver = new resolve_1.BaseResolver() } = options;
105
125
  if (!configPath)
106
- return {};
126
+ return { rawConfig: {} };
107
127
  try {
108
128
  const { document, resolvedRefMap } = yield (0, config_resolvers_1.resolveConfigFileAndRefs)({
109
129
  configPath,
110
130
  externalRefResolver,
111
131
  });
112
- if (typeof processRawConfig === 'function') {
113
- yield processRawConfig(document, resolvedRefMap);
114
- }
115
- const bundledConfig = yield (0, bundle_1.bundleConfig)(document, resolvedRefMap);
116
- return (0, utils_2.transformConfig)(bundledConfig);
132
+ const bundledRefMap = (0, utils_2.deepCloneMapWithJSON)(resolvedRefMap);
133
+ const parsed = yield (0, bundle_1.bundleConfig)(JSON.parse(JSON.stringify(document)), bundledRefMap);
134
+ return {
135
+ rawConfig: (0, utils_2.transformConfig)(parsed),
136
+ document,
137
+ parsed,
138
+ resolvedRefMap,
139
+ };
117
140
  }
118
141
  catch (e) {
119
- if (e instanceof utils_2.ConfigValidationError) {
120
- throw e;
121
- }
122
142
  throw new Error(`Error parsing config file at '${configPath}': ${e.message}`);
123
143
  }
124
144
  });
@@ -14,3 +14,4 @@ export declare function getResolveConfig(resolve?: RawResolveConfig): ResolveCon
14
14
  export declare function getUniquePlugins(plugins: Plugin[]): Plugin[];
15
15
  export declare class ConfigValidationError extends Error {
16
16
  }
17
+ export declare function deepCloneMapWithJSON<K, V>(originalMap: Map<K, V>): Map<K, V>;
@@ -11,7 +11,7 @@ var __rest = (this && this.__rest) || function (s, e) {
11
11
  return t;
12
12
  };
13
13
  Object.defineProperty(exports, "__esModule", { value: true });
14
- exports.ConfigValidationError = exports.getUniquePlugins = exports.getResolveConfig = exports.transformConfig = exports.checkForDeprecatedFields = exports.getMergedConfig = exports.mergeExtends = exports.prefixRules = exports.transformApiDefinitionsToApis = exports.parsePresetName = void 0;
14
+ exports.deepCloneMapWithJSON = exports.ConfigValidationError = exports.getUniquePlugins = exports.getResolveConfig = exports.transformConfig = exports.checkForDeprecatedFields = exports.getMergedConfig = exports.mergeExtends = exports.prefixRules = exports.transformApiDefinitionsToApis = exports.parsePresetName = void 0;
15
15
  const utils_1 = require("../utils");
16
16
  const config_1 = require("./config");
17
17
  const logger_1 = require("../logger");
@@ -251,3 +251,7 @@ exports.getUniquePlugins = getUniquePlugins;
251
251
  class ConfigValidationError extends Error {
252
252
  }
253
253
  exports.ConfigValidationError = ConfigValidationError;
254
+ function deepCloneMapWithJSON(originalMap) {
255
+ return new Map(JSON.parse(JSON.stringify([...originalMap])));
256
+ }
257
+ exports.deepCloneMapWithJSON = deepCloneMapWithJSON;
package/lib/lint.d.ts CHANGED
@@ -22,6 +22,7 @@ export declare function lintDocument(opts: {
22
22
  }): Promise<import("./walk").NormalizedProblem[]>;
23
23
  export declare function lintConfig(opts: {
24
24
  document: Document;
25
+ config: Config;
25
26
  resolvedRefMap?: ResolvedRefMap;
26
27
  severity?: ProblemSeverity;
27
28
  externalRefResolver?: BaseResolver;
package/lib/lint.js CHANGED
@@ -20,6 +20,7 @@ const oas_types_1 = require("./oas-types");
20
20
  const redocly_yaml_1 = require("./types/redocly-yaml");
21
21
  const spec_1 = require("./rules/common/spec");
22
22
  const no_unresolved_refs_1 = require("./rules/no-unresolved-refs");
23
+ const config_2 = require("@redocly/config");
23
24
  function lint(opts) {
24
25
  return __awaiter(this, void 0, void 0, function* () {
25
26
  const { ref, externalRefResolver = new resolve_1.BaseResolver(opts.config.resolve) } = opts;
@@ -85,18 +86,13 @@ function lintDocument(opts) {
85
86
  exports.lintDocument = lintDocument;
86
87
  function lintConfig(opts) {
87
88
  return __awaiter(this, void 0, void 0, function* () {
88
- const { document, severity, externalRefResolver = new resolve_1.BaseResolver() } = opts;
89
+ const { document, severity, externalRefResolver = new resolve_1.BaseResolver(), config } = opts;
89
90
  const ctx = {
90
91
  problems: [],
91
92
  oasVersion: oas_types_1.SpecVersion.OAS3_0,
92
93
  visitorsData: {},
93
94
  };
94
- const plugins = (0, config_1.resolvePlugins)([config_1.defaultPlugin]);
95
- const config = new config_1.StyleguideConfig({
96
- plugins,
97
- rules: { spec: 'error' },
98
- });
99
- const types = (0, types_1.normalizeTypes)(opts.externalConfigTypes || redocly_yaml_1.ConfigTypes, config);
95
+ const types = (0, types_1.normalizeTypes)(opts.externalConfigTypes || (0, redocly_yaml_1.createConfigTypes)(config_2.rootRedoclyConfigSchema, config), { doNotResolveExamples: config.styleguide.doNotResolveExamples });
100
96
  const rules = [
101
97
  {
102
98
  severity: severity || 'error',
@@ -24,4 +24,4 @@ export type Oas2DecoratorsSet = Record<string, Oas2Preprocessor>;
24
24
  export type Async2DecoratorsSet = Record<string, Async2Preprocessor>;
25
25
  export declare function detectSpec(root: any): SpecVersion;
26
26
  export declare function getMajorSpecVersion(version: SpecVersion): SpecMajorVersion;
27
- export declare function getTypes(spec: SpecVersion): Record<string, import("./types").NodeType> | Record<"Root" | "Tag" | "ExternalDocs" | "SecurityRequirement" | "Info" | "Contact" | "License" | "Paths" | "PathItem" | "Parameter" | "Operation" | "Example" | "Header" | "Responses" | "Response" | "Schema" | "Xml" | "SchemaProperties" | "NamedSchemas" | "NamedResponses" | "NamedParameters" | "NamedSecuritySchemes" | "SecurityScheme" | "Examples" | "ExamplesMap" | "TagList" | "SecurityRequirementList" | "ParameterList" | "ParameterItems" | "TagGroup" | "TagGroups" | "EnumDescriptions" | "Logo" | "XCodeSample" | "XCodeSampleList" | "XServer" | "XServerList", import("./types").NodeType> | Record<"Root" | "Tag" | "ExternalDocs" | "Server" | "ServerVariable" | "SecurityRequirement" | "Info" | "Contact" | "License" | "Paths" | "PathItem" | "Callback" | "CallbacksMap" | "Parameter" | "Operation" | "RequestBody" | "MediaTypesMap" | "MediaType" | "Example" | "Encoding" | "Header" | "Responses" | "Response" | "Link" | "Schema" | "Xml" | "SchemaProperties" | "DiscriminatorMapping" | "Discriminator" | "Components" | "NamedSchemas" | "NamedResponses" | "NamedParameters" | "NamedExamples" | "NamedRequestBodies" | "NamedHeaders" | "NamedSecuritySchemes" | "NamedLinks" | "NamedCallbacks" | "ImplicitFlow" | "PasswordFlow" | "ClientCredentials" | "AuthorizationCode" | "OAuth2Flows" | "SecurityScheme" | "ServerVariablesMap" | "ExamplesMap" | "EncodingMap" | "HeadersMap" | "LinksMap" | "TagList" | "SecurityRequirementList" | "ParameterList" | "TagGroup" | "TagGroups" | "EnumDescriptions" | "Logo" | "XCodeSample" | "XCodeSampleList" | "ServerList" | "XUsePkce" | "WebhooksMap", import("./types").NodeType> | Record<"Root" | "Info" | "License" | "Operation" | "Schema" | "SchemaProperties" | "Components" | "SecurityScheme" | "NamedPathItems", import("./types").NodeType>;
27
+ export declare function getTypes(spec: SpecVersion): Record<string, import("./types").NodeType> | Record<"Root" | "Tag" | "ExternalDocs" | "SecurityRequirement" | "Info" | "Contact" | "License" | "Paths" | "PathItem" | "Parameter" | "Operation" | "Example" | "Header" | "Responses" | "Response" | "Schema" | "Xml" | "SchemaProperties" | "NamedSchemas" | "NamedResponses" | "NamedParameters" | "NamedSecuritySchemes" | "SecurityScheme" | "Examples" | "ExamplesMap" | "TagList" | "SecurityRequirementList" | "ParameterList" | "ParameterItems" | "TagGroup" | "TagGroups" | "EnumDescriptions" | "Logo" | "XCodeSample" | "XCodeSampleList" | "XServer" | "XServerList", import("./types").NodeType> | Record<"Root" | "Tag" | "ExternalDocs" | "Server" | "ServerVariable" | "SecurityRequirement" | "Info" | "Contact" | "License" | "Paths" | "PathItem" | "Callback" | "CallbacksMap" | "Parameter" | "Operation" | "RequestBody" | "MediaTypesMap" | "MediaType" | "Example" | "Encoding" | "Header" | "Responses" | "Response" | "Link" | "Schema" | "Xml" | "SchemaProperties" | "DiscriminatorMapping" | "Discriminator" | "Components" | "NamedSchemas" | "NamedResponses" | "NamedParameters" | "NamedExamples" | "NamedRequestBodies" | "NamedHeaders" | "NamedSecuritySchemes" | "NamedLinks" | "NamedCallbacks" | "ImplicitFlow" | "PasswordFlow" | "ClientCredentials" | "AuthorizationCode" | "OAuth2Flows" | "SecurityScheme" | "ServerVariablesMap" | "ExamplesMap" | "EncodingMap" | "HeadersMap" | "LinksMap" | "WebhooksMap" | "TagList" | "SecurityRequirementList" | "ParameterList" | "TagGroup" | "TagGroups" | "EnumDescriptions" | "Logo" | "XCodeSample" | "XCodeSampleList" | "ServerList" | "XUsePkce", import("./types").NodeType> | Record<"Root" | "Info" | "License" | "Operation" | "Schema" | "SchemaProperties" | "Components" | "SecurityScheme" | "NamedPathItems" | "DependentRequired", import("./types").NodeType>;
@@ -129,6 +129,7 @@ const Schema = {
129
129
  then: 'Schema',
130
130
  else: 'Schema',
131
131
  dependentSchemas: (0, _1.listOf)('Schema'),
132
+ dependentRequired: 'DependentRequired',
132
133
  prefixItems: (0, _1.listOf)('Schema'),
133
134
  contains: 'Schema',
134
135
  minContains: { type: 'integer', minimum: 0 },
@@ -168,6 +169,7 @@ const Schema = {
168
169
  format: { type: 'string' },
169
170
  contentEncoding: { type: 'string' },
170
171
  contentMediaType: { type: 'string' },
172
+ contentSchema: 'Schema',
171
173
  default: null,
172
174
  readOnly: { type: 'boolean' },
173
175
  writeOnly: { type: 'boolean' },
@@ -261,10 +263,15 @@ const SecurityScheme = {
261
263
  },
262
264
  extensionsPrefix: 'x-',
263
265
  };
266
+ const DependentRequired = {
267
+ properties: {},
268
+ additionalProperties: { type: 'array', items: { type: 'string' } },
269
+ };
264
270
  exports.Oas3_1Types = Object.assign(Object.assign({}, oas3_1.Oas3Types), { Info,
265
271
  Root,
266
272
  Schema,
267
273
  SchemaProperties,
268
274
  License,
269
275
  Components, NamedPathItems: (0, _1.mapOf)('PathItem'), SecurityScheme,
270
- Operation });
276
+ Operation,
277
+ DependentRequired });
@@ -1,5 +1,6 @@
1
1
  import type { NodeType } from '.';
2
2
  import type { JSONSchema } from 'json-schema-to-ts';
3
+ import { Config } from '../config';
3
4
  declare const builtInCommonRules: readonly ["spec", "info-contact", "operation-operationId", "tag-description", "tags-alphabetical"];
4
5
  export type BuiltInCommonRuleId = typeof builtInCommonRules[number];
5
6
  declare const builtInCommonOASRules: readonly ["info-license-url", "info-license", "no-ambiguous-paths", "no-enum-type-mismatch", "no-http-verbs-in-paths", "no-identical-paths", "no-invalid-parameter-examples", "no-invalid-schema-examples", "no-path-trailing-slash", "operation-2xx-response", "operation-4xx-response", "operation-description", "operation-operationId-unique", "operation-operationId-url-safe", "operation-parameters-unique", "operation-singular-tag", "operation-summary", "operation-tag-defined", "parameter-description", "path-declaration-must-exist", "path-excludes-patterns", "path-http-verbs-order", "path-not-include-query", "path-params-defined", "path-parameters-defined", "path-segment-plural", "paths-kebab-case", "required-string-property-missing-min-length", "response-contains-header", "scalar-property-missing-example", "security-defined", "spec-strict-refs", "no-unresolved-refs", "no-required-schema-properties-undefined"];
@@ -14,11 +15,12 @@ declare const oas2NodeTypesList: readonly ["Root", "Tag", "TagList", "ExternalDo
14
15
  export type Oas2NodeType = typeof oas2NodeTypesList[number];
15
16
  declare const oas3NodeTypesList: readonly ["Root", "Tag", "TagList", "ExternalDocs", "Server", "ServerList", "ServerVariable", "ServerVariablesMap", "SecurityRequirement", "SecurityRequirementList", "Info", "Contact", "License", "Paths", "PathItem", "Parameter", "ParameterList", "Operation", "Callback", "CallbacksMap", "RequestBody", "MediaTypesMap", "MediaType", "Example", "ExamplesMap", "Encoding", "EncodingMap", "Header", "HeadersMap", "Responses", "Response", "Link", "LinksMap", "Schema", "Xml", "SchemaProperties", "DiscriminatorMapping", "Discriminator", "Components", "NamedSchemas", "NamedResponses", "NamedParameters", "NamedExamples", "NamedRequestBodies", "NamedHeaders", "NamedSecuritySchemes", "NamedLinks", "NamedCallbacks", "ImplicitFlow", "PasswordFlow", "ClientCredentials", "AuthorizationCode", "OAuth2Flows", "SecurityScheme", "TagGroup", "TagGroups", "EnumDescriptions", "Logo", "XCodeSample", "XCodeSampleList", "XUsePkce", "WebhooksMap"];
16
17
  export type Oas3NodeType = typeof oas3NodeTypesList[number];
17
- declare const oas3_1NodeTypesList: readonly ["Root", "Schema", "SchemaProperties", "Info", "License", "Components", "NamedPathItems", "SecurityScheme", "Operation"];
18
+ declare const oas3_1NodeTypesList: readonly ["Root", "Schema", "SchemaProperties", "Info", "License", "Components", "NamedPathItems", "SecurityScheme", "Operation", "DependentRequired"];
18
19
  export type Oas3_1NodeType = typeof oas3_1NodeTypesList[number];
19
- export declare const createConfigTypes: (extraSchemas: JSONSchema) => {
20
+ export declare function createConfigTypes(extraSchemas: JSONSchema, config?: Config): {
20
21
  ConfigRoot: NodeType;
21
22
  ConfigApisProperties: NodeType;
23
+ AssertionDefinitionSubject: NodeType;
22
24
  };
23
25
  export declare const ConfigTypes: Record<string, NodeType>;
24
26
  export {};
@@ -5,6 +5,7 @@ const config_1 = require("@redocly/config");
5
5
  const _1 = require(".");
6
6
  const utils_1 = require("../utils");
7
7
  const json_schema_adapter_1 = require("./json-schema-adapter");
8
+ const oas_types_1 = require("../oas-types");
8
9
  const builtInCommonRules = [
9
10
  'spec',
10
11
  'info-contact',
@@ -193,8 +194,8 @@ const oas3_1NodeTypesList = [
193
194
  'NamedPathItems',
194
195
  'SecurityScheme',
195
196
  'Operation',
197
+ 'DependentRequired',
196
198
  ];
197
- const asyncNodeTypesList = ['Message'];
198
199
  const ConfigStyleguide = {
199
200
  properties: {
200
201
  extends: {
@@ -296,37 +297,30 @@ const Schema = {
296
297
  properties: {},
297
298
  additionalProperties: {},
298
299
  };
299
- const AssertionDefinitionSubject = {
300
- properties: {
301
- type: {
302
- enum: [
303
- ...new Set([
304
- 'any',
305
- ...oas2NodeTypesList,
306
- ...oas3NodeTypesList,
307
- ...oas3_1NodeTypesList,
308
- ...asyncNodeTypesList,
309
- 'SpecExtension',
310
- ]),
311
- ],
312
- },
313
- property: (value) => {
314
- if (Array.isArray(value)) {
315
- return { type: 'array', items: { type: 'string' } };
316
- }
317
- else if (value === null) {
318
- return null;
319
- }
320
- else {
321
- return { type: 'string' };
322
- }
300
+ function createAssertionDefinitionSubject(nodeNames) {
301
+ return {
302
+ properties: {
303
+ type: {
304
+ enum: [...new Set(['any', ...nodeNames, 'SpecExtension'])],
305
+ },
306
+ property: (value) => {
307
+ if (Array.isArray(value)) {
308
+ return { type: 'array', items: { type: 'string' } };
309
+ }
310
+ else if (value === null) {
311
+ return null;
312
+ }
313
+ else {
314
+ return { type: 'string' };
315
+ }
316
+ },
317
+ filterInParentKeys: { type: 'array', items: { type: 'string' } },
318
+ filterOutParentKeys: { type: 'array', items: { type: 'string' } },
319
+ matchParentKeys: { type: 'string' },
323
320
  },
324
- filterInParentKeys: { type: 'array', items: { type: 'string' } },
325
- filterOutParentKeys: { type: 'array', items: { type: 'string' } },
326
- matchParentKeys: { type: 'string' },
327
- },
328
- required: ['type'],
329
- };
321
+ required: ['type'],
322
+ };
323
+ }
330
324
  const AssertionDefinitionAssertions = {
331
325
  properties: {
332
326
  enum: { type: 'array', items: { type: 'string' } },
@@ -897,11 +891,17 @@ const ConfigMockServer = {
897
891
  errorIfForcedExampleNotFound: { type: 'boolean' },
898
892
  },
899
893
  };
900
- const createConfigTypes = (extraSchemas) => {
894
+ function createConfigTypes(extraSchemas, config) {
895
+ const nodeNames = Object.values(oas_types_1.SpecVersion).flatMap((version) => {
896
+ const types = (config === null || config === void 0 ? void 0 : config.styleguide)
897
+ ? config.styleguide.extendTypes((0, oas_types_1.getTypes)(version), version)
898
+ : (0, oas_types_1.getTypes)(version);
899
+ return Object.keys(types);
900
+ });
901
901
  // Create types based on external schemas
902
902
  const nodeTypes = (0, json_schema_adapter_1.getNodeTypesFromJSONSchema)('rootRedoclyConfigSchema', extraSchemas);
903
- return Object.assign(Object.assign(Object.assign({}, CoreConfigTypes), { ConfigRoot: createConfigRoot(nodeTypes), ConfigApisProperties: createConfigApisProperties(nodeTypes) }), nodeTypes);
904
- };
903
+ return Object.assign(Object.assign(Object.assign({}, CoreConfigTypes), { ConfigRoot: createConfigRoot(nodeTypes), ConfigApisProperties: createConfigApisProperties(nodeTypes), AssertionDefinitionSubject: createAssertionDefinitionSubject(nodeNames) }), nodeTypes);
904
+ }
905
905
  exports.createConfigTypes = createConfigTypes;
906
906
  const CoreConfigTypes = {
907
907
  Assert,
@@ -964,6 +964,5 @@ const CoreConfigTypes = {
964
964
  Heading,
965
965
  Typography,
966
966
  AssertionDefinitionAssertions,
967
- AssertionDefinitionSubject,
968
967
  };
969
- exports.ConfigTypes = (0, exports.createConfigTypes)(config_1.rootRedoclyConfigSchema);
968
+ exports.ConfigTypes = createConfigTypes(config_1.rootRedoclyConfigSchema);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/openapi-core",
3
- "version": "1.16.0",
3
+ "version": "1.17.1",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "engines": {
@@ -36,7 +36,7 @@
36
36
  ],
37
37
  "dependencies": {
38
38
  "@redocly/ajv": "^8.11.0",
39
- "@redocly/config": "^0.6.0",
39
+ "@redocly/config": "^0.6.2",
40
40
  "colorette": "^1.2.0",
41
41
  "https-proxy-agent": "^7.0.4",
42
42
  "js-levenshtein": "^1.1.6",
@@ -3,7 +3,7 @@ import { outdent } from 'outdent';
3
3
 
4
4
  import { lintFromString, lintConfig, lintDocument, lint } from '../lint';
5
5
  import { BaseResolver } from '../resolve';
6
- import { loadConfig } from '../config/load';
6
+ import { createConfig, loadConfig } from '../config/load';
7
7
  import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../__tests__/utils';
8
8
  import { detectSpec } from '../oas-types';
9
9
  import { rootRedoclyConfigSchema } from '@redocly/config';
@@ -293,7 +293,7 @@ describe('lint', () => {
293
293
  - url: http://redocly-example.com
294
294
  paths: {}
295
295
  `,
296
- config: await loadConfig(),
296
+ config: await loadConfig({ configPath: path.join(__dirname, 'fixtures/redocly.yaml') }),
297
297
  });
298
298
 
299
299
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
@@ -374,7 +374,8 @@ describe('lint', () => {
374
374
  `,
375
375
  ''
376
376
  );
377
- const results = await lintConfig({ document });
377
+ const config = await createConfig({});
378
+ const results = await lintConfig({ document, config });
378
379
 
379
380
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
380
381
  [
@@ -435,7 +436,8 @@ describe('lint', () => {
435
436
  `,
436
437
  ''
437
438
  );
438
- const results = await lintConfig({ document });
439
+ const config = await createConfig({});
440
+ const results = await lintConfig({ document, config });
439
441
 
440
442
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
441
443
  [
@@ -475,7 +477,8 @@ describe('lint', () => {
475
477
  `,
476
478
  ''
477
479
  );
478
- const results = await lintConfig({ document });
480
+ const config = await createConfig({});
481
+ const results = await lintConfig({ document, config });
479
482
 
480
483
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
481
484
  [
@@ -510,7 +513,8 @@ describe('lint', () => {
510
513
  `,
511
514
  ''
512
515
  );
513
- const results = await lintConfig({ document });
516
+ const config = await createConfig({});
517
+ const results = await lintConfig({ document, config });
514
518
 
515
519
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
516
520
  [
@@ -534,7 +538,8 @@ describe('lint', () => {
534
538
 
535
539
  it('lintConfig should detect wrong fields in the default configuration after merging with the portal config schema', async () => {
536
540
  const document = testPortalConfig;
537
- const results = await lintConfig({ document });
541
+ const config = await createConfig({});
542
+ const results = await lintConfig({ document, config });
538
543
 
539
544
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
540
545
  [
@@ -1165,13 +1170,18 @@ describe('lint', () => {
1165
1170
 
1166
1171
  it('lintConfig should alternate its behavior when supplied externalConfigTypes', async () => {
1167
1172
  const document = testPortalConfig;
1173
+ const config = await createConfig({});
1168
1174
  const results = await lintConfig({
1169
1175
  document,
1170
- externalConfigTypes: createConfigTypes({
1171
- type: 'object',
1172
- properties: { theme: rootRedoclyConfigSchema.properties.theme },
1173
- additionalProperties: false,
1174
- }),
1176
+ externalConfigTypes: createConfigTypes(
1177
+ {
1178
+ type: 'object',
1179
+ properties: { theme: rootRedoclyConfigSchema.properties.theme },
1180
+ additionalProperties: false,
1181
+ },
1182
+ config
1183
+ ),
1184
+ config,
1175
1185
  });
1176
1186
 
1177
1187
  expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
@@ -1583,4 +1593,128 @@ describe('lint', () => {
1583
1593
  expect(result[0]).toHaveProperty('ignored', true);
1584
1594
  expect(result[0]).toHaveProperty('ruleId', 'operation-operationId');
1585
1595
  });
1596
+
1597
+ it('should throw an error for dependentRequired not expected here - OAS 3.0.x', async () => {
1598
+ const document = parseYamlToDocument(
1599
+ outdent`
1600
+ openapi: 3.0.3
1601
+ info:
1602
+ title: test json schema validation keyword - dependentRequired
1603
+ version: 1.0.0
1604
+ paths:
1605
+ '/thing':
1606
+ get:
1607
+ summary: a sample api
1608
+ responses:
1609
+ '200':
1610
+ description: OK
1611
+ content:
1612
+ 'application/json':
1613
+ schema:
1614
+ $ref: '#/components/schemas/test_schema'
1615
+ examples:
1616
+ dependentRequired_passing:
1617
+ summary: an example schema
1618
+ value: { "name": "bobby", "age": 25}
1619
+ dependentRequired_failing:
1620
+ summary: an example schema
1621
+ value: { "name": "jennie"}
1622
+ components:
1623
+ schemas:
1624
+ test_schema:
1625
+ type: object
1626
+ properties:
1627
+ name:
1628
+ type: string
1629
+ age:
1630
+ type: number
1631
+ dependentRequired:
1632
+ name:
1633
+ - age
1634
+ `,
1635
+ ''
1636
+ );
1637
+
1638
+ const configFilePath = path.join(__dirname, '..', '..', '..', 'redocly.yaml');
1639
+
1640
+ const results = await lintDocument({
1641
+ externalRefResolver: new BaseResolver(),
1642
+ document,
1643
+ config: await makeConfig({ spec: 'error' }, undefined, configFilePath),
1644
+ });
1645
+
1646
+ expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`
1647
+ [
1648
+ {
1649
+ "from": {
1650
+ "pointer": "#/paths/~1thing/get/responses/200/content/application~1json/schema",
1651
+ "source": "",
1652
+ },
1653
+ "location": [
1654
+ {
1655
+ "pointer": "#/components/schemas/test_schema/dependentRequired",
1656
+ "reportOnKey": true,
1657
+ "source": "",
1658
+ },
1659
+ ],
1660
+ "message": "Property \`dependentRequired\` is not expected here.",
1661
+ "ruleId": "spec",
1662
+ "severity": "error",
1663
+ "suggest": [],
1664
+ },
1665
+ ]
1666
+ `);
1667
+ });
1668
+
1669
+ it('should not throw an error for dependentRequired not expected here - OAS 3.1.x', async () => {
1670
+ const document = parseYamlToDocument(
1671
+ outdent`
1672
+ openapi: 3.1.0
1673
+ info:
1674
+ title: test json schema validation keyword - dependentRequired
1675
+ version: 1.0.0
1676
+ paths:
1677
+ '/thing':
1678
+ get:
1679
+ summary: a sample api
1680
+ responses:
1681
+ '200':
1682
+ description: OK
1683
+ content:
1684
+ 'application/json':
1685
+ schema:
1686
+ $ref: '#/components/schemas/test_schema'
1687
+ examples:
1688
+ dependentRequired_passing:
1689
+ summary: an example schema
1690
+ value: { "name": "bobby", "age": 25}
1691
+ dependentRequired_failing:
1692
+ summary: an example schema
1693
+ value: { "name": "jennie"}
1694
+ components:
1695
+ schemas:
1696
+ test_schema:
1697
+ type: object
1698
+ properties:
1699
+ name:
1700
+ type: string
1701
+ age:
1702
+ type: number
1703
+ dependentRequired:
1704
+ name:
1705
+ - age
1706
+ `,
1707
+ ''
1708
+ );
1709
+
1710
+ const configFilePath = path.join(__dirname, '..', '..', '..', 'redocly.yaml');
1711
+
1712
+ const results = await lintDocument({
1713
+ externalRefResolver: new BaseResolver(),
1714
+ document,
1715
+ config: await makeConfig({ spec: 'error' }, undefined, configFilePath),
1716
+ });
1717
+
1718
+ expect(replaceSourceWithRef(results)).toMatchInlineSnapshot(`[]`);
1719
+ });
1586
1720
  });