@hyperfrontend/versioning/workspace/discovery

discovery

Monorepo discovery: finds packages, locates their changelogs, and builds the internal-dependency graph.

The package-discovery half (DiscoveryOptions, DiscoveryResult) walks the workspace looking for package.json files and produces a normalized list of projects. The changelog half (hasChangelog, getExpectedChangelogPath, DiscoveredChangelog) reports which packages have a CHANGELOG.md and where it's expected to live. The dependency-graph half (findInternalDependencies, findInternalDependenciesWithTypes, buildDependencyGraph, getTopologicalOrder, getTransitiveDependents) computes the per-package dependency edges (DependencyEdge, DependencyType) and the topological order needed to drive cascade bumps and batch updates safely.

API Reference§

ƒ Functions

§function

buildDependencyGraph(projects: unknown): DependencyGraphAnalysis

Builds a complete dependency graph from a list of projects.
Parameters
NameTypeDescription
§projects
unknownList of projects to analyze
Returns
DependencyGraphAnalysis
Dependency graph analysis result
Example

Build a complete dependency graph

import { buildDependencyGraph, discoverPackages } from '@hyperfrontend/versioning'

const { projects } = discoverPackages()
const analysis = buildDependencyGraph(projects)

// Get packages that depend on 'lib-utils'
const dependents = analysis.dependencyGraph.get('lib-utils') ?? []

// Get packages in topological order for building
const buildOrder = getTopologicalOrder(analysis)
§function

discoverAllChangelogs(workspaceRoot: string, patterns: unknown): unknown

Discovers all changelog files within a workspace.
Parameters
NameTypeDescription
§workspaceRoot
stringWorkspace root path
§patterns
unknownGlob patterns for finding changelogs (default: all CHANGELOGs)(default: ...)
Returns
unknown
Array of discovered changelog information
Example

Discover all changelog files within a workspace

import { discoverAllChangelogs } from '@hyperfrontend/versioning'

const changelogs = discoverAllChangelogs('/path/to/workspace')
for (const changelog of changelogs) {
  console.log(`${changelog.projectPath} -> ${changelog.path}`)
}
§function

discoverPackages(options: DiscoveryOptions): DiscoveryResult

Discovers all packages within a workspace. Finds package.json files, parses them, and optionally discovers changelogs and internal dependencies.
Parameters
NameTypeDescription
§options
DiscoveryOptionsDiscovery options(default: {})
Returns
DiscoveryResult
Discovery result with all found packages
Example

Discover all packages within a workspace

import { discoverPackages } from '@hyperfrontend/versioning'

// Discover all packages in current workspace
const result = discoverPackages()

// Discover with custom patterns
const result = discoverPackages({
  patterns: ['packages/*/package.json'],
  includeChangelogs: true
})

// Access discovered projects
for (const project of result.projects) {
  console.log(`${project.name}@${project.version}`)
}
§function

discoverProject(projectPath: string): Project

Discovers a single project by path.
Parameters
NameTypeDescription
§projectPath
stringPath to project directory or package.json
Returns
Project
The discovered project or null if not found
Example

Discover a single project by path

import { discoverProject } from '@hyperfrontend/versioning'

const project = discoverProject('./libs/utils')
if (project) {
  console.log(`Found ${project.name}@${project.version}`)
}

// Also accepts direct package.json path
const project2 = discoverProject('./libs/utils/package.json')
§function

discoverProjectByName(projectName: string, options: DiscoveryOptions): Project

Discovers a project by name within a workspace.
Parameters
NameTypeDescription
§projectName
stringName of the project to find
§options
DiscoveryOptionsDiscovery options(default: {})
Returns
Project
The project or null if not found
Example

Discover a project by name within a workspace

import { discoverProjectByName } from '@hyperfrontend/versioning'

const project = discoverProjectByName('@myorg/utils')
if (project) {
  console.log(`Found at ${project.path}`)
}

// With custom workspace root
const project2 = discoverProjectByName('@myorg/core', { workspaceRoot: '/custom/path' })
§function

findChangelogs(workspaceRoot: string, packages: unknown): Map<string, string>

Finds changelog files for a list of packages. Returns a map of project path to changelog absolute path.
Parameters
NameTypeDescription
§workspaceRoot
stringWorkspace root path
§packages
unknownList of packages to find changelogs for
Returns
Map<string, string>
Map of project path to changelog path
Example

Find changelog files for all packages

import { findChangelogs, discoverPackages } from '@hyperfrontend/versioning'

const { packages } = discoverPackages()
const changelogs = findChangelogs('/workspace', packages)

for (const [projectPath, changelogPath] of changelogs) {
  console.log(`${projectPath} -> ${changelogPath}`)
}
§function

findChangelogsInTree(tree: Tree, packages: unknown): Map<string, string>

