@redocly/openapi-core 1.0.2 → 1.2.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.
Files changed (80) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/lib/bundle.d.ts +2 -2
  3. package/lib/bundle.js +24 -22
  4. package/lib/config/builtIn.js +4 -0
  5. package/lib/config/config-resolvers.js +19 -6
  6. package/lib/config/config.d.ts +9 -9
  7. package/lib/config/config.js +32 -17
  8. package/lib/config/rules.d.ts +2 -2
  9. package/lib/config/types.d.ts +9 -3
  10. package/lib/format/codeframes.d.ts +1 -1
  11. package/lib/index.d.ts +1 -1
  12. package/lib/index.js +7 -6
  13. package/lib/lint.js +10 -16
  14. package/lib/oas-types.d.ts +16 -10
  15. package/lib/oas-types.js +52 -26
  16. package/lib/rules/async2/channels-kebab-case.d.ts +2 -0
  17. package/lib/rules/async2/channels-kebab-case.js +19 -0
  18. package/lib/rules/async2/index.d.ts +12 -0
  19. package/lib/rules/async2/index.js +22 -0
  20. package/lib/rules/async2/no-channel-trailing-slash.d.ts +2 -0
  21. package/lib/rules/async2/no-channel-trailing-slash.js +16 -0
  22. package/lib/rules/common/no-path-trailing-slash.js +2 -2
  23. package/lib/rules/common/scalar-property-missing-example.js +1 -1
  24. package/lib/rules/common/spec.d.ts +2 -2
  25. package/lib/rules/common/spec.js +3 -3
  26. package/lib/rules/common/tags-alphabetical.js +5 -2
  27. package/lib/rules/oas2/index.js +1 -1
  28. package/lib/rules/oas2/remove-unused-components.js +4 -1
  29. package/lib/rules/oas3/index.js +1 -1
  30. package/lib/rules/oas3/remove-unused-components.js +4 -1
  31. package/lib/rules/utils.d.ts +1 -1
  32. package/lib/types/asyncapi.d.ts +2 -0
  33. package/lib/types/asyncapi.js +1027 -0
  34. package/lib/types/portal-config-schema.d.ts +2533 -0
  35. package/lib/types/portal-config-schema.js +304 -0
  36. package/lib/types/redocly-yaml.js +26 -20
  37. package/lib/types/{config-external-schemas.d.ts → theme-config.d.ts} +140 -575
  38. package/lib/types/{config-external-schemas.js → theme-config.js} +55 -261
  39. package/lib/typings/asyncapi.d.ts +21 -0
  40. package/lib/typings/asyncapi.js +2 -0
  41. package/lib/visitors.d.ts +12 -0
  42. package/lib/walk.d.ts +3 -3
  43. package/package.json +3 -2
  44. package/src/__tests__/lint.test.ts +38 -6
  45. package/src/bundle.ts +27 -28
  46. package/src/config/__tests__/__snapshots__/config.test.ts.snap +24 -0
  47. package/src/config/__tests__/config.test.ts +15 -4
  48. package/src/config/builtIn.ts +4 -0
  49. package/src/config/config-resolvers.ts +25 -6
  50. package/src/config/config.ts +51 -27
  51. package/src/config/rules.ts +2 -2
  52. package/src/config/types.ts +14 -4
  53. package/src/index.ts +7 -1
  54. package/src/lint.ts +13 -22
  55. package/src/oas-types.ts +59 -21
  56. package/src/rules/async2/__tests__/channels-kebab-case.test.ts +141 -0
  57. package/src/rules/async2/__tests__/no-channel-trailing-slash.test.ts +97 -0
  58. package/src/rules/async2/channels-kebab-case.ts +18 -0
  59. package/src/rules/async2/index.ts +22 -0
  60. package/src/rules/async2/no-channel-trailing-slash.ts +15 -0
  61. package/src/rules/common/__tests__/no-path-trailing-slash.test.ts +41 -0
  62. package/src/rules/common/__tests__/tags-alphabetical.test.ts +58 -0
  63. package/src/rules/common/no-path-trailing-slash.ts +2 -2
  64. package/src/rules/common/scalar-property-missing-example.ts +2 -2
  65. package/src/rules/common/spec.ts +2 -2
  66. package/src/rules/common/tags-alphabetical.ts +8 -4
  67. package/src/rules/oas2/__tests__/remove-unused-components.test.ts +155 -0
  68. package/src/rules/oas2/index.ts +2 -2
  69. package/src/rules/oas2/remove-unused-components.ts +6 -1
  70. package/src/rules/oas3/__tests__/remove-unused-components.test.ts +171 -0
  71. package/src/rules/oas3/index.ts +2 -2
  72. package/src/rules/oas3/remove-unused-components.ts +6 -1
  73. package/src/types/asyncapi.ts +1136 -0
  74. package/src/types/portal-config-schema.ts +343 -0
  75. package/src/types/redocly-yaml.ts +23 -34
  76. package/src/types/{config-external-schemas.ts → theme-config.ts} +60 -294
  77. package/src/typings/asyncapi.ts +26 -0
  78. package/src/visitors.ts +22 -0
  79. package/src/walk.ts +3 -3
  80. package/tsconfig.tsbuildinfo +1 -1
