@redocly/openapi-core 1.0.0-beta.111 → 1.0.0-beta.113

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.
Files changed (78) hide show
  1. package/lib/config/all.js +0 -1
  2. package/lib/config/config-resolvers.js +22 -18
  3. package/lib/config/config.d.ts +4 -10
  4. package/lib/config/config.js +1 -1
  5. package/lib/config/load.d.ts +1 -1
  6. package/lib/config/load.js +10 -10
  7. package/lib/config/minimal.js +0 -1
  8. package/lib/config/recommended.js +0 -1
  9. package/lib/config/rules.d.ts +6 -3
  10. package/lib/config/rules.js +3 -2
  11. package/lib/config/types.d.ts +3 -0
  12. package/lib/ref-utils.d.ts +1 -0
  13. package/lib/ref-utils.js +5 -1
  14. package/lib/resolve.js +19 -0
  15. package/lib/rules/common/assertions/asserts.d.ts +22 -5
  16. package/lib/rules/common/assertions/asserts.js +25 -0
  17. package/lib/rules/common/assertions/index.d.ts +27 -2
  18. package/lib/rules/common/assertions/index.js +6 -29
  19. package/lib/rules/common/assertions/utils.d.ts +7 -14
  20. package/lib/rules/common/assertions/utils.js +129 -97
  21. package/lib/rules/common/spec.js +6 -0
  22. package/lib/rules/oas2/index.d.ts +0 -1
  23. package/lib/rules/oas2/index.js +0 -2
  24. package/lib/rules/oas3/index.js +0 -2
  25. package/lib/rules/utils.js +3 -0
  26. package/lib/types/oas2.js +11 -7
  27. package/lib/types/oas3.js +15 -10
  28. package/lib/types/oas3_1.js +1 -0
  29. package/lib/types/redocly-yaml.js +49 -27
  30. package/lib/utils.d.ts +2 -0
  31. package/lib/utils.js +13 -1
  32. package/lib/visitors.d.ts +2 -1
  33. package/lib/visitors.js +1 -0
  34. package/lib/walk.js +7 -1
  35. package/package.json +1 -1
  36. package/src/__tests__/bundle.test.ts +46 -0
  37. package/src/__tests__/lint.test.ts +24 -5
  38. package/src/benchmark/benches/rebilly.yaml +36 -28
  39. package/src/config/__tests__/__snapshots__/config-resolvers.test.ts.snap +1 -3
  40. package/src/config/__tests__/config-resolvers.test.ts +6 -7
  41. package/src/config/__tests__/fixtures/load-redocly.yaml +2 -0
  42. package/src/config/__tests__/fixtures/resolve-config/local-config-with-custom-function.yaml +6 -5
  43. package/src/config/__tests__/fixtures/resolve-config/local-config-with-wrong-custom-function.yaml +0 -1
  44. package/src/config/__tests__/load.test.ts +4 -1
  45. package/src/config/all.ts +0 -1
  46. package/src/config/config-resolvers.ts +44 -31
  47. package/src/config/config.ts +6 -5
  48. package/src/config/load.ts +19 -9
  49. package/src/config/minimal.ts +0 -1
  50. package/src/config/recommended.ts +0 -1
  51. package/src/config/rules.ts +11 -3
  52. package/src/config/types.ts +2 -0
  53. package/src/ref-utils.ts +4 -0
  54. package/src/resolve.ts +25 -3
  55. package/src/rules/common/__tests__/spec.test.ts +170 -0
  56. package/src/rules/common/assertions/__tests__/asserts.test.ts +7 -3
  57. package/src/rules/common/assertions/__tests__/index.test.ts +41 -20
  58. package/src/rules/common/assertions/__tests__/utils.test.ts +43 -17
  59. package/src/rules/common/assertions/asserts.ts +60 -8
  60. package/src/rules/common/assertions/index.ts +36 -46
  61. package/src/rules/common/assertions/utils.ts +204 -127
  62. package/src/rules/common/spec.ts +7 -0
  63. package/src/rules/oas2/index.ts +0 -2
  64. package/src/rules/oas3/__tests__/no-invalid-media-type-examples.test.ts +32 -0
  65. package/src/rules/oas3/index.ts +0 -2
  66. package/src/rules/utils.ts +4 -0
  67. package/src/types/oas2.ts +11 -7
  68. package/src/types/oas3.ts +15 -10
  69. package/src/types/oas3_1.ts +1 -0
  70. package/src/types/redocly-yaml.ts +49 -29
  71. package/src/utils.ts +11 -0
  72. package/src/visitors.ts +7 -1
  73. package/src/walk.ts +8 -1
  74. package/tsconfig.tsbuildinfo +1 -1
  75. package/lib/rules/common/info-description.d.ts +0 -2
  76. package/lib/rules/common/info-description.js +0 -12
  77. package/src/rules/common/__tests__/info-description.test.ts +0 -102
  78. package/src/rules/common/info-description.ts +0 -10
