@hyperfrontend/project-scope/projectProject Module
The project module provides utilities for analyzing project structure, finding configuration files, reading package.json, discovering project roots, and traversing file trees.
Capabilities
Configuration Detection
Find and analyze configuration files in a project.
import { detectConfigs, findConfigFile } from '@hyperfrontend/project-scope'
// Detect all configuration files
const configs = detectConfigs('./my-project')
for (const config of configs) {
console.log(`${config.type}: ${config.path}`)
}
// Output:
// typescript: tsconfig.json
// eslint: eslint.config.js
// jest: jest.config.ts
// prettier: .prettierrc
// Detect specific config types
const tsConfigs = detectConfigs('./my-project', ['typescript', 'eslint'])
// Find specific config file
const eslintConfig = findConfigFile('./my-project', 'eslint')
// Returns: './my-project/eslint.config.js'
Supported Config Types
| Type | Example Files |
|---|---|
typescript |
tsconfig.json, tsconfig.*.json |
eslint |
.eslintrc, eslint.config.js, .eslintrc.json |
prettier |
.prettierrc, prettier.config.js |
jest |
jest.config.ts, jest.config.js |
vitest |
vitest.config.ts |
babel |
babel.config.js, .babelrc |
webpack |
webpack.config.js |
vite |
vite.config.ts |
rollup |
rollup.config.js |
nx |
nx.json, project.json |
docker |
Dockerfile, docker-compose.yml |
env |
.env, .env.* |
Package.json Utilities
Read and analyze package.json files.
import {
readPackageJson,
readPackageJsonIfExists,
findNearestPackageJson,
getDependencyVersion,
hasDependency,
} from '@hyperfrontend/project-scope'
// Read package.json
const pkg = readPackageJson('./my-project')
console.log(pkg.name, pkg.version)
console.log(pkg.dependencies)
console.log(pkg.scripts)
// Safe reading (returns null if not found)
const pkg2 = readPackageJsonIfExists('./maybe-project')
// Find nearest package.json from any path
const pkgPath = findNearestPackageJson('./src/utils/deep/file.ts')
// Returns: './src/package.json' or '../package.json'
// Check dependencies
if (hasDependency(pkg, 'react')) {
const version = getDependencyVersion(pkg, 'react')
console.log('React version:', version) // '^18.2.0'
}
Root Detection
Find project and workspace roots from any path.
import { findProjectRoot, findWorkspaceRoot } from '@hyperfrontend/project-scope'
// Find project root (nearest package.json with source files)
const projectRoot = findProjectRoot('./libs/my-lib/src/utils/helper.ts')
// Returns: './libs/my-lib'
// Find workspace/monorepo root
const workspaceRoot = findWorkspaceRoot('./libs/my-lib')
// Returns: './' (root with nx.json, turbo.json, etc.)
Root Markers
Project root markers:
package.json(withsrc/directory or entry files)project.json(NX project)
Workspace root markers:
nx.jsonturbo.jsonlerna.jsonpnpm-workspace.yamlrush.jsonpackage.jsonwithworkspacesfield
File Traversal
Search and walk through project files.
import { findFiles, walkDirectory, walkTree } from '@hyperfrontend/project-scope'
// Find files by glob pattern
const tsFiles = findFiles('./src', '**/*.ts')
const configFiles = findFiles('./', ['*.json', '*.yaml'])
// With options
const limited = findFiles('./src', '**/*.ts', {
maxResults: 10,
absolutePaths: true,
maxDepth: 5,
})
// Walk directory with callback
walkDirectory('./src', (entry) => {
if (entry.isFile && entry.name.endsWith('.ts')) {
console.log('Found:', entry.relativePath)
}
// Return 'skip' to skip directory, 'stop' to stop walking
})
// Walk virtual file system tree
walkTree(tree, tree.root, (entry) => {
console.log(entry.path, entry.isFile ? 'file' : 'directory')
})
Interfaces
PackageJson
interface PackageJson {
name?: string
version?: string
description?: string
main?: string
module?: string
browser?: string
types?: string
bin?: string | Record<string, string>
scripts?: Record<string, string>
dependencies?: Record<string, string>
devDependencies?: Record<string, string>
peerDependencies?: Record<string, string>
optionalDependencies?: Record<string, string>
workspaces?: string[] | { packages: string[] }
exports?: Record<string, unknown>
engines?: Record<string, string>
[key: string]: unknown
}
DetectedConfig
interface DetectedConfig {
/** Config type (e.g., 'typescript', 'eslint') */
type: ConfigType
/** File path relative to root */
path: string
/** Pattern that matched */
matchedPattern: string
/** Pattern info */
info: ConfigPatternInfo
}
DirectoryEntry
interface DirectoryEntry {
/** File/directory name */
name: string
/** Full path */
path: string
/** Relative path from start */
relativePath: string
/** Is a file */
isFile: boolean
/** Is a directory */
isDirectory: boolean
/** Traversal depth */
depth: number
}
Design Principles
- Caching: All detection functions cache results appropriately
- Safe operations:
*IfExistsvariants return null instead of throwing - Flexible patterns: Support for multiple glob patterns
- Depth control: Configurable traversal depth limits
- Cross-platform: Works on Windows, macOS, and Linux
API Reference
ƒ Functions
Useful for testing or when the project files have changed.
Example
Clearing the config detection cache
import { clearConfigDetectionCache } from '@hyperfrontend/project-scope'
// Reset cache after modifying config files
clearConfigDetectionCache()detectConfigs(rootPath: string, types?: ConfigType[], options?: DetectConfigOptions): DetectedConfig[]
Results are cached for 30 seconds per project path and options to avoid redundant file system operations on repeated calls.
Parameters
Returns
DetectedConfig[]Example
Detecting configuration files
import { detectConfigs } from '@hyperfrontend/project-scope'
// Detect all config files
const configs = detectConfigs('./my-project')
for (const config of configs) {
console.log(`${config.type}: ${config.path}`)
}
// Output:
// typescript: tsconfig.json
// eslint: eslint.config.js
// jest: jest.config.ts
// Detect specific config types only
const tsConfigs = detectConfigs('./my-project', ['typescript', 'eslint'])Parameters
Returns
stringExample
Finding a specific config file
import { findConfigFile } from '@hyperfrontend/project-scope'
const tsConfig = findConfigFile('/project', 'typescript')
// => '/project/tsconfig.json'
const eslint = findConfigFile('/project', 'eslint')
// => '/project/.eslintrc.js' or null if not foundfindDirectories(startPath: string, patterns: string | string[], options?: FindOptions): string[]
Parameters
Returns
string[]Example
Finding directories by pattern
import { findDirectories } from '@hyperfrontend/project-scope'
const componentDirs = findDirectories('./src', 'components')
// => ['features/auth/components', 'features/dashboard/components']Parameters
Returns
string[]Example
Finding files by pattern
import { findFiles } from '@hyperfrontend/project-scope'
// Find all TypeScript files
const tsFiles = findFiles('./src', '\*\*/*.ts')
// Find multiple file types
const configFiles = findFiles('./', ['\*.json', '\*.yaml', '\*.yml'])
// Limit results and get absolute paths
const first10 = findFiles('./src', '\*\*/*.ts', {
maxResults: 10,
absolutePaths: true
})Parameters
Returns
string[]Example
Finding files in a virtual tree
import { createTree, findFilesInTree } from '@hyperfrontend/project-scope'
const tree = createTree('/workspace')
const tsFiles = findFilesInTree(tree, '**/*.ts', { maxDepth: 3 })
// => ['src/index.ts', 'src/utils/helpers.ts']Parameters
| Name | Type | Description |
|---|---|---|
§startPath | string | Starting path |
Returns
stringExample
Finding Git repository root
import { findGitRoot } from '@hyperfrontend/project-scope'
const gitRoot = findGitRoot('./src/deep/nested/file.ts')
// => '/path/to/repository'Parameters
| Name | Type | Description |
|---|---|---|
§startPath | string | Starting path |
Returns
stringExample
Finding nearest package.json
import { findNearestPackageJson } from '@hyperfrontend/project-scope'
const pkgDir = findNearestPackageJson('./src/deep/nested/file.ts')
// => '/path/to/project'Parameters
| Name | Type | Description |
|---|---|---|
§startPath | string | Starting path |
Returns
stringExample
Finding project root
import { findProjectRoot } from '@hyperfrontend/project-scope'
// Find project root from current directory
const root = findProjectRoot(process.cwd())
if (root) {
console.log('Project root:', root)
}
// Find root from a deeply nested file
const root2 = findProjectRoot('./libs/my-lib/src/utils/helper.ts')Parameters
Returns
stringExample
Finding root by marker files
import { findRootDirectory } from '@hyperfrontend/project-scope'
// Find monorepo root by looking for nx.json or lerna.json
const root = findRootDirectory('./libs/my-lib', ['nx.json', 'lerna.json'])
// => '/path/to/monorepo'Parameters
| Name | Type | Description |
|---|---|---|
§startPath | string | Starting path |
Returns
stringExample
Finding workspace root
import { findWorkspaceRoot } from '@hyperfrontend/project-scope'
const root = findWorkspaceRoot('./libs/my-lib')
if (root) {
console.log('Monorepo root:', root) // e.g., '/home/user/my-monorepo'
}Parameters
| Name | Type | Description |
|---|---|---|
§packageJson | PackageJson | Parsed package.json |
Returns
DependencyMapExample
Getting all merged dependencies
import { getAllDependencies } from '@hyperfrontend/project-scope'
const allDeps = getAllDependencies(packageJson)
if ('typescript' in allDeps) {
console.log('TypeScript version:', allDeps['typescript'])
}Parameters
| Name | Type | Description |
|---|---|---|
§types | ConfigType[] | Array of config types to get patterns for |
Returns
string[]Example
Retrieving config patterns by type
import { getConfigPatternsByType } from '@hyperfrontend/project-scope'
const patterns = getConfigPatternsByType(['typescript', 'eslint'])
// => ['tsconfig.json', 'tsconfig.*.json', '.eslintrc', '.eslintrc.js', ...]Parameters
| Name | Type | Description |
|---|---|---|
§packageJson | PackageJson | Parsed package.json |
Returns
AllDependenciesExample
Extracting all dependencies
import { getDependencies } from '@hyperfrontend/project-scope'
const deps = getDependencies(packageJson)
console.log('Runtime:', Object.keys(deps.dependencies))
console.log('Dev:', Object.keys(deps.devDependencies))Parameters
Returns
stringExample
Getting dependency version
import { getDependencyVersion } from '@hyperfrontend/project-scope'
const version = getDependencyVersion(packageJson, 'react')
// => '^18.2.0' or nullParameters
| Name | Type | Description |
|---|---|---|
§packageJson | PackageJson | Parsed package.json |
Returns
DependencyMapExample
Getting development dependencies
import { getDevDependencies } from '@hyperfrontend/project-scope'
const devDeps = getDevDependencies(packageJson)
// => { 'jest': '^29.0.0', 'typescript': '^5.0.0' }Parameters
| Name | Type | Description |
|---|---|---|
§packageJson | PackageJson | Parsed package.json |
Returns
DependencyMapExample
Getting peer dependencies
import { getPeerDependencies } from '@hyperfrontend/project-scope'
const peerDeps = getPeerDependencies(packageJson)
// => { 'react': '^18.0.0', 'react-dom': '^18.0.0' }Parameters
| Name | Type | Description |
|---|---|---|
§packageJson | PackageJson | Parsed package.json |
Returns
DependencyMapExample
Getting production dependencies
import { getProductionDependencies } from '@hyperfrontend/project-scope'
const prodDeps = getProductionDependencies(packageJson)
// => { 'express': '^4.18.0', 'lodash': '^4.17.21' }Parameters
| Name | Type | Description |
|---|---|---|
§packageJson | PackageJson | Parsed package.json |
Returns
string[]Example
Getting workspace patterns
import { getWorkspaces } from '@hyperfrontend/project-scope'
const patterns = getWorkspaces(packageJson)
// => ['packages/*', 'apps/*']hasDependency(packageJson: PackageJson, name: string, depTypes?: ("dependencies" | "devDependencies" | "peerDependencies" | "optionalDependencies")[]): boolean
Parameters
Returns
booleanExample
Checking for a dependency
import { hasDependency } from '@hyperfrontend/project-scope'
// Check any dependency type
hasDependency(packageJson, 'lodash')
// Check only production dependencies
hasDependency(packageJson, 'lodash', ['dependencies'])Parameters
Returns
booleanExample
Checking installed packages
import { hasInstalledPackage } from '@hyperfrontend/project-scope'
if (hasInstalledPackage('/project', 'typescript')) {
console.log('TypeScript is installed')
}Parameters
| Name | Type | Description |
|---|---|---|
§packageJson | PackageJson | Parsed package.json |
Returns
booleanExample
Checking for workspaces
import { hasWorkspaces } from '@hyperfrontend/project-scope'
if (hasWorkspaces(packageJson)) {
console.log('This is a monorepo')
}Parameters
Returns
ParsedConfigExample
Parsing a configuration file
import { parseConfig } from '@hyperfrontend/project-scope'
const tsConfig = parseConfig('/project/tsconfig.json')
const eslintConfig = parseConfig('/project/.eslintrc.yml', 'eslint')parseJsonConfig(filePath: string, content: string, type?: ConfigType, format: "json" | "jsonc"): ParsedConfig
Parameters
Returns
ParsedConfigExample
Parsing JSON configuration
import { parseJsonConfig } from '@hyperfrontend/project-scope'
const config = parseJsonConfig(
'tsconfig.json',
'{ "extends": "./base.json", "compilerOptions": {} }',
'typescript'
)
// => { type: 'typescript', path: 'tsconfig.json', data: {...}, extends: ['./base.json'] }Parameters
Returns
ParsedConfigExample
Parsing YAML configuration
import { parseYamlConfig } from '@hyperfrontend/project-scope'
const config = parseYamlConfig('.github/workflows/ci.yml', yamlContent, 'github-actions')
// => { type: 'github-actions', path: '...', format: 'yaml', data: {...} }Parameters
| Name | Type | Description |
|---|---|---|
§projectPath | string | Project directory path or path to package.json |
Returns
PackageJsonExample
Reading package.json
import { readPackageJson } from '@hyperfrontend/project-scope'
const pkg = readPackageJson('/path/to/project')
console.log(pkg.name, pkg.version)Parameters
| Name | Type | Description |
|---|---|---|
§projectPath | string | Project directory path or path to package.json |
Returns
PackageJsonExample
Reading package.json if it exists
import { readPackageJsonIfExists } from '@hyperfrontend/project-scope'
const pkg = readPackageJsonIfExists('/path/to/project')
if (pkg) {
console.log('Found:', pkg.name)
}Parameters
Example
Walking a directory tree
import { walkDirectory } from '@hyperfrontend/project-scope'
const tsFiles: string[] = []
walkDirectory('./src', (entry) => {
if (entry.isFile && entry.name.endsWith('.ts')) {
tsFiles.push(entry.relativePath)
}
}, { maxDepth: 5, respectGitignore: true })Parameters
Example
Walking a virtual tree
import { createTree, walkTree } from '@hyperfrontend/project-scope'
const tree = createTree('/workspace')
walkTree(tree, 'src', (entry) => {
if (entry.isDirectory) {
console.log('Dir:', entry.relativePath)
return 'skip' // Don't recurse into this directory
}
})◈ Interfaces
Properties
format?:"json" | "yaml" | "js" | "ts" | "jsonc" | "ini" | "dotenv" | "text"— Properties
Properties
◆ Types
type ConfigType = "package.json" | "package-lock.json" | "pnpm-lock.yaml" | "yarn.lock" | ".npmrc" | "tsconfig" | "nx" | "project.json" | "workspace.json" | "turbo" | "lerna" | "webpack" | "rollup" | "vite" | "esbuild" | "babel" | "swc" | "jest" | "vitest" | "cypress" | "playwright" | "next" | "angular" | "nuxt" | "svelte" | "astro" | "eslint" | "prettier" | "env" | ".gitignore" | ".gitattributes"