Skip to content

Commit

Permalink
feat(open-api): add basic $ref resolution support for openapi documents
Browse files Browse the repository at this point in the history
adds support to resolve $ref references to paths within the document

INT-407
  • Loading branch information
FreekVR committed Apr 5, 2024
1 parent d22e659 commit 59e9e6d
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 5 deletions.
36 changes: 33 additions & 3 deletions src/.vuepress/theme/client/components/global/OpenApi.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<template>
<section class="open-api">
<OpenApiInfo :info="document.info" />
<OpenApiInfo :info="resolvedDocument.info" />

<article
v-for="(item, path) in document.paths"
v-for="(item, path) in resolvedDocument.paths"
:key="path">
<OpenApiPath
v-if="item"
Expand All @@ -14,11 +14,41 @@
</template>

<script setup lang="ts">
import {computed} from 'vue';
import {type OpenAPIV3_1 as OpenApiType} from 'openapi-types';
import {get} from 'lodash-es';
import OpenApiPath from './OpenApiPath.vue';
import OpenApiInfo from './OpenApiInfo.vue';
defineProps<{
const props = defineProps<{
document: OpenApiType.Document;
}>();
const resolvedDocument = computed(() => resolveRefs(props.document));
// Recursively loop through the entire document and replace any $ref keys with their corresponding values
function resolveRefs(document: OpenApiType.Document): OpenApiType.Document {
const resolvedDocument = {...document};
function resolveRefsRecursive(obj: object | (string | number | object)[]) {
for (const key in obj) {
if (key === '$ref') {
const lookup = (obj as {$ref: string})[key];
// Lookup is a string that defines the path to the referenced object like '#/components/schemas/Example'
const path = lookup.split('/').slice(1);
// Find the referenced object in the document using lodash's get function
const referencedObject = get(resolvedDocument, path);
// Remove the $ref: '...' key from the object and replace it with the referenced object itself
obj = Object.assign(obj, referencedObject);
} else if (typeof obj[key] === 'object' || Array.isArray(obj[key])) {
// If the value is an object or an array, recursively call this function
resolveRefsRecursive(obj[key]);
}
}
}
resolveRefsRecursive(resolvedDocument);
return resolvedDocument;
}
</script>
13 changes: 11 additions & 2 deletions src/.vuepress/theme/client/components/global/OpenApiResponses.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,19 @@ const responseObjects: ComputedRef<Record<string, OpenApiType.ResponseObject>> =
// Maps the response content to a CodeGroupItem array.
const mapToCodegroup = (content: Record<string, OpenApiType.MediaTypeObject>) => {
return Object.entries(content).map(([responseType, item]) => {
// @TODO support component references here, too
let code = {};
if (item.schema) {
code = item.schema;
} else if (item.example) {
code = item.example;
} else if (item.examples) {
code = item.examples;
}
return {
title: responseType,
code: item.examples ?? item.examples ?? item.example,
code,
language: responseType,
};
});
Expand Down

0 comments on commit 59e9e6d

Please sign in to comment.