Finds changelog files for a list of packages using VFS tree. Returns a map of project path to changelog absolute path.
Parameters
NameTypeDescription
§tree
TreeVFS tree instance
§packages
unknownList of packages to find changelogs for
Returns
Map<string, string>
Map of project path to changelog path
Example

Find changelogs using VFS tree

import { findChangelogsInTree, discoverPackages } from '@hyperfrontend/versioning'

// Inside an Nx generator
export default function myGenerator(tree: Tree) {
  const { packages } = discoverPackages()
  const changelogs = findChangelogsInTree(tree, packages)

  for (const [projectPath, changelogPath] of changelogs) {
    console.log(`Found changelog at ${changelogPath}`)
  }
}
§function

findInternalDependencies(packageJson: PackageJson, workspacePackageNames: Set<string>): string[]

Finds internal dependencies in a package.json. Returns names of workspace packages that this package depends on.
Parameters
NameTypeDescription
§packageJson
PackageJsonParsed package.json content
§workspacePackageNames
Set<string>Set of all package names in the workspace
Returns
string[]
Array of internal dependency names
Example

Find internal dependencies in a package

const internalDeps = findInternalDependencies(packageJson, allPackageNames)
// ['@scope/lib-a', '@scope/lib-b']
§function

findInternalDependenciesWithTypes(packageName: string, packageJson: PackageJson, workspacePackageNames: Set<string>): DependencyEdge[]

Finds internal dependencies with type information.
Parameters
NameTypeDescription
§packageName
stringName of the package being analyzed
§packageJson
PackageJsonParsed package.json content
§workspacePackageNames
Set<string>Set of all package names in the workspace
Returns
DependencyEdge[]
Array of dependency edges with type information
Example

Find internal dependencies with type information

import { findInternalDependenciesWithTypes, readPackageJson } from '@hyperfrontend/versioning'

const packageJson = readPackageJson('./libs/my-lib/package.json')
const workspacePackages = new Set(['@myorg/utils', '@myorg/core'])

const edges = findInternalDependenciesWithTypes('@myorg/my-lib', packageJson, workspacePackages)
for (const edge of edges) {
  console.log(`${edge.from} -> ${edge.to} (${edge.type})`)
}
§function

findProjectChangelog(projectPath: string): string

Finds the changelog file for a single project. Checks for common changelog names in order of priority.
Parameters
NameTypeDescription
§projectPath
stringPath to project directory
Returns
string
Absolute path to changelog or null if not found
Example

Find the changelog for a single project

import { findProjectChangelog } from '@hyperfrontend/versioning'

const changelogPath = findProjectChangelog('./libs/my-lib')
if (changelogPath) {
  console.log('Found changelog:', changelogPath)
}
§function

findProjectChangelogInTree(tree: Tree, projectPath: string): string

Finds the changelog file for a single project using VFS tree. Checks for common changelog names in order of priority.
Parameters
NameTypeDescription
§tree
TreeVFS tree instance
§projectPath
stringPath to project directory
Returns
string
Absolute path to changelog or null if not found
Example

Find project changelog using VFS tree

import { findProjectChangelogInTree } from '@hyperfrontend/versioning'

// Inside an Nx generator
export default function myGenerator(tree: Tree) {
  const changelogPath = findProjectChangelogInTree(tree, 'libs/my-lib')
  if (changelogPath) {
    const content = tree.read(changelogPath, 'utf-8')
    // Process changelog content
  }
}
§function

getExpectedChangelogPath(projectPath: string, fileName: string): string

Gets the expected changelog path for a project. Returns the standard CHANGELOG.md path regardless of whether it exists.
Parameters
NameTypeDescription
§projectPath
stringDirectory containing the project files
§fileName
stringChangelog filename to use (default: 'CHANGELOG.md')(default: DEFAULT_CHANGELOG_FILENAME)
Returns
string
Absolute path to changelog file in the project directory
Example

Get expected changelog path for a project

import { getExpectedChangelogPath } from '@hyperfrontend/versioning'

const changelogPath = getExpectedChangelogPath('./libs/my-lib')
// => '/workspace/libs/my-lib/CHANGELOG.md'

const customPath = getExpectedChangelogPath('./libs/my-lib', 'HISTORY.md')
// => '/workspace/libs/my-lib/HISTORY.md'
§function

getTopologicalOrder(analysis: DependencyGraphAnalysis): unknown

Gets a topological ordering of packages for building. Packages with no dependencies come first.
Parameters
NameTypeDescription
§analysis
DependencyGraphAnalysisDependency graph analysis result
Returns
unknown
Array of package names in build order
Example

Get packages in topological order for building

const buildOrder = getTopologicalOrder(analysis)
for (const pkg of buildOrder) {
  await build(pkg)
}
§function

