qiwi/packasso

View on GitHub
packages/core/src/main/ts/topo.ts

Summary

Maintainability
A
1 hr
Test Coverage
import { existsSync } from 'node:fs'
import { join, relative } from 'node:path'

import { ITopoOptions, topo } from '@semrel-extra/topo'
import { cosmiconfig } from 'cosmiconfig'
import lodash from 'lodash'

import { ExtraPackageEntry, ExtraTopoContext } from './types'

export const getConfig: (cwd: string) => Promise<string[]> = async (cwd) => {
  const result = await cosmiconfig('packasso').search(cwd)
  return lodash.uniqWith([result?.config || []].flat(), lodash.isEqual)
}

export const getTopo: (
  options?: ITopoOptions,
  preset?: string,
) => Promise<ExtraTopoContext> = async (options, preset) => {
  const context = await topo(options)
  const packages = Object.fromEntries(
    await Promise.all(
      Object.entries(context.packages).map<
        Promise<[string, ExtraPackageEntry]>
      >(async ([name, pkg]) => [
        name,
        {
          ...pkg,
          leaf: true,
          unit: false,
          tree: false,
          modules: await getConfig(pkg.absPath),
        },
      ]),
    ),
  )
  const root = {
    ...context.root,
    relPath: '.',
    leaf: false,
    unit: !context.root.manifest.workspaces,
    tree: !!context.root.manifest.workspaces,
    modules: lodash.uniqWith(
      [
        ...Object.values(packages).flatMap(({ modules }) => modules),
        ...(await getConfig(context.root.absPath)),
      ],
      lodash.isEqual,
    ),
  }
  return {
    ...context,
    packages,
    queuePackages: context.queue
      .map((name) => packages[name])
      .filter((pkg) => (preset ? pkg.modules.includes(preset) : true)),
    root,
  }
}

export const getDependencies: (
  pkg: ExtraPackageEntry,
  topo: ExtraTopoContext,
  file?: string,
) => [string, string][] = (pkg, topo, file) =>
  (pkg.tree
    ? Object.values(topo.packages || {})
    : Object.entries({
        ...pkg.manifest.dependencies,
        ...pkg.manifest.devDependencies,
        ...pkg.manifest.optionalDependencies,
        ...pkg.manifest.peerDependencies,
      })
        .filter(([name, version]) => name && version.startsWith('workspace:'))
        .map(([name]) => topo.packages[name])
  )
    .filter(({ absPath }) => !file || existsSync(join(absPath, file)))
    .map(({ name, absPath }) => [name, relative(pkg.absPath, absPath)])