@hyperfrontend/project-scope/heuristics

Heuristics Module

The heuristics module provides intelligent detection of project characteristics using multiple signals. It analyzes project structure, configuration files, dependencies, and code patterns to make accurate determinations about project type, frameworks, entry points, and dependency graphs.

Capabilities

Project Type Detection

Determine if a project is an application, library, e2e test suite, CLI tool, or plugin.

import { detectProjectType } from '@hyperfrontend/project-scope'

const result = detectProjectType('./my-project')
console.log(result.type) // 'library' | 'application' | 'e2e' | 'tool' | 'plugin'
console.log(result.confidence) // 85
console.log(result.evidence)
// [{ factor: 'exports', confidence: 20, description: '...' }]

Detection Factors

FactorSignalsConfidence Impact
Package name-lib, -app, -e2e, -cli suffixes15-30
Exports fieldHas exports, main, or module+20 for library
Bin fieldHas CLI executable definition+40 for tool
Entry pointsserver.ts vs index.ts patterns20-30
Directory structurepublic/, pages/, lib/, cypress/10-20
Framework presenceFrontend/backend frameworks+20 for application
E2E frameworksCypress, Playwright, Puppeteer+25 for e2e

Framework Identification

Comprehensive framework detection with confidence scoring.

import { identifyFrameworks } from '@hyperfrontend/project-scope'

const result = identifyFrameworks('./my-react-app')

console.log(result.summary) // 'React + Next.js with Jest'
console.log(result.primary?.name) // 'React'
console.log(result.frontend) // [{ id: 'react', name: 'React', ... }]
console.log(result.backend) // [{ id: 'express', name: 'Express', ... }]
console.log(result.metaFrameworks) // [{ id: 'nextjs', name: 'Next.js', ... }]
console.log(result.testing) // [{ id: 'jest', name: 'Jest', ... }]

// Stack summary for quick access
console.log(result.stack.frontend) // ['react', 'nextjs']
console.log(result.stack.testing) // ['jest']
console.log(result.stack.build) // ['webpack']
console.log(result.stack.linting) // ['eslint', 'prettier']

Entry Point Discovery

Find application entry points from package.json and conventions.

import { discoverEntryPoints } from '@hyperfrontend/project-scope'

const entryPoints = discoverEntryPoints('./my-app')

for (const entry of entryPoints) {
  console.log(`${entry.path} (${entry.type}) - ${entry.confidence}% confidence`)
}
// Output:
// src/index.ts (main) - 100% confidence
// src/cli.ts (cli) - 85% confidence
// src/server.ts (server) - 80% confidence

Entry Point Sources

SourcePriorityExamples
package.json fields100%main, module, browser, bin, exports
Convention patterns80-90%src/index.ts, src/main.ts, src/server.ts
Framework-specific85%Next.js pages, Angular modules

Dependency Graph Analysis

Build internal dependency graphs from source code.

import { buildDependencyGraph } from '@hyperfrontend/project-scope'

const graph = buildDependencyGraph('./my-lib')

console.log('Root files:', graph.roots) // Files not imported by anything
console.log('Leaf files:', graph.leaves) // Files that don't import anything
console.log('Total nodes:', graph.nodes.size)

// Examine dependencies
const node = graph.nodes.get('src/utils/helper.ts')
console.log('Depends on:', node?.dependencies) // ['src/utils/base.ts']
console.log('Used by:', node?.dependents) // ['src/index.ts', 'src/cli.ts']

Dependency Extraction

Supports multiple import/export patterns:

  • ES imports: import { x } from './module'
  • Dynamic imports: import('./module')
  • CommonJS: require('./module')
  • Re-exports: export * from './module'

Package Dependencies

Analyze npm dependencies from package.json.

import { getProjectDependencies } from '@hyperfrontend/project-scope'

const deps = getProjectDependencies('./my-project')

console.log('Runtime:', deps.runtime) // ['react', 'lodash']
console.log('Development:', deps.development) // ['typescript', 'jest']
console.log('Peer:', deps.peer) // ['react']
console.log('Total:', deps.total) // 25

Caching

All detection functions use intelligent caching:

  • TTL: 60 seconds (appropriate for active development)
  • Automatic invalidation: Cache keys include all relevant options
  • Skip cache: Pass { skipCache: true } for fresh results
// Force fresh detection
const result = detectProjectType('./project', { skipCache: true })

Design Principles

  1. Multi-signal detection: Never rely on a single indicator
  2. Confidence scoring: All detections include confidence percentages
  3. Evidence tracking: Understand why a detection was made
  4. Graceful degradation: Always returns a result, even with low confidence
  5. Performance: Aggressive caching with appropriate TTLs

API Reference§

