@redocly/openapi-core 1.1.0 → 1.2.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.
Files changed (77) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +250 -7
  3. package/lib/bundle.d.ts +12 -6
  4. package/lib/bundle.js +34 -24
  5. package/lib/config/builtIn.js +4 -0
  6. package/lib/config/config-resolvers.js +19 -6
  7. package/lib/config/config.d.ts +9 -9
  8. package/lib/config/config.js +32 -17
  9. package/lib/config/load.d.ts +3 -2
  10. package/lib/config/load.js +2 -2
  11. package/lib/config/rules.d.ts +2 -2
  12. package/lib/config/types.d.ts +10 -3
  13. package/lib/index.d.ts +4 -3
  14. package/lib/index.js +10 -6
  15. package/lib/lint.js +10 -16
  16. package/lib/oas-types.d.ts +16 -10
  17. package/lib/oas-types.js +52 -26
  18. package/lib/rules/async2/channels-kebab-case.d.ts +2 -0
  19. package/lib/rules/async2/channels-kebab-case.js +19 -0
  20. package/lib/rules/async2/index.d.ts +12 -0
  21. package/lib/rules/async2/index.js +22 -0
  22. package/lib/rules/async2/no-channel-trailing-slash.d.ts +2 -0
  23. package/lib/rules/async2/no-channel-trailing-slash.js +16 -0
  24. package/lib/rules/common/assertions/asserts.js +12 -4
  25. package/lib/rules/common/scalar-property-missing-example.js +1 -1
  26. package/lib/rules/common/spec.d.ts +2 -2
  27. package/lib/rules/common/spec.js +3 -3
  28. package/lib/rules/oas2/index.js +1 -1
  29. package/lib/rules/oas3/index.js +1 -1
  30. package/lib/rules/oas3/no-server-example.com.js +3 -2
  31. package/lib/types/asyncapi.d.ts +2 -0
  32. package/lib/types/asyncapi.js +1034 -0
  33. package/lib/types/oas3_1.js +8 -1
  34. package/lib/types/redocly-yaml.js +3 -0
  35. package/lib/typings/asyncapi.d.ts +21 -0
  36. package/lib/typings/asyncapi.js +2 -0
  37. package/lib/visitors.d.ts +12 -0
  38. package/lib/walk.d.ts +3 -3
  39. package/package.json +4 -2
  40. package/src/__tests__/__snapshots__/bundle.test.ts.snap +1 -1
  41. package/src/__tests__/bundle.test.ts +65 -25
  42. package/src/__tests__/fixtures/lint/openapi.yaml +10 -0
  43. package/src/__tests__/fixtures/redocly.yaml +2 -0
  44. package/src/__tests__/lint.test.ts +67 -8
  45. package/src/bundle.ts +62 -35
  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/__tests__/load.test.ts +35 -2
  49. package/src/config/builtIn.ts +4 -0
  50. package/src/config/config-resolvers.ts +25 -6
  51. package/src/config/config.ts +51 -27
  52. package/src/config/load.ts +11 -4
  53. package/src/config/rules.ts +2 -2
  54. package/src/config/types.ts +17 -4
  55. package/src/index.ts +10 -2
  56. package/src/lint.ts +13 -22
  57. package/src/oas-types.ts +59 -21
  58. package/src/rules/async2/__tests__/channels-kebab-case.test.ts +141 -0
  59. package/src/rules/async2/__tests__/no-channel-trailing-slash.test.ts +97 -0
  60. package/src/rules/async2/channels-kebab-case.ts +18 -0
  61. package/src/rules/async2/index.ts +22 -0
  62. package/src/rules/async2/no-channel-trailing-slash.ts +15 -0
  63. package/src/rules/common/assertions/asserts.ts +16 -4
  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/oas2/index.ts +2 -2
  67. package/src/rules/oas3/__tests__/no-server-example.com.test.ts +36 -1
  68. package/src/rules/oas3/__tests__/spec/spec.test.ts +1 -1
  69. package/src/rules/oas3/index.ts +2 -2
  70. package/src/rules/oas3/no-server-example.com.ts +3 -2
  71. package/src/types/asyncapi.ts +1142 -0
  72. package/src/types/oas3_1.ts +7 -1
  73. package/src/types/redocly-yaml.ts +3 -0
  74. package/src/typings/asyncapi.ts +26 -0
  75. package/src/visitors.ts +22 -0
  76. package/src/walk.ts +3 -3
  77. package/tsconfig.tsbuildinfo +1 -1
