Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 3x 3x 3x 3x 3x 3x 3x 3x 6x 6x 9x 9x 4x 5x 1x 4x 5x 4x 1x 4x 4x 4x 4x 4x 4x 4x 1x 1x 1x 4x 4x 4x 4x 4x 4x 4x 4x 1x 1x 1x 1x 4x 4x 4x 4x 4x 4x 1x 3x 1x | import * as R from 'ramda'
import { OpenAPIV3 } from 'openapi-types'
import { ReferenceStorage } from './types/reference-storage'
import { isObject } from './utils/is-object'
import { JSONPath } from 'jsonpath-plus'
import { Reference } from './reference'
import { OpenapiReferenceParserResult } from './types/openapi-reference-parser-result'
export class OpenapiReferenceParser {
private directDependenciesStorage: ReferenceStorage<Reference[]> = {}
private transitiveDependenciesStorage: ReferenceStorage<Reference[]> = {}
private dependenciesStorage: ReferenceStorage<Reference[]> = {}
constructor(
private document: OpenAPIV3.Document,
) {}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private forEach(fn: (ref: Reference, item: any) => void): void {
for (const [pathname, pathItem] of Object.entries(this.document.paths || {})) {
Iif (!isObject(this.document.paths)) continue
for (const m in pathItem) {
const method = m.toLowerCase() as OpenAPIV3.HttpMethods
const operation = pathItem[method]
Iif (R.isNil(operation)) continue
fn(Reference.from(['paths', pathname, method]), operation)
}
}
for (const [scopeName, scope] of Object.entries(this.document.components || {})) {
Iif (!isObject(this.document.components)) continue
for (const [componentName, component] of Object.entries(scope)) {
Iif (R.isNil(component)) continue
fn(Reference.from(['components', scopeName, componentName]), component)
}
}
}
private pickRefs(json: object): Reference[] {
const arr = JSONPath({
path: "$..*['$ref']",
json,
})
return arr.map((ref: string) => Reference.from(ref))
}
private buildDirectDependenciesStorage(): void {
this.forEach((ref, item) => {
const refs = this.pickRefs(item)
.filter((r) => !r.equals(ref))
ref.set(this.directDependenciesStorage, R.uniqWith((a, b) => a.equals(b), refs))
})
}
private buildTransitiveDependenciesStorage(): void {
this.forEach((ref) => {
const directDependencies = ref.get(this.directDependenciesStorage)
Iif (!directDependencies) return
const transitiveDependencies: Reference[] = []
const dependencies = [...directDependencies]
const isDuplicate = (r: Reference): boolean => ref.equals(r) || dependencies.some((d) => d.equals(r))
const appendToDependencies = (refs: Reference[]): void => {
for (const r of refs) {
Iif (isDuplicate(r)) continue
dependencies.push(r)
transitiveDependencies.push(r)
}
}
for (let i = 0; i < dependencies.length; i++) {
const dep = dependencies[i]
const depDirectDependencies = dep.get(this.directDependenciesStorage)
const depTransitiveDependencies = dep.get(this.transitiveDependenciesStorage)
Iif (depTransitiveDependencies) appendToDependencies(depTransitiveDependencies)
else if (depDirectDependencies) appendToDependencies(depDirectDependencies)
}
ref.set(this.transitiveDependenciesStorage, transitiveDependencies)
ref.set(this.dependenciesStorage, dependencies)
})
}
parse(): OpenapiReferenceParserResult {
this.buildDirectDependenciesStorage()
this.buildTransitiveDependenciesStorage()
const result: OpenapiReferenceParserResult = {}
this.forEach((ref) => {
const dependencies = ref.get(this.dependenciesStorage)
const transitiveDependencies = ref.get(this.transitiveDependenciesStorage)
const directDependencies = ref.get(this.directDependenciesStorage)
Iif (!dependencies || !transitiveDependencies || !directDependencies) return
ref.set(
result,
{
dependencies: dependencies.map((r) => r.toString()),
transitiveDependencies: transitiveDependencies.map((r) => r.toString()),
directDependencies: directDependencies.map((r) => r.toString()),
},
)
})
return result
}
}
|