@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
unknown
List 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
string
Workspace root path
§patterns
unknown
Glob 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
DiscoveryOptions
Discovery 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
string
Path 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
string
Name of the project to find
§options
DiscoveryOptions
Discovery 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
string
Workspace root path
§packages
unknown
List 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
Tree
VFS tree instance
§packages
unknown
List 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
PackageJson
Parsed 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
string
Name of the package being analyzed
§packageJson
PackageJson
Parsed 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
string
Path 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
Tree
VFS tree instance
§projectPath
string
Path 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
string
Directory containing the project files
§fileName
string
Changelog 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
DependencyGraphAnalysis
Dependency 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
Workspace
The workspace containing projects
§packageName
string
Name 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
Workspace
The workspace containing projects
§packageName
string
Name 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
string
Directory 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
Workspace
The workspace containing projects
§packageA
string
Name of the potentially dependent package
§packageB
string
Name 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:string
Package that has the dependency
§readonly to:string
Package being depended on
§readonly type:DependencyType
Type of dependency relationship
§readonly versionRange:string
Version range specified
§interface

DependencyGraphAnalysis

Result of dependency graph analysis.

Properties

§readonly circularDependencies:unknown
Detected circular dependency chains
§readonly dependencyGraph:DependencyGraph
Forward graph: package -> dependents
§readonly edges:unknown
All dependency edges
§readonly hasCircularDependencies:boolean
Whether the graph has circular dependencies
§readonly leafPackages:unknown
Packages with no dependents (leaf nodes)
§readonly reverseDependencyGraph:DependencyGraph
Reverse graph: package -> dependencies
§readonly rootPackages:unknown
Packages with no dependencies (root nodes)
§interface

DiscoveredChangelog

Represents a discovered changelog file.

Properties

§readonly filename:string
Name of the changelog file
§readonly path:string
Absolute path to the changelog file
§readonly projectPath:string
Path to the project containing this changelog
§readonly relativePath:string
Relative path from project root
§interface

DiscoveryOptions

Options for package discovery.

Properties

§exclude?:unknown
Patterns to exclude
§includeChangelogs?:boolean
Include changelogs in discovery
§patterns?:unknown
Glob patterns for finding package.json files
§trackDependencies?:boolean
Track internal dependencies
§tree?:Tree
Optional VFS tree for VFS-aware discovery
§workspaceRoot?:string
Workspace root (auto-detected if not provided)
§interface

DiscoveryResult

Result of package discovery.

Properties

§readonly config:WorkspaceConfig
Configuration used for discovery
§readonly packageNames:ReadonlySet<string>
All discovered package names
§readonly projectMap:ReadonlyMap<string, Project>
Projects indexed by name
§readonly projects:unknown
All discovered projects
§readonly workspaceRoot:string
Workspace 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.