@@ -135,7 +135,14 @@ const Schema = {
135
135
  maxContains: { type: 'integer', minimum: 0 },
136
136
  patternProperties: { type: 'object' },
137
137
  propertyNames: 'Schema',
138
- unevaluatedItems: 'Schema',
138
+ unevaluatedItems: (value) => {
139
+ if (typeof value === 'boolean') {
140
+ return { type: 'boolean' };
141
+ }
142
+ else {
143
+ return 'Schema';
144
+ }
145
+ },
139
146
  unevaluatedProperties: (value) => {
140
147
  if (typeof value === 'boolean') {
141
148
  return { type: 'boolean' };
@@ -61,6 +61,8 @@ const builtInRulesList = [
61
61
  'required-string-property-missing-min-length',
62
62
  'spec-strict-refs',
63
63
  'component-name-unique',
64
+ 'channels-kebab-case',
65
+ 'no-channel-trailing-slash',
64
66
  ];
65
67
  const nodeTypesList = [
66
68
  'any',
@@ -122,6 +124,7 @@ const nodeTypesList = [
122
124
  'XCodeSampleList',
123
125
  'WebhooksMap',
124
126
  'SpecExtension',
127
+ 'Message',
125
128
  ];
126
129
  const ConfigStyleguide = {
127
130
  properties: {
@@ -0,0 +1,21 @@
1
+ export interface Async2Definition {
2
+ asyncapi: string;
3
+ info?: Async2Info;
4
+ }
5
+ export interface Async2Info {
6
+ title: string;
7
+ version: string;
8
+ description?: string;
9
+ termsOfService?: string;
10
+ contact?: Async2Contact;
11
+ license?: Async2License;
12
+ }
13
+ export interface Async2Contact {
14
+ name?: string;
15
+ url?: string;
16
+ email?: string;
17
+ }
18
+ export interface Async2License {
19
+ name: string;
20
+ url?: string;
21
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/lib/visitors.d.ts CHANGED
@@ -4,6 +4,7 @@ import { NormalizedNodeType } from './types';
4
4
  import type { Stack } from './utils';
5
5
  import type { UserContext, ResolveResult, ProblemSeverity } from './walk';
6
6
  import type { Location } from './ref-utils';
7
+ import { Async2Definition } from './typings/asyncapi';
7
8
  export declare type SkipFunctionContext = Pick<UserContext, 'location' | 'rawNode' | 'resolve' | 'rawLocation'>;
8
9
  export declare type VisitFunction<T> = (node: T, ctx: UserContext & {
9
10
  ignoreNextVisitorsOnNode: () => void;
@@ -134,16 +135,24 @@ declare type Oas2FlatVisitor = {
134
135
  SecurityScheme?: VisitFunctionOrObject<Oas2SecurityScheme>;
135
136
  SpecExtension?: VisitFunctionOrObject<unknown>;
136
137
  };
138
+ declare type Async2FlatVisitor = {
139
+ Root?: VisitFunctionOrObject<Async2Definition>;
140
+ };
137
141
  declare type Oas3NestedVisitor = {
138
142
  [T in keyof Oas3FlatVisitor]: Oas3FlatVisitor[T] extends Function ? Oas3FlatVisitor[T] : Oas3FlatVisitor[T] & NestedVisitor<Oas3NestedVisitor>;
139
143
  };
140
144
  declare type Oas2NestedVisitor = {
141
145
  [T in keyof Oas2FlatVisitor]: Oas2FlatVisitor[T] extends Function ? Oas2FlatVisitor[T] : Oas2FlatVisitor[T] & NestedVisitor<Oas2NestedVisitor>;
142
146
  };
147
+ declare type Async2NestedVisitor = {
148
+ [T in keyof Async2FlatVisitor]: Async2FlatVisitor[T] extends Function ? Async2FlatVisitor[T] : Async2FlatVisitor[T] & NestedVisitor<Async2NestedVisitor>;
149
+ };
143
150
  export declare type Oas3Visitor = BaseVisitor & Oas3NestedVisitor & Record<string, VisitFunction<any> | NestedVisitObject<any, Oas3NestedVisitor>>;
144
151
  export declare type Oas2Visitor = BaseVisitor & Oas2NestedVisitor & Record<string, VisitFunction<any> | NestedVisitObject<any, Oas2NestedVisitor>>;
152
+ export declare type Async2Visitor = BaseVisitor & Async2NestedVisitor & Record<string, VisitFunction<any> | NestedVisitObject<any, Async2NestedVisitor>>;
145
153
  export declare type Oas3TransformVisitor = BaseVisitor & Oas3FlatVisitor & Record<string, VisitFunction<any> | VisitObject<any>>;
146
154
  export declare type Oas2TransformVisitor = BaseVisitor & Oas2FlatVisitor & Record<string, VisitFunction<any> | VisitObject<any>>;
155
+ export declare type Async2TransformVisitor = BaseVisitor & Async2FlatVisitor & Record<string, VisitFunction<any> | VisitObject<any>>;
147
156
  export declare type NestedVisitor<T> = Exclude<T, 'any' | 'ref' | 'Root'>;
148
157
  export declare type NormalizedOasVisitors<T extends BaseVisitor> = {
149
158
  [V in keyof T]-?: {
@@ -162,10 +171,13 @@ export declare type NormalizedOasVisitors<T extends BaseVisitor> = {
162
171
  };
163
172
  export declare type Oas3Rule = (options: Record<string, any>) => Oas3Visitor | Oas3Visitor[];
164
173
  export declare type Oas2Rule = (options: Record<string, any>) => Oas2Visitor | Oas2Visitor[];
174
+ export declare type Async2Rule = (options: Record<string, any>) => Async2Visitor | Async2Visitor[];
165
175
  export declare type Oas3Preprocessor = (options: Record<string, any>) => Oas3TransformVisitor;
166
176
  export declare type Oas2Preprocessor = (options: Record<string, any>) => Oas2TransformVisitor;
177
+ export declare type Async2Preprocessor = (options: Record<string, any>) => Async2TransformVisitor;
167
178
  export declare type Oas3Decorator = (options: Record<string, any>) => Oas3TransformVisitor;
168
179
  export declare type Oas2Decorator = (options: Record<string, any>) => Oas2TransformVisitor;
180
+ export declare type Async2Decorator = (options: Record<string, any>) => Async2TransformVisitor;
169
181
  export declare type OasRule = Oas3Rule;
170
182
  export declare type OasPreprocessor = Oas3Preprocessor;
171
183
  export declare type OasDecorator = Oas3Decorator;
package/lib/walk.d.ts CHANGED
@@ -5,7 +5,7 @@ import type { NormalizedNodeType } from './types';
5
5
  import type { RuleSeverity } from './config';
6
6
  import { Location } from './ref-utils';
7
7
  import { ResolveError, YamlParseError, Source } from './resolve';
8
- import { OasVersion } from './oas-types';
8
+ import { SpecVersion } from './oas-types';
9
9
  declare type NonUndefined = string | number | boolean | symbol | bigint | object | Record<string, any>;
10
10
  export declare type ResolveResult<T extends NonUndefined> = {
11
11
  node: T;
@@ -27,7 +27,7 @@ export declare type UserContext = {
27
27
  type: NormalizedNodeType;
28
28
  key: string | number;
29
29
  parent: any;
30
- oasVersion: OasVersion;
30
+ oasVersion: SpecVersion;
31
31
  getVisitorData: () => Record<string, unknown>;
32
32
  };
33
33
  export declare type Loc = {
@@ -65,7 +65,7 @@ export declare type NormalizedProblem = {
65
65
  };
66
66
  export declare type WalkContext = {
67
67
  problems: NormalizedProblem[];
68
- oasVersion: OasVersion;
68
+ oasVersion: SpecVersion;
69
69
  visitorsData: Record<string, Record<string, unknown>>;
70
70
  refTypes?: Map<string, NormalizedNodeType>;
71
71
  };
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@redocly/openapi-core",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "",
5
5
  "main": "lib/index.js",
6
6
  "engines": {
7
- "node": ">=14.0.0"
7
+ "node": ">=14.19.0",
8
+ "npm": ">=7.0.0"
8
9
  },
9
10
  "engineStrict": true,
10
11
  "license": "MIT",
@@ -26,6 +27,7 @@
26
27
  "Swagger",
27
28
  "OpenAPI linter",
28
29
  "Swagger linter",
30
+ "AsyncAPI linter",
29
31
  "oas"
30
32
  ],
31
33
  "contributors": [
@@ -308,7 +308,7 @@ components:
308
308
 
309
309
  `;
310
310
 
311
- exports[`bundle should not place referened schema inline when component in question is not of type "schemas" 1`] = `
311
+ exports[`bundle should not place referenced schema inline when component in question is not of type "schemas" 1`] = `
312
312
  openapi: 3.0.0
313
313
  paths:
314
314
  /pet:
@@ -1,11 +1,32 @@
1
1
  import outdent from 'outdent';
2
2
  import * as path from 'path';
3
3
 
4
- import { bundleDocument, bundle } from '../bundle';
4
+ import { bundleDocument, bundle, bundleFromString } from '../bundle';
5
5
  import { parseYamlToDocument, yamlSerializer, makeConfig } from '../../__tests__/utils';
6
- import { StyleguideConfig, Config, ResolvedConfig } from '../config';
6
+ import { StyleguideConfig, Config, ResolvedConfig, createConfig, loadConfig } from '../config';
7
7
  import { BaseResolver } from '../resolve';
8
8
 
9
+ const stringDocument = outdent`
10
+ openapi: 3.0.0
11
+ paths:
12
+ /pet:
13
+ get:
14
+ operationId: get
15
+ parameters:
16
+ - $ref: '#/components/parameters/shared_a'
17
+ - name: get_b
18
+ post:
19
+ operationId: post
20
+ parameters:
21
+ - $ref: '#/components/parameters/shared_a'
22
+ components:
23
+ parameters:
24
+ shared_a:
25
+ name: shared-a
26
+ `;
27
+
28
+ const testDocument = parseYamlToDocument(stringDocument, '');
29
+
9
30
  describe('bundle', () => {
10
31
  const fetchMock = jest.fn(() =>
11
32
  Promise.resolve({
@@ -19,28 +40,6 @@ describe('bundle', () => {
19
40
 
20
41
  expect.addSnapshotSerializer(yamlSerializer);
21
42
 
22
- const testDocument = parseYamlToDocument(
23
- outdent`
24
- openapi: 3.0.0
25
- paths:
26
- /pet:
27
- get:
28
- operationId: get
29
- parameters:
30
- - $ref: '#/components/parameters/shared_a'
31
- - name: get_b
32
- post:
33
- operationId: post
34
- parameters:
35
- - $ref: '#/components/parameters/shared_a'
36
- components:
37
- parameters:
38
- shared_a:
39
- name: shared-a
40
- `,
41
- ''
42
- );
43
-
44
43
  it('change nothing with only internal refs', async () => {
45
44
  const { bundle, problems } = await bundleDocument({
46
45
  document: testDocument,
@@ -97,7 +96,7 @@ describe('bundle', () => {
97
96
  expect(res.parsed).toMatchSnapshot();
98
97
  });
99
98
 
100
- it('should not place referened schema inline when component in question is not of type "schemas"', async () => {
99
+ it('should not place referenced schema inline when component in question is not of type "schemas"', async () => {
101
100
  const { bundle: res, problems } = await bundle({
102
101
  config: new Config({} as ResolvedConfig),
103
102
  ref: path.join(__dirname, 'fixtures/refs/external-request-body.yaml'),
@@ -233,4 +232,45 @@ describe('bundle', () => {
233
232
 
234
233
  `);
235
234
  });
235
+
236
+ it('should throw an error when there is no document to bundle', () => {
237
+ const wrapper = () =>
238
+ bundle({
239
+ config: new Config({} as ResolvedConfig),
240
+ });
241
+
242
+ expect(wrapper()).rejects.toThrowError('Document or reference is required.\n');
243
+ });
244
+
245
+ it('should bundle with a doc provided', async () => {
246
+ const {
247
+ bundle: { parsed },
248
+ problems,
249
+ } = await bundle({
250
+ config: await loadConfig({ configPath: path.join(__dirname, 'fixtures/redocly.yaml') }),
251
+ doc: testDocument,
252
+ });
253
+
254
+ const origCopy = JSON.parse(JSON.stringify(testDocument.parsed));
255
+
256
+ expect(problems).toHaveLength(0);
257
+ expect(parsed).toEqual(origCopy);
258
+ });
259
+ });
260
+
261
+ describe('bundleFromString', () => {
262
+ it('should bundle from string using bundleFromString', async () => {
263
+ const {
264
+ bundle: { parsed, ...rest },
265
+ problems,
266
+ } = await bundleFromString({
267
+ config: await createConfig(`
268
+ extends:
269
+ - recommended
270
+ `),
271
+ source: testDocument.source.body,
272
+ });
273
+ expect(problems).toHaveLength(0);
274
+ expect(rest.source.body).toEqual(stringDocument);
275
+ });
236
276
  });
@@ -0,0 +1,10 @@
1
+ openapi: 3.0.0
2
+ info:
3
+ title: Test API
4
+ version: '1.0'
5
+ description: Test
6
+ license: Fail
7
+
8
+ servers:
9
+ - url: http://redocly-example.com
10
+ paths: {}
@@ -0,0 +1,2 @@
1
+ extends:
2
+ - recommended
@@ -1,11 +1,11 @@
1
1
  import * as path from 'path';
2
2
  import { outdent } from 'outdent';
3
3
 
4
- import { lintFromString, lintConfig, lintDocument } from '../lint';
4
+ import { lintFromString, lintConfig, lintDocument, lint } from '../lint';
5
5
  import { BaseResolver } from '../resolve';
6
6
  import { loadConfig } from '../config/load';
7
7
  import { parseYamlToDocument, replaceSourceWithRef, makeConfig } from '../../__tests__/utils';
8
- import { detectOpenAPI } from '../oas-types';
8
+ import { detectSpec } from '../oas-types';
9
9
 
10
10
  describe('lint', () => {
11
11
  it('lintFromString should work', async () => {
@@ -20,7 +20,7 @@ describe('lint', () => {
20
20
  license: Fail
21
21
 
22
22
  servers:
23
- - url: http://example.com
23
+ - url: http://redocly-example.com
24
24
  paths: {}
25
25
  `,
26
26
  config: await loadConfig(),
@@ -46,6 +46,35 @@ describe('lint', () => {
46
46
  `);
47
47
  });
48
48
 
49
+ it('lint should work', async () => {
50
+ const results = await lint({
51
+ ref: path.join(__dirname, 'fixtures/lint/openapi.yaml'),
52
+ config: await loadConfig({
53
+ configPath: path.join(__dirname, 'fixtures/redocly.yaml'),
54
+ }),
55
+ });
56
+
57
+ expect(replaceSourceWithRef(results, path.join(__dirname, 'fixtures/lint/')))
58
+ .toMatchInlineSnapshot(`
59
+ Array [
60
+ Object {
61
+ "from": undefined,
62
+ "location": Array [
63
+ Object {
64
+ "pointer": "#/info/license",
65
+ "reportOnKey": false,
66
+ "source": "openapi.yaml",
67
+ },
68
+ ],
69
+ "message": "Expected type \`License\` (object) but got \`string\`",
70
+ "ruleId": "spec",
71
+ "severity": "error",
72
+ "suggest": Array [],
73
+ },
74
+ ]
75
+ `);
76
+ });
77
+
49
78
  it('lintConfig should work', async () => {
50
79
  const document = parseYamlToDocument(
51
80
  outdent`
@@ -61,12 +90,12 @@ describe('lint', () => {
61
90
  path-http-verbs-order: error
62
91
  boolean-parameter-prefixes: off
63
92
  rule/operation-summary-length:
64
- subject:
93
+ subject:
65
94
  type: Operation
66
95
  property: summary
67
96
  message: Operation summary should start with an active verb
68
97
  assertions:
69
- local/checkWordsCount:
98
+ local/checkWordsCount:
70
99
  min: 3
71
100
  theme:
72
101
  openapi:
@@ -189,8 +218,8 @@ describe('lint', () => {
189
218
  it('lintConfig should work with legacy fields - referenceDocs', async () => {
190
219
  const document = parseYamlToDocument(
191
220
  outdent`
192
- apis:
193
- entry:
221
+ apis:
222
+ entry:
194
223
  root: ./file.yaml
195
224
  rules:
196
225
  operation-2xx-response: warn
@@ -304,11 +333,41 @@ describe('lint', () => {
304
333
  `,
305
334
  ''
306
335
  );
307
- expect(() => detectOpenAPI(testDocument.parsed)).toThrow(
336
+ expect(() => detectSpec(testDocument.parsed)).toThrow(
308
337
  `Invalid OpenAPI version: should be a string but got "number"`
309
338
  );
310
339
  });
311
340
 
341
+ it('detect unsupported OpenAPI version', () => {
342
+ const testDocument = parseYamlToDocument(
343
+ outdent`
344
+ openapi: 1.0.4
345
+ `,
346
+ ''
347
+ );
348
+ expect(() => detectSpec(testDocument.parsed)).toThrow(`Unsupported OpenAPI version: 1.0.4`);
349
+ });
350
+
351
+ it('detect unsupported AsyncAPI version', () => {
352
+ const testDocument = parseYamlToDocument(
353
+ outdent`
354
+ asyncapi: 1.0.4
355
+ `,
356
+ ''
357
+ );
358
+ expect(() => detectSpec(testDocument.parsed)).toThrow(`Unsupported AsyncAPI version: 1.0.4`);
359
+ });
360
+
361
+ it('detect unsupported spec format', () => {
362
+ const testDocument = parseYamlToDocument(
363
+ outdent`
364
+ notapi: 3.1.0
365
+ `,
366
+ ''
367
+ );
368
+ expect(() => detectSpec(testDocument.parsed)).toThrow(`Unsupported specification`);
369
+ });
370
+
312
371
  it("spec rule shouldn't throw an error for named callback", async () => {
313
372
  const document = parseYamlToDocument(
314
373
  outdent`
package/src/bundle.ts CHANGED
@@ -1,12 +1,16 @@
1
1
  import isEqual = require('lodash.isequal');
2
- import { BaseResolver, resolveDocument, Document, ResolvedRefMap, makeRefId } from './resolve';
2
+ import {
3
+ BaseResolver,
4
+ resolveDocument,
5
+ Document,
6
+ ResolvedRefMap,
7
+ makeRefId,
8
+ makeDocumentFromString,
9
+ } from './resolve';
3
10
  import { Oas3Rule, normalizeVisitors, Oas3Visitor, Oas2Visitor } from './visitors';
4
- import { Oas3Types } from './types/oas3';
5
- import { Oas2Types } from './types/oas2';
6
- import { Oas3_1Types } from './types/oas3_1';
7
11
  import { NormalizedNodeType, normalizeTypes, NodeType } from './types';
8
12
  import { WalkContext, walkDocument, UserContext, ResolveResult, NormalizedProblem } from './walk';
9
- import { detectOpenAPI, openAPIMajor, OasMajorVersion } from './oas-types';
13
+ import { detectSpec, getTypes, getMajorSpecVersion, SpecMajorVersion } from './oas-types';
10
14
  import { isAbsoluteUrl, isRef, Location, refBaseName } from './ref-utils';
11
15
  import { initRules } from './config/rules';
12
16
  import { reportUnresolvedRef } from './rules/no-unresolved-refs';
@@ -25,10 +29,7 @@ export enum OasVersion {
25
29
  Version3_0 = 'oas3_0',
26
30
  Version3_1 = 'oas3_1',
27
31
  }
28
-
29
- export async function bundle(opts: {
30
- ref?: string;
31
- doc?: Document;
32
+ export type BundleOptions = {
32
33
  externalRefResolver?: BaseResolver;
33
34
  config: Config;
34
35
  dereference?: boolean;
@@ -36,7 +37,14 @@ export async function bundle(opts: {
36
37
  skipRedoclyRegistryRefs?: boolean;
37
38
  removeUnusedComponents?: boolean;
38
39
  keepUrlRefs?: boolean;
39
- }) {
40
+ };
41
+
42
+ export async function bundle(
43
+ opts: {
44
+ ref?: string;
45
+ doc?: Document;
46
+ } & BundleOptions
47
+ ) {
40
48
  const {
41
49
  ref,
42
50
  doc,
@@ -48,7 +56,7 @@ export async function bundle(opts: {
48
56
  }
49
57
 
50
58
  const document =
51
- doc !== undefined ? doc : await externalRefResolver.resolveDocument(base, ref!, true);
59
+ doc === undefined ? await externalRefResolver.resolveDocument(base, ref!, true) : doc;
52
60
 
53
61
  if (document instanceof Error) {
54
62
  throw document;
@@ -62,6 +70,23 @@ export async function bundle(opts: {
62
70
  });
63
71
  }
64
72
 
73
+ export async function bundleFromString(
74
+ opts: {
75
+ source: string;
76
+ absoluteRef?: string;
77
+ } & BundleOptions
78
+ ) {
79
+ const { source, absoluteRef, externalRefResolver = new BaseResolver(opts.config.resolve) } = opts;
80
+ const document = makeDocumentFromString(source, absoluteRef || '/');
81
+
82
+ return bundleDocument({
83
+ document,
84
+ ...opts,
85
+ externalRefResolver,
86
+ config: opts.config.styleguide,
87
+ });
88
+ }
89
+
65
90
  type BundleContext = WalkContext;
66
91
 
67
92
  export type BundleResult = {
@@ -93,27 +118,20 @@ export async function bundleDocument(opts: {
93
118
  removeUnusedComponents = false,
94
119
  keepUrlRefs = false,
95
120
  } = opts;
96
- const oasVersion = detectOpenAPI(document.parsed);
97
- const oasMajorVersion = openAPIMajor(oasVersion);
98
- const rules = config.getRulesForOasVersion(oasMajorVersion);
121
+ const specVersion = detectSpec(document.parsed);
122
+ const specMajorVersion = getMajorSpecVersion(specVersion);
123
+ const rules = config.getRulesForOasVersion(specMajorVersion);
99
124
  const types = normalizeTypes(
100
- config.extendTypes(
101
- customTypes ?? oasMajorVersion === OasMajorVersion.Version3
102
- ? oasVersion === OasVersion.Version3_1
103
- ? Oas3_1Types
104
- : Oas3Types
105
- : Oas2Types,
106
- oasVersion
107
- ),
125
+ config.extendTypes(customTypes ?? getTypes(specVersion), specVersion),
108
126
  config
109
127
  );
110
128
 
111
- const preprocessors = initRules(rules as any, config, 'preprocessors', oasVersion);
112
- const decorators = initRules(rules as any, config, 'decorators', oasVersion);
129
+ const preprocessors = initRules(rules as any, config, 'preprocessors', specVersion);
130
+ const decorators = initRules(rules as any, config, 'decorators', specVersion);
113
131
 
114
132
  const ctx: BundleContext = {
115
133
  problems: [],
116
- oasVersion: oasVersion,
134
+ oasVersion: specVersion,
117
135
  refTypes: new Map<string, NormalizedNodeType>(),
118
136
  visitorsData: {},
119
137
  };
@@ -123,7 +141,7 @@ export async function bundleDocument(opts: {
123
141
  severity: 'error',
124
142
  ruleId: 'remove-unused-components',
125
143
  visitor:
126
- oasMajorVersion === OasMajorVersion.Version2
144
+ specMajorVersion === SpecMajorVersion.OAS2
127
145
  ? RemoveUnusedComponentsOas2({})
128
146
  : RemoveUnusedComponentsOas3({}),
129
147
  });
@@ -157,7 +175,7 @@ export async function bundleDocument(opts: {
157
175
  severity: 'error',
158
176
  ruleId: 'bundler',
159
177
  visitor: makeBundleVisitor(
160
- oasMajorVersion,
178
+ specMajorVersion,
161
179
  dereference,
162
180
  skipRedoclyRegistryRefs,
163
181
  document,
@@ -188,9 +206,9 @@ export async function bundleDocument(opts: {
188
206
  };
189
207
  }
190
208
 
191
- export function mapTypeToComponent(typeName: string, version: OasMajorVersion) {
209
+ export function mapTypeToComponent(typeName: string, version: SpecMajorVersion) {
192
210
  switch (version) {
193
- case OasMajorVersion.Version3:
211
+ case SpecMajorVersion.OAS3:
194
212
  switch (typeName) {
195
213
  case 'Schema':
196
214
  return 'schemas';
@@ -213,7 +231,7 @@ export function mapTypeToComponent(typeName: string, version: OasMajorVersion) {
213
231
  default:
214
232
  return null;
215
233
  }
216
- case OasMajorVersion.Version2:
234
+ case SpecMajorVersion.OAS2:
217
235
  switch (typeName) {
218
236
  case 'Schema':
219
237
  return 'definitions';
@@ -224,13 +242,22 @@ export function mapTypeToComponent(typeName: string, version: OasMajorVersion) {
224
242
  default:
225
243
  return null;
226
244
  }
245
+ case SpecMajorVersion.Async2:
246
+ switch (typeName) {
247
+ case 'Schema':
248
+ return 'schemas';
249
+ case 'Parameter':
250
+ return 'parameters';
251
+ default:
252
+ return null;
253
+ }
227
254
  }
228
255
  }
229
256
 
230
257
  // function oas3Move
231
258
 
232
259
  function makeBundleVisitor(
233
- version: OasMajorVersion,
260
+ version: SpecMajorVersion,
234
261
  dereference: boolean,
235
262
  skipRedoclyRegistryRefs: boolean,
236
263
  rootDocument: Document,
@@ -282,16 +309,16 @@ function makeBundleVisitor(
282
309
  Root: {
283
310
  enter(root: any, ctx: any) {
284
311
  rootLocation = ctx.location;
285
- if (version === OasMajorVersion.Version3) {
312
+ if (version === SpecMajorVersion.OAS3) {
286
313
  components = root.components = root.components || {};
287
- } else if (version === OasMajorVersion.Version2) {
314
+ } else if (version === SpecMajorVersion.OAS2) {
288
315
  components = root;
289
316
  }
290
317
  },
291
318
  },
292
319
  };
293
320
 
294
- if (version === OasMajorVersion.Version3) {
321
+ if (version === SpecMajorVersion.OAS3) {
295
322
  visitor.DiscriminatorMapping = {
296
323
  leave(mapping: Record<string, string>, ctx: any) {
297
324
  for (const name of Object.keys(mapping)) {
@@ -345,7 +372,7 @@ function makeBundleVisitor(
345
372
  components[componentType] = components[componentType] || {};
346
373
  const name = getComponentName(target, componentType, ctx);
347
374
  components[componentType][name] = target.node;
348
- if (version === OasMajorVersion.Version3) {
375
+ if (version === SpecMajorVersion.OAS3) {
349
376
  return `#/components/${componentType}/${name}`;
350
377
  } else {
351
378
  return `#/${componentType}/${name}`;
@@ -6,6 +6,11 @@ StyleguideConfig {
6
6
  "_usedVersions": Set {},
7
7
  "configFile": undefined,
8
8
  "decorators": Object {
9
+ "async2": Object {
10
+ "oas2": Object {},
11
+ "oas3_0": Object {},
12
+ "oas3_1": Object {},
13
+ },
9
14
  "oas2": Object {
10
15
  "oas2": Object {},
11
16
  "oas3_0": Object {},
@@ -39,6 +44,11 @@ StyleguideConfig {
39
44
  "pluginPaths": Array [],
40
45
  "plugins": Array [],
41
46
  "preprocessors": Object {
47
+ "async2": Object {
48
+ "oas2": Object {},
49
+ "oas3_0": Object {},
50
+ "oas3_1": Object {},
51
+ },
42
52
  "oas2": Object {
43
53
  "oas2": Object {},
44
54
  "oas3_0": Object {},
@@ -97,6 +107,20 @@ StyleguideConfig {
97
107
  },
98
108
  "recommendedFallback": false,
99
109
  "rules": Object {
110
+ "async2": Object {
111
+ "oas2": Object {
112
+ "no-empty-servers": "error",
113
+ "operation-summary": "error",
114
+ },
115
+ "oas3_0": Object {
116
+ "no-empty-servers": "error",
117
+ "operation-summary": "error",
118
+ },
119
+ "oas3_1": Object {
120
+ "no-empty-servers": "error",
121
+ "operation-summary": "error",
122
+ },
123
+ },
100
124
  "oas2": Object {
101
125
  "oas2": Object {
102
126
  "no-empty-servers": "error",