|
1 | 1 | import {OpenAPIV3} from "openapi-types"; |
| 2 | +import * as lodash from "lodash"; |
2 | 3 |
|
3 | 4 | export class RefResolver { |
4 | 5 | constructor(private doc: any) { |
5 | 6 |
|
6 | 7 | } |
7 | 8 |
|
8 | | - resolveRef(ref: string): OpenAPIV3.SchemaObject { |
9 | | - const refPath = ref.split('/').slice(1); |
10 | | - let schema: any = this.doc; |
11 | | - for (const path of refPath) { |
12 | | - // @ts-ignore |
13 | | - schema = schema[path]; |
14 | | - if (!schema) { |
15 | | - throw new Error(`Schema not found for ref '${ref}'`); |
16 | | - } |
17 | | - } |
18 | | - if ('$ref' in schema) { |
19 | | - return this.resolveRef(schema['$ref']); |
20 | | - } |
21 | | - return schema; |
22 | | - } |
23 | | - |
24 | | - resolve<T>(schema: OpenAPIV3.ReferenceObject | T): T { |
| 9 | + /** |
| 10 | + * Resolve ref and return it if found |
| 11 | + * @param schema |
| 12 | + */ |
| 13 | + resolveRef<T>(schema: OpenAPIV3.ReferenceObject | T): [T, string[]?] { |
25 | 14 | // @ts-ignore |
26 | 15 | if ("oneOf" in schema) { |
27 | 16 | // @ts-ignore |
28 | | - return this.resolve(schema.oneOf[0]); |
| 17 | + schema = schema.oneOf[0] |
29 | 18 | } |
30 | 19 | // @ts-ignore |
31 | 20 | if ("anyOf" in schema) { |
32 | 21 | // @ts-ignore |
33 | | - return this.resolve(schema.anyOf[0]); |
| 22 | + schema = schema.anyOf[0] |
34 | 23 | } |
35 | 24 | // @ts-ignore |
36 | 25 | if ("allOf" in schema) { |
37 | 26 | // @ts-ignore |
38 | | - const schemas = schema.allOf.map((s) => this.resolve(s)); |
39 | | - return Object.assign({}, ...schemas) as T; |
| 27 | + const results = schema.allOf.map((s) => this.resolveRef(s)); |
| 28 | + const schemas = results.map((r: any) => r[0]); |
| 29 | + const refs = results.map((r: any) => r[1]); |
| 30 | + const refsFlat = lodash.flatten<string>(refs); |
| 31 | + const object = Object.assign({}, ...schemas); |
| 32 | + return [object as T, refsFlat] |
40 | 33 | } |
41 | 34 | // @ts-ignore |
42 | 35 | if ('$ref' in schema) { |
43 | | - const schemaResolved = this.resolveRef(schema['$ref']); |
| 36 | + const schemaResolved = this.findRef(schema['$ref']); |
44 | 37 | // Remove $ref from schema, add all other properties |
45 | 38 | const {$ref, ...rest} = schema; |
46 | 39 | Object.assign(rest, schemaResolved); |
47 | | - return rest as T |
| 40 | + return [rest as T, [$ref]] |
| 41 | + } |
| 42 | + return [schema as T, undefined] |
| 43 | + } |
| 44 | + |
| 45 | + resolve<T>(schema: OpenAPIV3.ReferenceObject | T): T { |
| 46 | + return this.resolveRef(schema)[0] |
| 47 | + } |
| 48 | + |
| 49 | + private findRef(ref: string): OpenAPIV3.SchemaObject { |
| 50 | + const refPath = ref.split('/').slice(1); |
| 51 | + let schema: any = this.doc; |
| 52 | + for (const path of refPath) { |
| 53 | + // @ts-ignore |
| 54 | + schema = schema[path]; |
| 55 | + if (!schema) { |
| 56 | + throw new Error(`Schema not found for ref '${ref}'`); |
| 57 | + } |
| 58 | + } |
| 59 | + if ('$ref' in schema) { |
| 60 | + return this.findRef(schema['$ref']); |
48 | 61 | } |
49 | | - return schema as T |
| 62 | + return schema; |
50 | 63 | } |
51 | 64 | } |
0 commit comments