ƒ Functions

§function

buildDependencyGraph(projectPath: string, options?: BuildGraphOptions): DependencyGraph

Build dependency graph from source files.
Analyzes imports/exports in source files to build a graph of internal dependencies.
Parameters
NameTypeDescription
§projectPath
stringAbsolute path to project root
§options?
BuildGraphOptionsConfiguration for graph building
Returns
DependencyGraph
Dependency graph with nodes, roots, and leaves
Example

Building a dependency graph

import { buildDependencyGraph } from '@hyperfrontend/project-scope'

const graph = buildDependencyGraph('./my-lib')
console.log('Root files:', graph.roots)   // Files not imported by anything
console.log('Leaf files:', graph.leaves)  // Files that don't import anything
console.log('Total nodes:', graph.nodes.size)

// Examine a specific node's dependencies
const node = graph.nodes.get('src/utils/helper.ts')
console.log('Depends on:', node?.dependencies)
console.log('Used by:', node?.dependents)
§function

clearEntryPointCache(): void

Clear the entry point discovery cache.
Useful for testing or when the project files have changed.
Example

Clearing the entry point cache

import { clearEntryPointCache } from '@hyperfrontend/project-scope'

// Reset cache before re-analyzing after file changes
clearEntryPointCache()
§function

clearFrameworkIdentificationCache(): void

Clear the framework identification cache.
Useful for testing or when the project files have changed.
Example

Clearing the framework cache

import { clearFrameworkIdentificationCache } from '@hyperfrontend/project-scope'

// Reset cache before re-identifying frameworks
clearFrameworkIdentificationCache()
§function

detectProjectType(projectPath: string, options?: DetectProjectTypeOptions): ProjectTypeDetection

Detect the type of a project based on its structure and configuration.
Uses multiple heuristics including:
  • Package name patterns
  • Exports/main/module fields
  • Binary (bin) field
  • Entry point patterns
  • Testing framework presence
  • Directory structure
  • Framework detection
  • NX project type field
Parameters
NameTypeDescription
§projectPath
stringProject directory path
§options?
DetectProjectTypeOptionsDetection options
Returns
ProjectTypeDetection
Project type detection result with confidence score
Example

Detecting project type

import { detectProjectType } from '@hyperfrontend/project-scope'

const result = detectProjectType('./my-lib')
console.log(result.type)       // 'library' | 'application' | 'e2e' | 'tool' | 'plugin'
console.log(result.confidence) // 85
console.log(result.evidence)   // [{ factor: 'exports', confidence: 20, ... }]
§function

discoverEntryPoints(projectPath: string, options?: DiscoverEntryPointsOptions): EntryPointInfo[]

Discover entry points in project.
Analyzes package.json fields (main, module, bin, exports), convention-based patterns, and framework-specific entries.
Results are cached for 60 seconds per project path and options to avoid redundant file system operations on repeated calls.
Parameters
NameTypeDescription
§projectPath
stringProject directory path
§options?
DiscoverEntryPointsOptionsDiscovery options
Returns
EntryPointInfo[]
Array of discovered entry points sorted by confidence
Example

Discovering project entry points

import { discoverEntryPoints } from '@hyperfrontend/project-scope'

const entryPoints = discoverEntryPoints('./my-app')
for (const entry of entryPoints) {
  console.log(`${entry.path} (${entry.type}) - ${entry.confidence}% confidence`)
}
// Output:
// src/index.ts (main) - 100% confidence
// src/cli.ts (cli) - 85% confidence
§function

findCircularDependencies(graph: DependencyGraph): CircularDependency[]

Find circular dependencies in graph using DFS.
Parameters
NameTypeDescription
§graph
DependencyGraphDependency graph
Returns
CircularDependency[]
Array of circular dependencies found
Example

Finding circular dependencies

import { buildDependencyGraph, findCircularDependencies } from '@hyperfrontend/project-scope'

const graph = buildDependencyGraph('/workspace')
const cycles = findCircularDependencies(graph)
cycles.forEach(c => console.log(`Cycle: ${c.cycle.join(' -> ')}`))
§function

getProjectDependencies(projectPath: string): ProjectDependencies

Collect all dependencies from package.json grouped by category.
Parameters
NameTypeDescription
§projectPath
stringProject directory
Returns
ProjectDependencies
Dependencies grouped by runtime, dev, peer, and optional
Example

Getting project dependencies

import { getProjectDependencies } from '@hyperfrontend/project-scope'

const deps = getProjectDependencies('/path/to/project')
console.log('Runtime:', deps.runtime)     // ['express', 'lodash']
console.log('Dev:', deps.development)     // ['jest', 'typescript']
console.log('Total:', deps.total)         // 15
§function

