UNPKG

@opendoc/openapi-reference-parser

Version:

Get the dependencies of reference in openapi.

1 lines 11.6 kB
{"version":3,"sources":["../src/parser.ts","../src/utils/is-object.ts","../src/reference.ts"],"sourcesContent":["import * as R from 'ramda'\nimport { OpenAPIV3, OpenAPIV3_1 } from '@scalar/openapi-types'\nimport { ReferenceStorage } from './types/reference-storage'\nimport { isObject } from './utils/is-object'\nimport { JSONPath } from 'jsonpath-plus'\nimport { Reference } from './reference'\nimport { OpenapiReferenceParserResult } from './types/openapi-reference-parser-result'\nimport { OpenapiReferenceParserOptions } from './types/openapi-reference-parser-options'\n\n\nexport class OpenapiReferenceParser {\n private directDependenciesStorage: ReferenceStorage<Reference[]> = {}\n private transitiveDependenciesStorage: ReferenceStorage<Reference[]> = {}\n private dependenciesStorage: ReferenceStorage<Reference[]> = {}\n\n constructor(\n private document: OpenAPIV3.Document | OpenAPIV3_1.Document,\n private options: OpenapiReferenceParserOptions = {},\n ) {}\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private forEach(fn: (ref: Reference, item: any) => void): void {\n for (const [pathname, pathItem] of Object.entries(this.document.paths || {})) {\n if (!isObject(this.document.paths)) continue\n\n for (const m in pathItem) {\n const method = m.toLowerCase() as OpenAPIV3.HttpMethods\n\n const operation = pathItem[method]\n if (R.isNil(operation)) continue\n fn(Reference.from(['paths', pathname, method]), operation)\n }\n }\n\n for (const [scopeName, scope] of Object.entries(this.document.components || {})) {\n if (!isObject(this.document.components)) continue\n\n for (const [componentName, component] of Object.entries(scope)) {\n if (R.isNil(component)) continue\n fn(Reference.from(['components', scopeName, componentName]), component)\n }\n }\n }\n\n private pickRefs(json: object): Reference[] {\n const arr = JSONPath({\n path: \"$..*['$ref']\",\n json,\n })\n\n return arr.map((ref: string) => Reference.from(ref))\n }\n\n private buildDirectDependenciesStorage(): void {\n this.forEach((ref, item) => {\n const refs = this.pickRefs(item)\n .filter((r) => !r.equals(ref))\n\n ref.set(this.directDependenciesStorage, R.uniqWith((a, b) => a.equals(b), refs))\n })\n }\n\n private buildTransitiveDependenciesStorage(): void {\n this.forEach((ref) => {\n const directDependencies = ref.get(this.directDependenciesStorage)\n if (!directDependencies) return\n\n const transitiveDependencies: Reference[] = []\n const dependencies = [...directDependencies]\n const isDuplicate = (r: Reference): boolean => ref.equals(r) || dependencies.some((d) => d.equals(r))\n const appendToDependencies = (refs: Reference[]): void => {\n for (const r of refs) {\n if (isDuplicate(r)) continue\n dependencies.push(r)\n transitiveDependencies.push(r)\n }\n }\n\n for (let i = 0; i < dependencies.length; i++) {\n try {\n const dep = dependencies[i]\n const depDirectDependencies = dep.get(this.directDependenciesStorage)\n const depTransitiveDependencies = dep.get(this.transitiveDependenciesStorage)\n\n if (depTransitiveDependencies) appendToDependencies(depTransitiveDependencies)\n else if (depDirectDependencies) appendToDependencies(depDirectDependencies)\n } catch (err) {\n if (!this.options.tolerant) throw err\n }\n }\n\n ref.set(this.transitiveDependenciesStorage, transitiveDependencies)\n ref.set(this.dependenciesStorage, dependencies)\n })\n }\n\n parse(): OpenapiReferenceParserResult {\n this.buildDirectDependenciesStorage()\n this.buildTransitiveDependenciesStorage()\n\n const result: OpenapiReferenceParserResult = {}\n this.forEach((ref) => {\n const dependencies = ref.get(this.dependenciesStorage)\n const transitiveDependencies = ref.get(this.transitiveDependenciesStorage)\n const directDependencies = ref.get(this.directDependenciesStorage)\n\n if (!dependencies || !transitiveDependencies || !directDependencies) return\n\n ref.set(\n result,\n {\n dependencies: dependencies.map((r) => r.toString()),\n transitiveDependencies: transitiveDependencies.map((r) => r.toString()),\n directDependencies: directDependencies.map((r) => r.toString()),\n },\n )\n })\n\n return result\n }\n}\n","// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function isObject(value: unknown): value is Exclude<object, null | Array<any>> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n}\n","import * as R from 'ramda'\nimport { ReferenceStorage } from './types/reference-storage'\nimport * as ObjectPath from 'object-path'\n\n\nexport abstract class Reference {\n static from($ref: string | string[]): Reference {\n if (typeof $ref === 'string') {\n if ($ref.startsWith('#')) return new LocalReference($ref.split('/').slice(1))\n return new ExternalFileReference($ref)\n }\n\n return new LocalReference($ref)\n }\n\n abstract toString(): string\n abstract set<T>(storage: ReferenceStorage<T>, value: T): void\n abstract get<T>(storage: ReferenceStorage<T>): T | undefined\n abstract equals(ref: Reference): boolean\n}\n\n/**\n * Represents a reference to a location within the same document.\n */\nexport class LocalReference extends Reference {\n constructor(private paths: string[]) {\n super()\n }\n\n // resolve<T>(object: object): T | undefined {\n // return R.pathOr(undefined, this.paths, object)\n // }\n\n toString(): string {\n return `#/${this.paths.join('/')}`\n }\n\n set<T>(storage: ReferenceStorage<T>, value: T): void {\n ObjectPath.set(storage, this.paths, value)\n }\n\n get<T>(storage: ReferenceStorage<T>): T | undefined {\n return R.path(this.paths, storage)\n }\n\n equals(ref: Reference): boolean {\n if (!(ref instanceof LocalReference)) return false\n return R.equals(this.paths, ref.paths)\n }\n}\n\n/**\n * Represents a reference to a location within a remote document.\n */\nexport class RemoteReference extends Reference {\n constructor(private address: string) {\n super()\n }\n\n // async resolve<T>(): Promise<T | undefined> {\n // throw new Error('Not implemented')\n // }\n\n toString(): string {\n return this.address\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n set<T>(storage: ReferenceStorage<T>, value: T): void {\n throw new Error(`RemoteReference(${this.address}) is not supported`)\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n get<T>(storage: ReferenceStorage<T>): T | undefined {\n throw new Error(`RemoteReference(${this.address}) is not supported`)\n }\n\n equals(ref: Reference): boolean {\n if (!(ref instanceof RemoteReference)) return false\n return this.address === ref.address\n }\n}\n\nexport class ExternalFileReference extends Reference {\n constructor(private address: string) {\n super()\n }\n\n async resolve<T>(): Promise<T | undefined> {\n throw new Error('Not implemented')\n }\n\n toString(): string {\n return this.address\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n set<T>(storage: ReferenceStorage<T>, value: T): void {\n throw new Error(`ExternalFileReference(${this.address}) is not supported`)\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n get<T>(storage: ReferenceStorage<T>): T | undefined {\n throw new Error(`ExternalFileReference(${this.address}) is not supported`)\n }\n\n equals(ref: Reference): boolean {\n if (!(ref instanceof ExternalFileReference)) return false\n return this.address === ref.address\n }\n}\n"],"mappings":"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","names":["R"]}