getTransitiveDependencies(workspace: Workspace, packageName: string): Set<string>

Gets all transitive dependencies of a package (direct and indirect).
Parameters
NameTypeDescription
§workspace
WorkspaceThe workspace containing projects
§packageName
stringName of the package to analyze
Returns
Set<string>
Set of all packages this package depends on
Example

Get all transitive dependencies of a package

import { discoverWorkspace, getTransitiveDependencies } from '@hyperfrontend/versioning'

const workspace = discoverWorkspace()
const allDeps = getTransitiveDependencies(workspace, '@myorg/app')

console.log(`@myorg/app transitively depends on ${allDeps.size} packages`)
for (const dep of allDeps) {
  console.log(`  - ${dep}`)
}
§function

getTransitiveDependents(workspace: Workspace, packageName: string): Set<string>

Gets all transitive dependents of a package (direct and indirect).
Parameters
NameTypeDescription
§workspace
WorkspaceThe workspace containing projects
§packageName
stringName of the package to analyze
Returns
Set<string>
Set of all packages that depend on this package
Example

Get all transitive dependents of a package

// If lib-a depends on lib-utils and app-main depends on lib-a
// Then getTransitiveDependents('lib-utils') returns ['lib-a', 'app-main']
§function

hasChangelog(projectPath: string): boolean

Checks if a project has a changelog file.
Parameters
NameTypeDescription
§projectPath
stringDirectory containing the project to check
Returns
boolean
True if changelog exists
Example

Check if a project has a changelog

import { hasChangelog } from '@hyperfrontend/versioning'

if (hasChangelog('./libs/my-lib')) {
  console.log('Project has a changelog')
}
§function

transitivelyDependsOn(workspace: Workspace, packageA: string, packageB: string): boolean

Checks if package A transitively depends on package B.
Parameters
NameTypeDescription
§workspace
WorkspaceThe workspace containing projects
§packageA
stringName of the potentially dependent package
§packageB
stringName of the potential dependency
Returns
boolean
True if packageA transitively depends on packageB
Example

Check if one package transitively depends on another

import { discoverWorkspace, transitivelyDependsOn } from '@hyperfrontend/versioning'

const workspace = discoverWorkspace()

if (transitivelyDependsOn(workspace, '@myorg/app', '@myorg/utils')) {
  console.log('Bumping @myorg/utils will affect @myorg/app')
}

◈ Interfaces

§interface

DependencyEdge

A single dependency edge in the graph.
Properties
§readonly from:stringPackage that has the dependency
§readonly to:stringPackage being depended on
§readonly type:DependencyTypeType of dependency relationship
§readonly versionRange:stringVersion range specified
§interface

DependencyGraphAnalysis

Result of dependency graph analysis.
Properties
§readonly circularDependencies:unknownDetected circular dependency chains
§readonly dependencyGraph:DependencyGraphForward graph: package -> dependents
§readonly edges:unknownAll dependency edges
§readonly hasCircularDependencies:booleanWhether the graph has circular dependencies
§readonly leafPackages:unknownPackages with no dependents (leaf nodes)
§readonly reverseDependencyGraph:DependencyGraphReverse graph: package -> dependencies
§readonly rootPackages:unknownPackages with no dependencies (root nodes)
§interface

DiscoveredChangelog

Represents a discovered changelog file.
Properties
§readonly filename:stringName of the changelog file
§readonly path:stringAbsolute path to the changelog file
§readonly projectPath:stringPath to the project containing this changelog
§readonly relativePath:stringRelative path from project root
§interface

DiscoveryOptions

Options for package discovery.
Properties
§exclude?:unknownPatterns to exclude
§includeChangelogs?:booleanInclude changelogs in discovery
§patterns?:unknownGlob patterns for finding package.json files
§trackDependencies?:booleanTrack internal dependencies
§tree?:TreeOptional VFS tree for VFS-aware discovery
§workspaceRoot?:stringWorkspace root (auto-detected if not provided)
§interface

DiscoveryResult

Result of package discovery.
Properties
§readonly config:WorkspaceConfigConfiguration used for discovery
§readonly packageNames:ReadonlySet<string>All discovered package names
§readonly projectMap:ReadonlyMap<string, Project>Projects indexed by name
§readonly projects:unknownAll discovered projects
§readonly workspaceRoot:stringWorkspace root path

◆ Types

§type

DependencyGraph

Dependency graph structure. Maps package name to list of packages that depend on it.
type DependencyGraph = ReadonlyMap<string, unknown>
§type

DependencyType

Dependency relation type.
type DependencyType = "dependencies" | "devDependencies" | "peerDependencies" | "optionalDependencies"

● Variables

§type

CHANGELOG_NAMES

Common changelog file names in priority order.