From 30a0f3c9eadfbe40f78b52918d1d8ac4e8c36924 Mon Sep 17 00:00:00 2001 From: Viacheslav Turovskyi Date: Fri, 16 Feb 2024 19:11:00 +0000 Subject: [PATCH] feat: add `x-origin` property --- package.json | 1 + src/util.ts | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index d42fa1a..0b0ab62 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "dependencies": { "@apidevtools/json-schema-ref-parser": "^9.1.2", "@types/json-schema": "^7.0.11", + "axios": "^1.6.7", "js-yaml": "^4.1.0", "jsonpath-plus": "^6.0.1", "lodash": "^4.17.21" diff --git a/src/util.ts b/src/util.ts index c0a80ee..dea3e29 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,5 +1,7 @@ +import fs from 'fs'; import $RefParser from '@apidevtools/json-schema-ref-parser'; -import { cloneDeep } from 'lodash'; +import axios from 'axios'; +import { cloneDeep, merge } from 'lodash'; import yaml from 'js-yaml'; import { parse, isExternalReference } from './parser'; import { ParserError } from './errors'; @@ -105,15 +107,45 @@ export function versionCheck(asyncapiDocuments: AsyncAPIObject[]): number { export function addXOrigins(asyncapiDocument: AsyncAPIObject) { // VALUE from 'asyncapiDocument' becomes KEY for the // underlying and recursive functions - Object.values(asyncapiDocument).forEach((key: any) => { + Object.values(asyncapiDocument).forEach(async (key: any) => { if (typeof key === 'object' && key !== '$ref') { if (Object.keys(key).indexOf('$ref') !== -1) { if (isExternalReference(key['$ref'])) { key['x-origin'] = key['$ref']; + + // If an external `$ref` is found, the function goes into + // second-level recursion to see if there are more `$ref`s whose + // values need to be copied to the `x-origin` properties of the + // `$ref`ed file. + // If an external `$ref` is found again, the function goes into the + // third-level recursion, and so on, until it reaches a file that + // contains no external `$ref`s at all. + // Then it exits all the way up in the opposite direction. + + let inlineAsyncapiDocumentURI = key['$ref'].split('#/'); + let inlineAsyncapiDocumentPath = inlineAsyncapiDocumentURI[0]; + let inlineAsyncapiDocumentPointer = inlineAsyncapiDocumentURI[1]; + + let inlineAsyncapiDocument = inlineAsyncapiDocumentPath.startsWith( + 'http' + ) + ? yaml.load(await axios(inlineAsyncapiDocumentPath)) + : (yaml.load( + fs.readFileSync(inlineAsyncapiDocumentPath, 'utf-8') + ) as any); + + inlineAsyncapiDocument = + inlineAsyncapiDocument[inlineAsyncapiDocumentPointer]; + + if (inlineAsyncapiDocument) { + addXOrigins(inlineAsyncapiDocument as AsyncAPIObject); + merge(key, inlineAsyncapiDocument); + } } } else { addXOrigins(key); } } }); + return asyncapiDocument; }