All files / src shaking-orphaned-components.ts

88.46% Statements 23/26
50% Branches 5/10
100% Functions 8/8
95.65% Lines 22/23

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 472x   2x     2x 2x   2x 2x 2x     2x 6x 6x 6x         9x 21x       2x   2x 4x   4x 9x   9x 3x       4x         2x    
import * as R from 'ramda'
import { OpenAPIV3 } from 'openapi-types'
import { OpenapiReferenceParser } from '@opendoc/openapi-reference-parser'
 
 
export function openapiShakingOrphanedComponents(document: Readonly<OpenAPIV3.Document>): OpenAPIV3.Document {
  const dependencies = new OpenapiReferenceParser(document).parse()
 
  const refs = R.unnest(Object.values(dependencies.paths || {})
    .map((pathObj) => R.unnest(Object.values(pathObj || {})
      .map((op) => op.dependencies)),
    ))
 
  const exists = refs
    .map((ref) => ref.match(/#\/components\/(.+?)\/(.+)/))
    .filter((matched): matched is RegExpMatchArray => !!matched)
    .map((matched) => ({
      scopeName: matched[1],
      componentName: matched[2],
    }))
 
  const isExist = (scopeName: string, componentName: string): boolean => exists.some(
    (item) => item.scopeName === scopeName &&
    item.componentName === componentName,
  )
 
  let doc = document
 
  for (const scopeName in document.components) {
    Iif (!document.components[scopeName]) continue
 
    for (const componentName in document.components[scopeName]) {
      Iif (!document.components[scopeName][componentName]) continue
 
      if (!isExist(scopeName, componentName)) {
        doc = R.dissocPath(['components', scopeName, componentName], doc)
      }
    }
 
    Iif (R.isEmpty(R.path(['components', scopeName], doc))) {
      doc = R.dissocPath(['components', scopeName], doc)
    }
  }
 
  return doc
}