@redocly/openapi-core 1.16.0 → 1.17.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 CHANGED
@@ -1,5 +1,15 @@
1
1
  # @redocly/openapi-core
2
2
 
3
+ ## 1.17.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Changed resolution process to include extendedTypes and plugins before linting.
8
+
9
+ ### Patch Changes
10
+
11
+ - Added support for the `contentSchema` keyword to parse as a schema instance.
12
+
3
13
  ## 1.16.0
4
14
 
5
15
  ### 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", import("./types").NodeType>;
@@ -168,6 +168,7 @@ const Schema = {
168
168
  format: { type: 'string' },
169
169
  contentEncoding: { type: 'string' },
170
170
  contentMediaType: { type: 'string' },
171
+ contentSchema: 'Schema',
171
172
  default: null,
172
173
  readOnly: { type: 'boolean' },
173
174
  writeOnly: { type: 'boolean' },
@@ -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"];
@@ -16,9 +17,10 @@ declare const oas3NodeTypesList: readonly ["Root", "Tag", "TagList", "ExternalDo
16
17
  export type Oas3NodeType = typeof oas3NodeTypesList[number];
17
18
  declare const oas3_1NodeTypesList: readonly ["Root", "Schema", "SchemaProperties", "Info", "License", "Components", "NamedPathItems", "SecurityScheme", "Operation"];
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',
@@ -194,7 +195,6 @@ const oas3_1NodeTypesList = [
194
195
  'SecurityScheme',
195
196
  'Operation',
196
197
  ];
197
- const asyncNodeTypesList = ['Message'];
198
198
  const ConfigStyleguide = {
199
199
  properties: {
200
200
  extends: {
@@ -296,37 +296,30 @@ const Schema = {
296
296
  properties: {},
297
297
  additionalProperties: {},
298
298
  };
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
- }
299
+ function createAssertionDefinitionSubject(nodeNames) {
300
+ return {
301
+ properties: {
302
+ type: {
303
+ enum: [...new Set(['any', ...nodeNames, 'SpecExtension'])],
304
+ },
305
+ property: (value) => {
306
+ if (Array.isArray(value)) {
307
+ return { type: 'array', items: { type: 'string' } };
308
+ }
309
+ else if (value === null) {
310
+ return null;
311
+ }
312
+ else {
313
+ return { type: 'string' };
314
+ }
315
+ },
316
+ filterInParentKeys: { type: 'array', items: { type: 'string' } },
317
+ filterOutParentKeys: { type: 'array', items: { type: 'string' } },
318
+ matchParentKeys: { type: 'string' },
323
319
  },
324
- filterInParentKeys: { type: 'array', items: { type: 'string' } },
325
- filterOutParentKeys: { type: 'array', items: { type: 'string' } },
326
- matchParentKeys: { type: 'string' },
327
- },
328
- required: ['type'],
329
- };
320
+ required: ['type'],
321
+ };
322
+ }
330
323
  const AssertionDefinitionAssertions = {
331
324
  properties: {
332
325
  enum: { type: 'array', items: { type: 'string' } },
@@ -897,11 +890,17 @@ const ConfigMockServer = {
897
890
  errorIfForcedExampleNotFound: { type: 'boolean' },
898
891
  },
899
892
  };
900
- const createConfigTypes = (extraSchemas) => {
893
+ function createConfigTypes(extraSchemas, config) {
894
+ const nodeNames = Object.values(oas_types_1.SpecVersion).flatMap((version) => {
895
+ const types = (config === null || config === void 0 ? void 0 : config.styleguide)
896
+ ? config.styleguide.extendTypes((0, oas_types_1.getTypes)(version), version)
897
+ : (0, oas_types_1.getTypes)(version);
898
+ return Object.keys(types);
899
+ });
901
900
  // Create types based on external schemas
902
901
  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
- };
902
+ return Object.assign(Object.assign(Object.assign({}, CoreConfigTypes), { ConfigRoot: createConfigRoot(nodeTypes), ConfigApisProperties: createConfigApisProperties(nodeTypes), AssertionDefinitionSubject: createAssertionDefinitionSubject(nodeNames) }), nodeTypes);
903
+ }
905
904
  exports.createConfigTypes = createConfigTypes;
906
905
  const CoreConfigTypes = {
907
906
  Assert,
@@ -964,6 +963,5 @@ const CoreConfigTypes = {
964
963
  Heading,
965
964
  Typography,
966
965
  AssertionDefinitionAssertions,
967
- AssertionDefinitionSubject,
968
966
  };
969
- exports.ConfigTypes = (0, exports.createConfigTypes)(config_1.rootRedoclyConfigSchema);
967
+ 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.0",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "engines": {
@@ -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(`
@@ -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
- const result = await getConfig({
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(result).toEqual({
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