@@ -1,122 +1,154 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.regexFromString = exports.isOrdered = exports.getIntersectionLength = exports.buildSubjectVisitor = exports.buildVisitorObject = void 0;
3
+ exports.regexFromString = exports.isOrdered = exports.getIntersectionLength = exports.buildSubjectVisitor = exports.buildVisitorObject = exports.getAssertsToApply = void 0;
4
+ const asserts_1 = require("./asserts");
4
5
  const logger_1 = require("../../../logger");
5
6
  const ref_utils_1 = require("../../../ref-utils");
6
- const asserts_1 = require("./asserts");
7
- function buildVisitorObject(subject, context, subjectVisitor) {
8
- if (!context) {
9
- return { [subject]: subjectVisitor };
7
+ const utils_1 = require("../../../utils");
8
+ const assertionMessageTemplates = {
9
+ problems: '{{problems}}',
10
+ };
11
+ function getPredicatesFromLocators(locators) {
12
+ const { filterInParentKeys, filterOutParentKeys, matchParentKeys } = locators;
13
+ const keyMatcher = matchParentKeys && regexFromString(matchParentKeys);
14
+ const matchKeysPredicate = keyMatcher && ((key) => keyMatcher.test(key.toString()));
15
+ const filterInPredicate = Array.isArray(filterInParentKeys) &&
16
+ ((key) => filterInParentKeys.includes(key.toString()));
17
+ const filterOutPredicate = Array.isArray(filterOutParentKeys) &&
18
+ ((key) => !filterOutParentKeys.includes(key.toString()));
19
+ return [matchKeysPredicate, filterInPredicate, filterOutPredicate].filter(utils_1.isTruthy);
20
+ }
21
+ function getAssertsToApply(assertion) {
22
+ const assertsToApply = utils_1.keysOf(asserts_1.asserts)
23
+ .filter((assertName) => assertion.assertions[assertName] !== undefined)
24
+ .map((assertName) => {
25
+ return {
26
+ name: assertName,
27
+ conditions: assertion.assertions[assertName],
28
+ runsOnKeys: asserts_1.runOnKeysSet.has(assertName),
29
+ runsOnValues: asserts_1.runOnValuesSet.has(assertName),
30
+ };
31
+ });
32
+ const shouldRunOnKeys = assertsToApply.find((assert) => assert.runsOnKeys && !assert.runsOnValues);
33
+ const shouldRunOnValues = assertsToApply.find((assert) => assert.runsOnValues && !assert.runsOnKeys);
34
+ if (shouldRunOnValues && !assertion.subject.property) {
35
+ throw new Error(`${shouldRunOnValues.name} can't be used on all keys. Please provide a single property`);
36
+ }
37
+ if (shouldRunOnKeys && assertion.subject.property) {
38
+ throw new Error(`${shouldRunOnKeys.name} can't be used on a single property. Please use 'property'.`);
39
+ }
40
+ return assertsToApply;
41
+ }
42
+ exports.getAssertsToApply = getAssertsToApply;
43
+ function getAssertionProperties({ subject }) {
44
+ return (Array.isArray(subject.property) ? subject.property : [subject === null || subject === void 0 ? void 0 : subject.property]).filter(Boolean);
45
+ }
46
+ function applyAssertions(assertionDefinition, asserts, { rawLocation, rawNode, resolve, location, node }) {
47
+ var _a;
48
+ const properties = getAssertionProperties(assertionDefinition);
49
+ const assertResults = [];
50
+ for (const assert of asserts) {
51
+ const currentLocation = assert.name === 'ref' ? rawLocation : location;
52
+ if (properties.length) {
53
+ for (const property of properties) {
54
+ // we can have resolvable scalar so need to resolve value here.
55
+ const value = ref_utils_1.isRef(node[property]) ? (_a = resolve(node[property])) === null || _a === void 0 ? void 0 : _a.node : node[property];
56
+ assertResults.push(runAssertion({
57
+ values: value,
58
+ rawValues: rawNode[property],
59
+ assert,
60
+ location: currentLocation.child(property),
61
+ }));
62
+ }
63
+ }
64
+ else {
65
+ const value = assert.name === 'ref' ? rawNode : Object.keys(node);
66
+ assertResults.push(runAssertion({
67
+ values: Object.keys(node),
68
+ rawValues: value,
69
+ assert,
70
+ location: currentLocation,
71
+ }));
72
+ }
73
+ }
74
+ return assertResults.flat();
75
+ }
76
+ function buildVisitorObject(assertion, subjectVisitor) {
77
+ var _a, _b;
78
+ const targetVisitorLocatorPredicates = getPredicatesFromLocators(assertion.subject);
79
+ const targetVisitorSkipFunction = targetVisitorLocatorPredicates.length
80
+ ? (node, key) => !targetVisitorLocatorPredicates.every((predicate) => predicate(key))
81
+ : undefined;
82
+ const targetVisitor = {
83
+ [assertion.subject.type]: Object.assign({ enter: subjectVisitor }, (targetVisitorSkipFunction && { skip: targetVisitorSkipFunction })),
84
+ };
85
+ if (!Array.isArray(assertion.where)) {
86
+ return targetVisitor;
10
87
  }
11
88
  let currentVisitorLevel = {};
12
89
  const visitor = currentVisitorLevel;
90
+ const context = assertion.where;
13
91
  for (let index = 0; index < context.length; index++) {
14
- const node = context[index];
15
- if (context.length === index + 1 && node.type === subject) {
16
- // Visitors don't work properly for the same type nested nodes, so
17
- // as a workaround for that we don't create separate visitor for the last element
18
- // which is the same as subject;
19
- // we will check includes/excludes it in the last visitor.
20
- continue;
92
+ const assertionDefinitionNode = context[index];
93
+ if (!utils_1.isString((_a = assertionDefinitionNode.subject) === null || _a === void 0 ? void 0 : _a.type)) {
94
+ throw new Error(`${assertion.assertionId} -> where -> [${index}]: 'type' (String) is required`);
21
95
  }
22
- const matchParentKeys = node.matchParentKeys;
23
- const excludeParentKeys = node.excludeParentKeys;
24
- if (matchParentKeys && excludeParentKeys) {
25
- throw new Error(`Both 'matchParentKeys' and 'excludeParentKeys' can't be under one context item`);
26
- }
27
- if (matchParentKeys || excludeParentKeys) {
28
- currentVisitorLevel[node.type] = {
29
- skip: (_value, key) => {
30
- if (matchParentKeys) {
31
- return !matchParentKeys.includes(key);
32
- }
33
- if (excludeParentKeys) {
34
- return excludeParentKeys.includes(key);
35
- }
36
- },
37
- };
96
+ const locatorPredicates = getPredicatesFromLocators(assertionDefinitionNode.subject);
97
+ const assertsToApply = getAssertsToApply(assertionDefinitionNode);
98
+ const skipFunction = (node, key, { location, rawLocation, resolve, rawNode }) => !locatorPredicates.every((predicate) => predicate(key)) ||
99
+ !!applyAssertions(assertionDefinitionNode, assertsToApply, {
100
+ location,
101
+ node,
102
+ rawLocation,
103
+ rawNode,
104
+ resolve,
105
+ }).length;
106
+ const nodeVisitor = Object.assign({}, ((locatorPredicates.length || assertsToApply.length) && { skip: skipFunction }));
107
+ if (assertionDefinitionNode.subject.type === assertion.subject.type &&
108
+ index === context.length - 1) {
109
+ // We have to merge the visitors if the last node inside the `where` is the same as the subject.
110
+ targetVisitor[assertion.subject.type] = Object.assign({ enter: subjectVisitor }, ((nodeVisitor.skip && { skip: nodeVisitor.skip }) ||
111
+ (targetVisitorSkipFunction && {
112
+ skip: (node, key, ctx // We may have locators defined on assertion level and on where level for the same node type
113
+ ) => { var _a; return !!(((_a = nodeVisitor.skip) === null || _a === void 0 ? void 0 : _a.call(nodeVisitor, node, key, ctx)) || (targetVisitorSkipFunction === null || targetVisitorSkipFunction === void 0 ? void 0 : targetVisitorSkipFunction(node, key))); },
114
+ })));
38
115
  }
39
116
  else {
40
- currentVisitorLevel[node.type] = {};
117
+ currentVisitorLevel = currentVisitorLevel[(_b = assertionDefinitionNode.subject) === null || _b === void 0 ? void 0 : _b.type] =
118
+ nodeVisitor;
41
119
  }
42
- currentVisitorLevel = currentVisitorLevel[node.type];
43
120
  }
44
- currentVisitorLevel[subject] = subjectVisitor;
121
+ currentVisitorLevel[assertion.subject.type] = targetVisitor[assertion.subject.type];
45
122
  return visitor;
46
123
  }
47
124
  exports.buildVisitorObject = buildVisitorObject;
48
- function buildSubjectVisitor(assertId, assertion, asserts) {
49
- return (node, { report, location, rawLocation, key, type, resolve, rawNode }) => {
50
- var _a;
51
- let properties = assertion.property;
52
- // We need to check context's last node if it has the same type as subject node;
53
- // if yes - that means we didn't create context's last node visitor,
54
- // so we need to handle 'matchParentKeys' and 'excludeParentKeys' conditions here;
55
- if (assertion.context) {
56
- const lastContextNode = assertion.context[assertion.context.length - 1];
57
- if (lastContextNode.type === type.name) {
58
- const matchParentKeys = lastContextNode.matchParentKeys;
59
- const excludeParentKeys = lastContextNode.excludeParentKeys;
60
- if (matchParentKeys && !matchParentKeys.includes(key)) {
61
- return;
62
- }
63
- if (excludeParentKeys && excludeParentKeys.includes(key)) {
64
- return;
65
- }
66
- }
67
- }
68
- if (properties) {
69
- properties = Array.isArray(properties) ? properties : [properties];
70
- }
71
- const defaultMessage = `${logger_1.colorize.blue(assertId)} failed because the ${logger_1.colorize.blue(assertion.subject)}${logger_1.colorize.blue(properties ? ` ${properties.join(', ')}` : '')} didn't meet the assertions: {{problems}}`;
72
- const assertResults = [];
73
- for (const assert of asserts) {
74
- const currentLocation = assert.name === 'ref' ? rawLocation : location;
75
- if (properties) {
76
- for (const property of properties) {
77
- // we can have resolvable scalar so need to resolve value here.
78
- const value = ref_utils_1.isRef(node[property]) ? (_a = resolve(node[property])) === null || _a === void 0 ? void 0 : _a.node : node[property];
79
- assertResults.push(runAssertion({
80
- values: value,
81
- rawValues: rawNode[property],
82
- assert,
83
- location: currentLocation.child(property),
84
- }));
85
- }
86
- }
87
- else {
88
- const value = assert.name === 'ref' ? rawNode : Object.keys(node);
89
- assertResults.push(runAssertion({
90
- values: Object.keys(node),
91
- rawValues: value,
92
- assert,
93
- location: currentLocation,
94
- }));
95
- }
96
- }
97
- const problems = assertResults.flat();
125
+ function buildSubjectVisitor(assertId, assertion) {
126
+ return (node, { report, location, rawLocation, resolve, rawNode }) => {
127
+ const properties = getAssertionProperties(assertion);
128
+ const defaultMessage = `${logger_1.colorize.blue(assertId)} failed because the ${logger_1.colorize.blue(assertion.subject.type)} ${logger_1.colorize.blue(properties.join(', '))} didn't meet the assertions: ${assertionMessageTemplates.problems}`.replace(/ +/g, ' ');
129
+ const problems = applyAssertions(assertion, getAssertsToApply(assertion), {
130
+ rawLocation,
131
+ rawNode,
132
+ resolve,
133
+ location,
134
+ node,
135
+ });
98
136
  if (problems.length) {
99
137
  const message = assertion.message || defaultMessage;
100
- report({
101
- message: message.replace('{{problems}}', getProblemsMessage(problems)),
102
- location: getProblemsLocation(problems) || location,
103
- forceSeverity: assertion.severity || 'error',
104
- suggest: assertion.suggest || [],
105
- ruleId: assertId,
106
- });
138
+ for (const problem of problems) {
139
+ const problemMessage = problem.message ? problem.message : defaultMessage;
140
+ report({
141
+ message: message.replace(assertionMessageTemplates.problems, problemMessage),
142
+ location: problem.location || location,
143
+ forceSeverity: assertion.severity || 'error',
144
+ suggest: assertion.suggest || [],
145
+ ruleId: assertId,
146
+ });
147
+ }
107
148
  }
108
149
  };
109
150
  }
110
151
  exports.buildSubjectVisitor = buildSubjectVisitor;
111
- function getProblemsLocation(problems) {
112
- return problems.length ? problems[0].location : undefined;
113
- }
114
- function getProblemsMessage(problems) {
115
- var _a;
116
- return problems.length === 1
117
- ? (_a = problems[0].message) !== null && _a !== void 0 ? _a : ''
118
- : problems.map((problem) => { var _a; return `\n- ${(_a = problem.message) !== null && _a !== void 0 ? _a : ''}`; }).join('');
119
- }
120
152
  function getIntersectionLength(keys, properties) {
121
153
  const props = new Set(properties);
122
154
  let count = 0;
@@ -142,6 +142,12 @@ const OasSpec = () => {
142
142
  });
143
143
  }
144
144
  }
145
+ if (propName === 'nullable' && !node.type) {
146
+ report({
147
+ message: 'The `type` field must be defined when the `nullable` field is used.',
148
+ location: location.child([propName]),
149
+ });
150
+ }
145
151
  }
146
152
  },
147
153
  };
@@ -3,7 +3,6 @@ export declare const rules: {
3
3
  spec: Oas2Rule;
4
4
  'no-invalid-schema-examples': any;
5
5
  'no-invalid-parameter-examples': any;
6
- 'info-description': Oas2Rule;
7
6
  'info-contact': Oas2Rule;
8
7
  'info-license': Oas2Rule;
9
8
  'info-license-url': Oas2Rule;
@@ -4,7 +4,6 @@ exports.preprocessors = exports.rules = void 0;
4
4
  const spec_1 = require("../common/spec");
5
5
  const no_invalid_schema_examples_1 = require("../common/no-invalid-schema-examples");
6
6
  const no_invalid_parameter_examples_1 = require("../common/no-invalid-parameter-examples");
7
- const info_description_1 = require("../common/info-description");
8
7
  const info_contact_1 = require("../common/info-contact");
9
8
  const info_license_1 = require("../common/info-license");
10
9
  const info_license_url_1 = require("../common/info-license-url");
@@ -46,7 +45,6 @@ exports.rules = {
46
45
  spec: spec_1.OasSpec,
47
46
  'no-invalid-schema-examples': no_invalid_schema_examples_1.NoInvalidSchemaExamples,
48
47
  'no-invalid-parameter-examples': no_invalid_parameter_examples_1.NoInvalidParameterExamples,
49
- 'info-description': info_description_1.InfoDescription,
50
48
  'info-contact': info_contact_1.InfoContact,
51
49
  'info-license': info_license_1.InfoLicense,
52
50
  'info-license-url': info_license_url_1.InfoLicenseUrl,
@@ -17,7 +17,6 @@ const operation_operationId_url_safe_1 = require("../common/operation-operationI
17
17
  const tags_alphabetical_1 = require("../common/tags-alphabetical");
18
18
  const no_server_example_com_1 = require("./no-server-example.com");
19
19
  const no_server_trailing_slash_1 = require("./no-server-trailing-slash");
20
- const info_description_1 = require("../common/info-description");
21
20
  const tag_description_1 = require("../common/tag-description");
22
21
  const info_contact_1 = require("../common/info-contact");
23
22
  const info_license_1 = require("../common/info-license");
@@ -54,7 +53,6 @@ const spec_components_invalid_map_name_1 = require("./spec-components-invalid-ma
54
53
  const operation_4xx_problem_details_rfc7807_1 = require("./operation-4xx-problem-details-rfc7807");
55
54
  exports.rules = {
56
55
  spec: spec_1.OasSpec,
57
- 'info-description': info_description_1.InfoDescription,
58
56
  'info-contact': info_contact_1.InfoContact,
59
57
  'info-license': info_license_1.InfoLicense,
60
58
  'info-license-url': info_license_url_1.InfoLicenseUrl,
@@ -101,6 +101,9 @@ function validateExample(example, schema, dataLoc, { resolve, location, report }
101
101
  }
102
102
  }
103
103
  catch (e) {
104
+ if (e.message === 'discriminator: requires oneOf or anyOf composite keyword') {
105
+ return;
106
+ }
104
107
  report({
105
108
  message: `Example validation errored: ${e.message}.`,
106
109
  location: location.child('schema'),
package/lib/types/oas2.js CHANGED
@@ -17,8 +17,8 @@ const Root = {
17
17
  parameters: 'NamedParameters',
18
18
  responses: 'NamedResponses',
19
19
  securityDefinitions: 'NamedSecuritySchemes',
20
- security: _1.listOf('SecurityRequirement'),
21
- tags: _1.listOf('Tag'),
20
+ security: 'SecurityRequirementList',
21
+ tags: 'TagList',
22
22
  externalDocs: 'ExternalDocs',
23
23
  },
24
24
  required: ['swagger', 'paths', 'info'],
@@ -55,7 +55,7 @@ const Paths = {
55
55
  const PathItem = {
56
56
  properties: {
57
57
  $ref: { type: 'string' },
58
- parameters: _1.listOf('Parameter'),
58
+ parameters: 'ParameterList',
59
59
  get: 'Operation',
60
60
  put: 'Operation',
61
61
  post: 'Operation',
@@ -74,13 +74,13 @@ const Operation = {
74
74
  operationId: { type: 'string' },
75
75
  consumes: { type: 'array', items: { type: 'string' } },
76
76
  produces: { type: 'array', items: { type: 'string' } },
77
- parameters: _1.listOf('Parameter'),
77
+ parameters: 'ParameterList',
78
78
  responses: 'Responses',
79
79
  schemes: { type: 'array', items: { type: 'string' } },
80
80
  deprecated: { type: 'boolean' },
81
- security: _1.listOf('SecurityRequirement'),
82
- 'x-codeSamples': _1.listOf('XCodeSample'),
83
- 'x-code-samples': _1.listOf('XCodeSample'),
81
+ security: 'SecurityRequirementList',
82
+ 'x-codeSamples': 'XCodeSampleList',
83
+ 'x-code-samples': 'XCodeSampleList',
84
84
  'x-hideTryItPanel': { type: 'boolean' },
85
85
  },
86
86
  required: ['responses'],
@@ -354,8 +354,10 @@ const SecurityRequirement = {
354
354
  exports.Oas2Types = {
355
355
  Root,
356
356
  Tag,
357
+ TagList: _1.listOf('Tag'),
357
358
  ExternalDocs,
358
359
  SecurityRequirement,
360
+ SecurityRequirementList: _1.listOf('SecurityRequirement'),
359
361
  Info,
360
362
  Contact,
361
363
  License,
@@ -363,6 +365,7 @@ exports.Oas2Types = {
363
365
  PathItem,
364
366
  Parameter,
365
367
  ParameterItems,
368
+ ParameterList: _1.listOf('Parameter'),
366
369
  Operation,
367
370
  Examples,
368
371
  Header,
@@ -377,4 +380,5 @@ exports.Oas2Types = {
377
380
  NamedSecuritySchemes: _1.mapOf('SecurityScheme'),
378
381
  SecurityScheme,
379
382
  XCodeSample,
383
+ XCodeSampleList: _1.listOf('XCodeSample'),
380
384
  };
package/lib/types/oas3.js CHANGED
@@ -8,9 +8,9 @@ const Root = {
8
8
  properties: {
9
9
  openapi: null,
10
10
  info: 'Info',
11
- servers: _1.listOf('Server'),
12
- security: _1.listOf('SecurityRequirement'),
13
- tags: _1.listOf('Tag'),
11
+ servers: 'ServerList',
12
+ security: 'SecurityRequirementList',
13
+ tags: 'TagList',
14
14
  externalDocs: 'ExternalDocs',
15
15
  paths: 'Paths',
16
16
  components: 'Components',
@@ -92,8 +92,8 @@ const WebhooksMap = {
92
92
  const PathItem = {
93
93
  properties: {
94
94
  $ref: { type: 'string' },
95
- servers: _1.listOf('Server'),
96
- parameters: _1.listOf('Parameter'),
95
+ servers: 'ServerList',
96
+ parameters: 'ParameterList',
97
97
  summary: { type: 'string' },
98
98
  description: { type: 'string' },
99
99
  get: 'Operation',
@@ -137,15 +137,15 @@ const Operation = {
137
137
  description: { type: 'string' },
138
138
  externalDocs: 'ExternalDocs',
139
139
  operationId: { type: 'string' },
140
- parameters: _1.listOf('Parameter'),
141
- security: _1.listOf('SecurityRequirement'),
142
- servers: _1.listOf('Server'),
140
+ parameters: 'ParameterList',
141
+ security: 'SecurityRequirementList',
142
+ servers: 'ServerList',
143
143
  requestBody: 'RequestBody',
144
144
  responses: 'Responses',
145
145
  deprecated: { type: 'boolean' },
146
146
  callbacks: 'CallbacksMap',
147
- 'x-codeSamples': _1.listOf('XCodeSample'),
148
- 'x-code-samples': _1.listOf('XCodeSample'),
147
+ 'x-codeSamples': 'XCodeSampleList',
148
+ 'x-code-samples': 'XCodeSampleList',
149
149
  'x-hideTryItPanel': { type: 'boolean' },
150
150
  },
151
151
  required: ['responses'],
@@ -430,17 +430,21 @@ const SecurityScheme = {
430
430
  exports.Oas3Types = {
431
431
  Root,
432
432
  Tag,
433
+ TagList: _1.listOf('Tag'),
433
434
  ExternalDocs,
434
435
  Server,
436
+ ServerList: _1.listOf('Server'),
435
437
  ServerVariable,
436
438
  ServerVariablesMap: _1.mapOf('ServerVariable'),
437
439
  SecurityRequirement,
440
+ SecurityRequirementList: _1.listOf('SecurityRequirement'),
438
441
  Info,
439
442
  Contact,
440
443
  License,
441
444
  Paths,
442
445
  PathItem,
443
446
  Parameter,
447
+ ParameterList: _1.listOf('Parameter'),
444
448
  Operation,
445
449
  Callback: _1.mapOf('PathItem'),
446
450
  CallbacksMap: _1.mapOf('Callback'),
@@ -479,5 +483,6 @@ exports.Oas3Types = {
479
483
  OAuth2Flows,
480
484
  SecurityScheme,
481
485
  XCodeSample,
486
+ XCodeSampleList: _1.listOf('XCodeSample'),
482
487
  WebhooksMap,
483
488
  };
@@ -78,6 +78,7 @@ const Operation = {
78
78
  const Schema = {
79
79
  properties: {
80
80
  $id: { type: 'string' },
81
+ $anchor: { type: 'string' },
81
82
  id: { type: 'string' },
82
83
  $schema: { type: 'string' },
83
84
  definitions: 'NamedSchemas',
@@ -5,7 +5,6 @@ const _1 = require(".");
5
5
  const utils_1 = require("../utils");
6
6
  const builtInRulesList = [
7
7
  'spec',
8
- 'info-description',
9
8
  'info-contact',
10
9
  'info-license',
11
10
  'info-license-url',
@@ -60,17 +59,21 @@ const builtInRulesList = [
60
59
  const nodeTypesList = [
61
60
  'Root',
62
61
  'Tag',
62
+ 'TagList',
63
63
  'ExternalDocs',
64
64
  'Server',
65
+ 'ServerList',
65
66
  'ServerVariable',
66
67
  'ServerVariablesMap',
67
68
  'SecurityRequirement',
69
+ 'SecurityRequirementList',
68
70
  'Info',
69
71
  'Contact',
70
72
  'License',
71
73
  'Paths',
72
74
  'PathItem',
73
75
  'Parameter',
76
+ 'ParameterList',
74
77
  'Operation',
75
78
  'Callback',
76
79
  'CallbacksMap',
@@ -109,6 +112,7 @@ const nodeTypesList = [
109
112
  'OAuth2Flows',
110
113
  'SecurityScheme',
111
114
  'XCodeSample',
115
+ 'XCodeSampleList',
112
116
  'WebhooksMap',
113
117
  ];
114
118
  const ConfigStyleguide = {
@@ -140,11 +144,7 @@ const RootConfigStyleguide = {
140
144
  } }, ConfigStyleguide.properties),
141
145
  };
142
146
  const ConfigRoot = {
143
- properties: Object.assign(Object.assign({ organization: { type: 'string' }, apis: 'ConfigApis', apiDefinitions: {
144
- type: 'object',
145
- properties: {},
146
- additionalProperties: { properties: { type: 'string' } },
147
- } }, RootConfigStyleguide.properties), { styleguide: 'RootConfigStyleguide', lint: 'RootConfigStyleguide', 'features.openapi': 'ConfigReferenceDocs', referenceDocs: 'ConfigReferenceDocs', 'features.mockServer': 'ConfigMockServer', region: { enum: ['us', 'eu'] }, resolve: {
147
+ properties: Object.assign(Object.assign({ organization: { type: 'string' }, apis: 'ConfigApis' }, RootConfigStyleguide.properties), { 'features.openapi': 'ConfigReferenceDocs', 'features.mockServer': 'ConfigMockServer', region: { enum: ['us', 'eu'] }, resolve: {
148
148
  properties: {
149
149
  http: 'ConfigHTTP',
150
150
  doNotResolveExamples: { type: 'boolean' },
@@ -209,16 +209,9 @@ const ObjectRule = {
209
209
  additionalProperties: {},
210
210
  required: ['severity'],
211
211
  };
212
- const Assert = {
212
+ const AssertionDefinitionSubject = {
213
213
  properties: {
214
- subject: (value) => {
215
- if (Array.isArray(value)) {
216
- return { type: 'array', items: { enum: nodeTypesList } };
217
- }
218
- else {
219
- return { enum: nodeTypesList };
220
- }
221
- },
214
+ type: { enum: nodeTypesList },
222
215
  property: (value) => {
223
216
  if (Array.isArray(value)) {
224
217
  return { type: 'array', items: { type: 'string' } };
@@ -230,10 +223,14 @@ const Assert = {
230
223
  return { type: 'string' };
231
224
  }
232
225
  },
233
- context: _1.listOf('Context'),
234
- message: { type: 'string' },
235
- suggest: { type: 'array', items: { type: 'string' } },
236
- severity: { enum: ['error', 'warn', 'off'] },
226
+ filterInParentKeys: { type: 'array', items: { type: 'string' } },
227
+ filterOutParentKeys: { type: 'array', items: { type: 'string' } },
228
+ matchParentKeys: { type: 'string' },
229
+ },
230
+ required: ['type'],
231
+ };
232
+ const AssertionDefinitionAssertions = {
233
+ properties: {
237
234
  enum: { type: 'array', items: { type: 'string' } },
238
235
  pattern: { type: 'string' },
239
236
  casing: {
@@ -253,26 +250,49 @@ const Assert = {
253
250
  requireAny: { type: 'array', items: { type: 'string' } },
254
251
  disallowed: { type: 'array', items: { type: 'string' } },
255
252
  defined: { type: 'boolean' },
256
- undefined: { type: 'boolean' },
253
+ // undefined: { type: 'boolean' }, // TODO: Remove `undefined` assertion from codebase overall
257
254
  nonEmpty: { type: 'boolean' },
258
255
  minLength: { type: 'integer' },
259
256
  maxLength: { type: 'integer' },
260
257
  ref: (value) => typeof value === 'string' ? { type: 'string' } : { type: 'boolean' },
258
+ const: (value) => {
259
+ if (typeof value === 'string') {
260
+ return { type: 'string' };
261
+ }
262
+ if (typeof value === 'number') {
263
+ return { type: 'number' };
264
+ }
265
+ if (typeof value === 'boolean') {
266
+ return { type: 'boolean' };
267
+ }
268
+ else {
269
+ return;
270
+ }
271
+ },
261
272
  },
262
273
  additionalProperties: (_value, key) => {
263
274
  if (/^\w+\/\w+$/.test(key))
264
275
  return { type: 'object' };
265
276
  return;
266
277
  },
267
- required: ['subject'],
268
278
  };
269
- const Context = {
279
+ const AssertDefinition = {
270
280
  properties: {
271
- type: { enum: nodeTypesList },
272
- matchParentKeys: { type: 'array', items: { type: 'string' } },
273
- excludeParentKeys: { type: 'array', items: { type: 'string' } },
281
+ subject: 'AssertionDefinitionSubject',
282
+ assertions: 'AssertionDefinitionAssertions',
274
283
  },
275
- required: ['type'],
284
+ required: ['subject', 'assertions'],
285
+ };
286
+ const Assert = {
287
+ properties: {
288
+ subject: 'AssertionDefinitionSubject',
289
+ assertions: 'AssertionDefinitionAssertions',
290
+ where: _1.listOf('AssertDefinition'),
291
+ message: { type: 'string' },
292
+ suggest: { type: 'array', items: { type: 'string' } },
293
+ severity: { enum: ['error', 'warn', 'off'] },
294
+ },
295
+ required: ['subject', 'assertions'],
276
296
  };
277
297
  const ConfigLanguage = {
278
298
  properties: {
@@ -792,7 +812,7 @@ exports.ConfigTypes = {
792
812
  ConfigSidebarLinks,
793
813
  CommonConfigSidebarLinks,
794
814
  ConfigTheme,
795
- Context,
815
+ AssertDefinition,
796
816
  ThemeColors,
797
817
  CommonThemeColors,
798
818
  BorderThemeColors,
@@ -839,4 +859,6 @@ exports.ConfigTypes = {
839
859
  Sidebar,
840
860
  Heading,
841
861
  Typography,
862
+ AssertionDefinitionAssertions,
863
+ AssertionDefinitionSubject,
842
864
  };
package/lib/utils.d.ts CHANGED
@@ -46,4 +46,6 @@ export declare function showErrorForDeprecatedField(deprecatedField: string, upd
46
46
  export declare type Falsy = undefined | null | false | '' | 0;
47
47
  export declare function isTruthy<Truthy>(value: Truthy | Falsy): value is Truthy;
48
48
  export declare function identity<T>(value: T): T;
49
+ export declare function keysOf<T>(obj: T): (keyof T)[];
49
50
  export declare function pickDefined<T extends Record<string, unknown>>(obj?: T): Record<string, unknown> | undefined;
51
+ export declare function nextTick(): void;