Skip to content

Commit bd3ad86

Browse files
committed
feat: Refactoring
1 parent 225d22a commit bd3ad86

File tree

3 files changed

+41
-22
lines changed

3 files changed

+41
-22
lines changed

src/apitypes/rest/rest.operation.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
isOperationDeprecated,
3737
normalizePath,
3838
rawToApiKind,
39+
resolveRefAndMap,
3940
setValueByPath,
4041
takeIf,
4142
takeIfDefined,
@@ -213,7 +214,7 @@ export const calculateSpecRefs = (sourceDocument: unknown, normalizedSpec: unkno
213214
}
214215
//todo why? description?
215216
const componentName = matchResult.grepValues[grepKey].toString()
216-
const sourceComponents = getKeyValue(sourceDocument, ...matchResult.path)
217+
let sourceComponents = getKeyValue(sourceDocument, ...matchResult.path)
217218
const resultComponents = getKeyValue(resultSpec, ...matchResult.path)
218219
const httpMethods = new Set<string>(Object.values(OpenAPIV3.HttpMethods) as string[])
219220
const allowedOps = (typeof resultComponents === 'object' && resultComponents !== null)
@@ -223,6 +224,7 @@ export const calculateSpecRefs = (sourceDocument: unknown, normalizedSpec: unkno
223224
return
224225
}
225226
if (allowedOps.length > 0) {
227+
sourceComponents = { ...sourceComponents }
226228
Object.keys(sourceComponents as object).forEach((key: string) => {
227229
if (httpMethods.has(key) && !allowedOps.includes(key)) {
228230
// prune operations not present in the partial result component
@@ -238,6 +240,8 @@ export const calculateSpecRefs = (sourceDocument: unknown, normalizedSpec: unkno
238240
if (componentHash) {
239241
models[componentName] = componentHash
240242
} else {
243+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
244+
// @ts-ignore
241245
componentHash = calculateObjectHash(sourceComponents)
242246
componentsHashMap?.set(componentName, componentHash)
243247
models[componentName] = componentHash
@@ -274,8 +278,12 @@ const createSingleOperationSpec = (
274278
): TYPE.RestOperationData => {
275279
const pathData = document.paths[path] as OpenAPIV3.PathItemObject
276280

277-
if (INLINE_REFS_FLAG in pathData || (pathData && '$ref' in pathData && pathData.$ref)) {
278-
//todo check
281+
const ref = pathData?.$ref
282+
if (pathData && ref) {
283+
const cleanedDocument = resolveRefAndMap(document, ref, (pathItemObject: OpenAPIV3.PathItemObject) => ({
284+
...extractCommonPathItemProperties(pathItemObject),
285+
[method]: { ...pathItemObject[method] },
286+
}))
279287
return {
280288
openapi: openapi ?? '3.0.0',
281289
...takeIfDefined({ servers }),
@@ -285,6 +293,7 @@ const createSingleOperationSpec = (
285293
},
286294
components: {
287295
...takeIfDefined({ securitySchemes }),
296+
...cleanedDocument?.components ?? {},
288297
},
289298
}
290299
}

src/strategies/document-group.strategy.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,17 +154,19 @@ function transformDocumentData(versionDocument: VersionDocument): OpenAPIV3.Docu
154154
const pathData = sourceDocument.paths[path]!
155155
if (pathItemRef) {
156156
const targetFromResultDocument = getParentValueByRef(resultDocument, pathData.$ref ?? '')
157-
const target = resolveRefAndMap(sourceDocument, pathData.$ref ?? '', (value) => ({
157+
const target = resolveRefAndMap(sourceDocument, pathData.$ref ?? '', (pathItemObject: OpenAPIV3.PathItemObject) => ({
158158
...targetFromResultDocument,
159-
...extractCommonPathItemProperties(value),
160-
[method]: { ...value[method] },
159+
...extractCommonPathItemProperties(pathItemObject),
160+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
161+
// @ts-ignore
162+
[method]: { ...pathItemObject[method] },
161163
}))
162164

163165
resultDocument.paths[path] = pathData
164166

165167
resultDocument.components = {
166168
...takeIfDefined({ securitySchemes: sourceComponents?.securitySchemes }),
167-
...target.components,
169+
...target.components ?? {},
168170
}
169171
} else {
170172
const existingPath = resultDocument.paths[path]

src/utils/builder.ts

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import { API_KIND } from '../consts'
3030
import { Diff, DiffType } from '@netcracker/qubership-apihub-api-diff'
3131
import { JsonPath } from '@netcracker/qubership-apihub-json-crawl'
3232
import { parseRef } from '@netcracker/qubership-apihub-api-unifier'
33+
import { OpenAPIV3 } from 'openapi-types'
3334

3435
export type ObjPath = (string | number)[]
3536

@@ -217,44 +218,51 @@ export const getParentValueByRef = (obj: any, ref: string): any => {
217218
}
218219

219220
export const resolveRefAndMap = (
220-
obj: any,
221+
document: OpenAPIV3.Document,
221222
ref: string,
222-
valueMapper: (target: any) => any,
223-
component: any = {},
224-
): any => {
225-
const visited = new Set<string>()
223+
valueMapper: (target: Record<string, unknown>) => Record<string, unknown>,
224+
result: Record<string, unknown> = {},
225+
): Record<string, unknown> => {
226+
const cyclingGuard = new Set<string>()
226227
let currentRef: string | undefined = ref
227228
let lastPath: JsonPath = []
228229

229230
while (currentRef) {
230-
if (visited.has(currentRef)) {
231-
// circular reference guard
231+
if (cyclingGuard.has(currentRef)) {
232232
break
233233
}
234-
visited.add(currentRef)
234+
cyclingGuard.add(currentRef)
235235

236236
const { jsonPath } = parseRef(currentRef)
237237
lastPath = jsonPath
238-
const value = getValueByJsonPath(obj, jsonPath)
238+
239+
const rawValue = getValueByJsonPath(document, jsonPath)
240+
if (rawValue === null) {
241+
break
242+
}
243+
244+
const value = { ...rawValue }
239245

240246
if (isRecordObject(value) && typeof value.$ref === 'string') {
241247
// preserve intermediate referenced node
242-
setValueByPath(component, jsonPath, value)
248+
setValueByPath(result, jsonPath, value)
243249
currentRef = value.$ref
244250
continue
245251
}
246252

247253
// terminal value reached; apply mapper
248-
setValueByPath(component, jsonPath, valueMapper(value))
249-
return component
254+
setValueByPath(result, jsonPath, valueMapper(value))
255+
return result
250256
}
251257

252258
// Fallback when loop breaks due to cycle or missing ref
253259
if (lastPath.length) {
254-
const terminal = getValueByJsonPath(obj, lastPath)
255-
setValueByPath(component, lastPath, valueMapper(terminal))
260+
const terminal = getValueByJsonPath(document, lastPath)
261+
if (terminal !== undefined) {
262+
setValueByPath(result, lastPath, valueMapper(terminal))
263+
}
256264
}
257-
return component
265+
return result
258266
}
259267

260268
export const rawToApiKind = (apiKindLike: string): ApiKind => {

0 commit comments

Comments
 (0)