const fs = require('fs')
const { promisify } = require('util')

const cache = {}
const readFile = path => cache[path] = cache[path] || JSON.parse(fs.readFileSync(path))
const readDir = promisify(fs.readdir)
const DEPS_FIELDS = ['dependencies', 'devDependencies', 'optionalDependencies', 'peerDependencies']


function isDependency(path, anotherPath) {
  const details = readFile(`${path}/package.json`)
  const anotherDetails = readFile(`${anotherPath}/package.json`)

  return DEPS_FIELDS.some(field => anotherDetails[field] && anotherDetails[field][details.name])
}

async function resolve(folder) {
  const items = await readDir(folder)
  const packagesPath = items.filter(path => fs.lstatSync(`${folder}/${path}`).isDirectory())
  const copy = packagesPath.slice(0)
  const result = []
  const insert = (path) => {
    packagesPath
      .filter((anotherPath) => {
        return isDependency(`${folder}/${anotherPath}`, `${folder}/${path}`)
      })
      .forEach(insert)

    if (!result.includes(path)) {
      result.push(path)
      const index = copy.indexOf(path)
      index !== -1 && copy.splice(index, 1)
    }
  }

  let path
  while (path = copy.pop()) {
    insert(path)
  }

  return result
}

resolve('../packages')
  .then(items => console.log(items))
  .catch(console.error)