package/lib/oas-types.js CHANGED
@@ -1,45 +1,71 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.openAPIMajor = exports.detectOpenAPI = exports.OasMajorVersion = exports.OasVersion = void 0;
4
- var OasVersion;
5
- (function (OasVersion) {
6
- OasVersion["Version2"] = "oas2";
7
- OasVersion["Version3_0"] = "oas3_0";
8
- OasVersion["Version3_1"] = "oas3_1";
9
- })(OasVersion = exports.OasVersion || (exports.OasVersion = {}));
10
- var OasMajorVersion;
11
- (function (OasMajorVersion) {
12
- OasMajorVersion["Version2"] = "oas2";
13
- OasMajorVersion["Version3"] = "oas3";
14
- })(OasMajorVersion = exports.OasMajorVersion || (exports.OasMajorVersion = {}));
15
- function detectOpenAPI(root) {
3
+ exports.getTypes = exports.getMajorSpecVersion = exports.detectSpec = exports.SpecMajorVersion = exports.SpecVersion = void 0;
4
+ const oas2_1 = require("./types/oas2");
5
+ const oas3_1 = require("./types/oas3");
6
+ const oas3_1_1 = require("./types/oas3_1");
7
+ const asyncapi_1 = require("./types/asyncapi");
8
+ var SpecVersion;
9
+ (function (SpecVersion) {
10
+ SpecVersion["OAS2"] = "oas2";
11
+ SpecVersion["OAS3_0"] = "oas3_0";
12
+ SpecVersion["OAS3_1"] = "oas3_1";
13
+ SpecVersion["Async2"] = "async2";
14
+ })(SpecVersion = exports.SpecVersion || (exports.SpecVersion = {}));
15
+ var SpecMajorVersion;
16
+ (function (SpecMajorVersion) {
17
+ SpecMajorVersion["OAS2"] = "oas2";
18
+ SpecMajorVersion["OAS3"] = "oas3";
19
+ SpecMajorVersion["Async2"] = "async2";
20
+ })(SpecMajorVersion = exports.SpecMajorVersion || (exports.SpecMajorVersion = {}));
21
+ const typesMap = {
22
+ [SpecVersion.OAS2]: oas2_1.Oas2Types,
23
+ [SpecVersion.OAS3_0]: oas3_1.Oas3Types,
24
+ [SpecVersion.OAS3_1]: oas3_1_1.Oas3_1Types,
25
+ [SpecVersion.Async2]: asyncapi_1.AsyncApi2Types,
26
+ };
27
+ function detectSpec(root) {
16
28
  if (typeof root !== 'object') {
17
29
  throw new Error(`Document must be JSON object, got ${typeof root}`);
18
30
  }
19
- if (!(root.openapi || root.swagger)) {
20
- throw new Error('This doesn’t look like an OpenAPI document.\n');
21
- }
22
31
  if (root.openapi && typeof root.openapi !== 'string') {
23
32
  throw new Error(`Invalid OpenAPI version: should be a string but got "${typeof root.openapi}"`);
24
33
  }
25
34
  if (root.openapi && root.openapi.startsWith('3.0')) {
26
- return OasVersion.Version3_0;
35
+ return SpecVersion.OAS3_0;
27
36
  }
28
37
  if (root.openapi && root.openapi.startsWith('3.1')) {
29
- return OasVersion.Version3_1;
38
+ return SpecVersion.OAS3_1;
30
39
  }
31
40
  if (root.swagger && root.swagger === '2.0') {
32
- return OasVersion.Version2;
41
+ return SpecVersion.OAS2;
42
+ }
43
+ // if not detected yet
44
+ if (root.openapi || root.swagger) {
45
+ throw new Error(`Unsupported OpenAPI version: ${root.openapi || root.swagger}`);
46
+ }
47
+ if (root.asyncapi && root.asyncapi.startsWith('2.')) {
48
+ return SpecVersion.Async2;
33
49
  }
34
- throw new Error(`Unsupported OpenAPI Version: ${root.openapi || root.swagger}`);
50
+ if (root.asyncapi) {
51
+ throw new Error(`Unsupported AsyncAPI version: ${root.asyncapi}`);
52
+ }
53
+ throw new Error(`Unsupported specification`);
35
54
  }
36
- exports.detectOpenAPI = detectOpenAPI;
37
- function openAPIMajor(version) {
38
- if (version === OasVersion.Version2) {
39
- return OasMajorVersion.Version2;
55
+ exports.detectSpec = detectSpec;
56
+ function getMajorSpecVersion(version) {
57
+ if (version === SpecVersion.OAS2) {
58
+ return SpecMajorVersion.OAS2;
59
+ }
60
+ else if (version === SpecVersion.Async2) {
61
+ return SpecMajorVersion.Async2;
40
62
  }
41
63
  else {
42
- return OasMajorVersion.Version3;
64
+ return SpecMajorVersion.OAS3;
43
65
  }
44
66
  }
45
- exports.openAPIMajor = openAPIMajor;
67
+ exports.getMajorSpecVersion = getMajorSpecVersion;
68
+ function getTypes(spec) {
69
+ return typesMap[spec];
70
+ }
71
+ exports.getTypes = getTypes;
@@ -0,0 +1,2 @@
1
+ import { Async2Rule } from '../../visitors';
2
+ export declare const ChannelsKebabCase: Async2Rule;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ChannelsKebabCase = void 0;
4
+ const ChannelsKebabCase = () => {
5
+ return {
6
+ Channel(_channel, { report, key }) {
7
+ const segments = key
8
+ .split(/[/.:]/) // split on / or : as likely channel namespacers
9
+ .filter((s) => s !== ''); // filter out empty segments
10
+ if (!segments.every((segment) => /^{.+}$/.test(segment) || /^[a-z0-9-.]+$/.test(segment))) {
11
+ report({
12
+ message: `\`${key}\` does not use kebab-case.`,
13
+ location: { reportOnKey: true },
14
+ });
15
+ }
16
+ },
17
+ };
18
+ };
19
+ exports.ChannelsKebabCase = ChannelsKebabCase;
@@ -0,0 +1,12 @@
1
+ import { Async2Rule } from '../../visitors';
2
+ export declare const rules: {
3
+ spec: Async2Rule;
4
+ assertions: (opts: Record<string, import("../common/assertions").Assertion>) => (import("../../visitors").Oas3Visitor | import("../../visitors").Oas2Visitor)[];
5
+ 'info-contact': import("../../visitors").Oas3Rule | import("../../visitors").Oas2Rule;
6
+ 'operation-operationId': import("../../visitors").Oas3Rule | import("../../visitors").Oas2Rule;
7
+ 'channels-kebab-case': Async2Rule;
8
+ 'no-channel-trailing-slash': Async2Rule;
9
+ 'tag-description': import("../../visitors").Oas3Rule | import("../../visitors").Oas2Rule;
10
+ 'tags-alphabetical': import("../../visitors").Oas3Rule | import("../../visitors").Oas2Rule;
11
+ };
12
+ export declare const preprocessors: {};
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.preprocessors = exports.rules = void 0;
4
+ const assertions_1 = require("../common/assertions");
5
+ const spec_1 = require("../common/spec");
6
+ const info_contact_1 = require("../common/info-contact");
7
+ const operation_operationId_1 = require("../common/operation-operationId");
8
+ const tag_description_1 = require("../common/tag-description");
9
+ const tags_alphabetical_1 = require("../common/tags-alphabetical");
10
+ const channels_kebab_case_1 = require("./channels-kebab-case");
11
+ const no_channel_trailing_slash_1 = require("./no-channel-trailing-slash");
12
+ exports.rules = {
13
+ spec: spec_1.Spec,
14
+ assertions: assertions_1.Assertions,
15
+ 'info-contact': info_contact_1.InfoContact,
16
+ 'operation-operationId': operation_operationId_1.OperationOperationId,
17
+ 'channels-kebab-case': channels_kebab_case_1.ChannelsKebabCase,
18
+ 'no-channel-trailing-slash': no_channel_trailing_slash_1.NoChannelTrailingSlash,
19
+ 'tag-description': tag_description_1.TagDescription,
20
+ 'tags-alphabetical': tags_alphabetical_1.TagsAlphabetical,
21
+ };
22
+ exports.preprocessors = {};
@@ -0,0 +1,2 @@
1
+ import { Async2Rule } from '../../visitors';
2
+ export declare const NoChannelTrailingSlash: Async2Rule;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NoChannelTrailingSlash = void 0;
4
+ const NoChannelTrailingSlash = () => {
5
+ return {
6
+ Channel(_channel, { report, key, location }) {
7
+ if (key.endsWith('/') && key !== '/') {
8
+ report({
9
+ message: `\`${key}\` should not have a trailing slash.`,
10
+ location: location.key(),
11
+ });
12
+ }
13
+ },
14
+ };
15
+ };
16
+ exports.NoChannelTrailingSlash = NoChannelTrailingSlash;
@@ -3,11 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NoPathTrailingSlash = void 0;
4
4
  const NoPathTrailingSlash = () => {
5
5
  return {
6
- PathItem(_path, { report, key, location }) {
6
+ PathItem(_path, { report, key, rawLocation }) {
7
7
  if (key.endsWith('/') && key !== '/') {
8
8
  report({
9
9
  message: `\`${key}\` should not have a trailing slash.`,
10
- location: location.key(),
10
+ location: rawLocation.key(),
11
11
  });
12
12
  }
13
13
  },
@@ -14,7 +14,7 @@ const ScalarPropertyMissingExample = () => {
14
14
  if (propSchema.example === undefined &&
15
15
  propSchema.examples === undefined) {
16
16
  report({
17
- message: `Scalar property should have "example"${oasVersion === oas_types_1.OasVersion.Version3_1 ? ' or "examples"' : ''} defined.`,
17
+ message: `Scalar property should have "example"${oasVersion === oas_types_1.SpecVersion.OAS3_1 ? ' or "examples"' : ''} defined.`,
18
18
  location: location.child(propName).key(),
19
19
  });
20
20
  }
@@ -1,2 +1,2 @@
1
- import type { Oas3Rule, Oas2Rule } from '../../visitors';
2
- export declare const OasSpec: Oas3Rule | Oas2Rule;
1
+ import type { Oas3Rule, Oas2Rule, Async2Rule } from '../../visitors';
2
+ export declare const Spec: Oas3Rule | Oas2Rule | Async2Rule;
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.OasSpec = void 0;
3
+ exports.Spec = void 0;
4
4
  const types_1 = require("../../types");
5
5
  const utils_1 = require("../utils");
6
6
  const ref_utils_1 = require("../../ref-utils");
7
7
  const utils_2 = require("../../utils");
8
- const OasSpec = () => {
8
+ const Spec = () => {
9
9
  return {
10
10
  any(node, { report, type, location, rawLocation, key, resolve, ignoreNextVisitorsOnNode }) {
11
11
  var _a, _b, _c, _d, _e, _f;
@@ -156,4 +156,4 @@ const OasSpec = () => {
156
156
  },
157
157
  };
158
158
  };
159
- exports.OasSpec = OasSpec;
159
+ exports.Spec = Spec;
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TagsAlphabetical = void 0;
4
- const TagsAlphabetical = () => {
4
+ const TagsAlphabetical = ({ ignoreCase = false }) => {
5
5
  return {
6
6
  Root(root, { report, location }) {
7
7
  if (!root.tags)
8
8
  return;
9
9
  for (let i = 0; i < root.tags.length - 1; i++) {
10
- if (root.tags[i].name > root.tags[i + 1].name) {
10
+ if (getTagName(root.tags[i], ignoreCase) > getTagName(root.tags[i + 1], ignoreCase)) {
11
11
  report({
12
12
  message: 'The `tags` array should be in alphabetical order.',
13
13
  location: location.child(['tags', i]),
@@ -18,3 +18,6 @@ const TagsAlphabetical = () => {
18
18
  };
19
19
  };
20
20
  exports.TagsAlphabetical = TagsAlphabetical;
21
+ function getTagName(tag, ignoreCase) {
22
+ return ignoreCase ? tag.name.toLowerCase() : tag.name;
23
+ }
@@ -44,7 +44,7 @@ const scalar_property_missing_example_1 = require("../common/scalar-property-mis
44
44
  const required_string_property_missing_min_length_1 = require("../common/required-string-property-missing-min-length");
45
45
  const spec_strict_refs_1 = require("../common/spec-strict-refs");
46
46
  exports.rules = {
47
- spec: spec_1.OasSpec,
47
+ spec: spec_1.Spec,
48
48
  'no-invalid-schema-examples': no_invalid_schema_examples_1.NoInvalidSchemaExamples,
49
49
  'no-invalid-parameter-examples': no_invalid_parameter_examples_1.NoInvalidParameterExamples,
50
50
  'info-contact': info_contact_1.InfoContact,
@@ -19,7 +19,10 @@ const RemoveUnusedComponents = () => {
19
19
  const resolvedRef = resolve(ref);
20
20
  if (!resolvedRef.location)
21
21
  return;
22
- components.set(resolvedRef.location.absolutePointer, {
22
+ const [fileLocation, localPointer] = resolvedRef.location.absolutePointer.split('#', 2);
23
+ const componentLevelLocalPointer = localPointer.split('/').slice(0, 3).join('/');
24
+ const pointer = `${fileLocation}#${componentLevelLocalPointer}`;
25
+ components.set(pointer, {
23
26
  used: true,
24
27
  name: key.toString(),
25
28
  });
@@ -55,7 +55,7 @@ const required_string_property_missing_min_length_1 = require("../common/require
55
55
  const spec_strict_refs_1 = require("../common/spec-strict-refs");
56
56
  const component_name_unique_1 = require("./component-name-unique");
57
57
  exports.rules = {
58
- spec: spec_1.OasSpec,
58
+ spec: spec_1.Spec,
59
59
  'info-contact': info_contact_1.InfoContact,
60
60
  'info-license': info_license_1.InfoLicense,
61
61
  'info-license-url': info_license_url_1.InfoLicenseUrl,
@@ -19,7 +19,10 @@ const RemoveUnusedComponents = () => {
19
19
  const resolvedRef = resolve(ref);
20
20
  if (!resolvedRef.location)
21
21
  return;
22
- components.set(resolvedRef.location.absolutePointer, {
22
+ const [fileLocation, localPointer] = resolvedRef.location.absolutePointer.split('#', 2);
23
+ const componentLevelLocalPointer = localPointer.split('/').slice(0, 4).join('/');
24
+ const pointer = `${fileLocation}#${componentLevelLocalPointer}`;
25
+ components.set(pointer, {
23
26
  used: true,
24
27
  name: key.toString(),
25
28
  });
@@ -1,7 +1,7 @@
1
1
  import { UserContext } from '../walk';
2
2
  import { Location } from '../ref-utils';
3
3
  import { Oas3Schema, Referenced } from '../typings/openapi';
4
- export declare function oasTypeOf(value: unknown): "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | "null" | "integer" | "array";
4
+ export declare function oasTypeOf(value: unknown): "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" | "integer" | "array" | "null";
5
5
  /**
6
6
  * Checks if value matches specified JSON schema type
7
7
  *
@@ -0,0 +1,2 @@
1
+ import { NodeType } from '.';
2
+ export declare const AsyncApi2Types: Record<string, NodeType>;