identifyFrameworks(projectPath: string, options?: IdentifyFrameworksOptions): FrameworkIdentification

Identify all frameworks in project.
Runs all technology detectors and aggregates results into a comprehensive framework identification with confidence scoring.
Parameters
NameTypeDescription
§projectPath
stringProject directory path
§options?
IdentifyFrameworksOptionsIdentification options
Returns
FrameworkIdentification
Framework identification result
Example

Identifying all frameworks in project

import { identifyFrameworks } from '@hyperfrontend/project-scope'

const result = identifyFrameworks('./my-react-app')
console.log(result.summary)      // 'React + Next.js with Jest'
console.log(result.primary?.name) // 'React'
console.log(result.stack.frontend) // ['react', 'nextjs']
console.log(result.stack.testing)  // ['jest']
§function

usesFramework(projectPath: string, frameworkId: string, minConfidence: number): boolean

Check if a project uses a specific framework.
Parameters
NameTypeDescription
§projectPath
stringProject directory path
§frameworkId
stringFramework identifier to check
§minConfidence
numberMinimum confidence threshold (default: 50)(default: 50)
Returns
boolean
True if the framework is detected with sufficient confidence
Example

Checking for a specific framework

import { usesFramework } from '@hyperfrontend/project-scope'

if (usesFramework('/path/to/project', 'react', 70)) {
  console.log('Project uses React with high confidence')
}

◈ Interfaces

§interface

BuildGraphOptions

Options for dependency graph building.
Properties
§extensions?:string[]File extensions to analyze
§includeExternal?:booleanInclude node_modules imports
§maxDepth?:numberMaximum depth to traverse
§interface

CircularDependency

Circular dependency information.
Properties
§cycle:string[]Ordered list of files in cycle
§length:numberCycle length
§interface

DetectProjectTypeOptions

Options for project type detection.
Properties
§skipTechDetection?:booleanSkip technology detection (faster but less accurate)
§interface

DiscoverEntryPointsOptions

Options for entry point discovery.
Properties
§includeFrameworkEntries?:booleanInclude framework-specific entries (e.g., Next.js pages)
§maxDepth?:numberMaximum depth for file search
§skipCache?:booleanSkip cache lookup (force fresh detection)
§interface

ExtendedEntryPointInfo

Extended entry point info with source.
Properties
§confidence:numberDetection confidence (0-100)
§path:stringFile path
§source:EntryPointSourceHow the entry point was discovered
§type:"main" | "app" | "server" | "cli" | "test"Entry point type
§interface

FrameworkIdentification

Framework identification result.
Properties
§backend:FrameworkInfo[]Backend frameworks
§frontend:FrameworkInfo[]Frontend frameworks
§metaFrameworks:FrameworkInfo[]Meta-frameworks (Next.js, Nuxt, etc.)
§primary?:FrameworkInfoPrimary framework (highest confidence)
§stack:StackSummaryStack summary
§summary:stringSummary string (e.g., "React + Next.js with Jest")
§testing:TestingInfo[]Testing frameworks
§interface

IdentifyFrameworksOptions

Options for framework identification.
Properties
§minConfidence?:numberMinimum confidence threshold (0-100)
§skipCache?:booleanSkip cache lookup (force fresh detection)
§interface

ProjectDependencies

Project dependencies categorized.
Properties
§development:string[]Development dependencies
§optional:string[]Optional dependencies
§peer:string[]Peer dependencies
§runtime:string[]Production dependencies
§total:numberTotal count
§interface

ProjectTypeDetection

Project type detection result.
Properties
§confidence:numberDetection confidence (0-100)
§evidence:TypeEvidence[]Evidence collected
§secondaryTypes:ProjectType[]Secondary types
§type:ProjectTypePrimary project type
§interface

StackSummary

Stack summary for a project.
Properties
§backend:string[]Backend framework IDs
§build:string[]Build tool IDs
§frontend:string[]Frontend framework IDs
§linting:string[]Linting tool IDs
§testing:string[]Testing framework IDs
§typeSystem:string[]Type system IDs
§interface

TypeEvidence

Type evidence for detection.
Properties
§confidence:numberConfidence contribution
§description:stringDescription
§factor:stringEvidence factor

◆ Types

§type

EntryPointSource

Entry point source information. Describes how an entry point was discovered.
type EntryPointSource = PackageJsonEntrySource | ConventionEntrySource | FrameworkEntrySource | ConfigEntrySource
§type

EntryPointType

Supported entry point type enumeration.
type EntryPointType = "main" | "app" | "server" | "cli" | "test"

● Variables

§type

ENTRY_POINT_PATTERNS

Common entry point patterns by project type. Used for convention-based entry point discovery.