Sign In

@bfra.me/workspace-analyzer

Package Overview
Dependencies
Maintainers
2
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@bfra.me/workspace-analyzer

Comprehensive monorepo static analysis for workspace configuration, dependencies, and architecture

latest
Source
npmnpm
Version
0.2.8
Version published
Weekly downloads
13
85.71%
Maintainers
2
Weekly downloads
 
Created
Source

@bfra.me/workspace-analyzer

Comprehensive monorepo static analysis for workspace configuration, dependencies, and architecture.

Features

  • Configuration Analysis: Detect inconsistencies across package.json, tsconfig.json, eslint.config.ts, and tsup.config.ts files
  • Dependency Analysis: Identify unused dependencies and circular imports with full path reporting
  • Architectural Validation: Validate against configurable rule sets (layer violations, barrel export misuse)
  • Performance Analysis: Identify tree-shaking blockers, large dependencies, and dead code
  • Modern CLI: Interactive TUI using @clack/prompts with progress reporting
  • Incremental Analysis: Caching support for fast re-analysis of large codebases
  • Multiple Output Formats: Console, JSON, and Markdown report generation

Installation

pnpm add -D @bfra.me/workspace-analyzer

Quick Start

# Analyze current workspace
npx workspace-analyzer

# Interactive mode with package selection
npx workspace-analyzer --interactive

# CI-friendly JSON output
npx workspace-analyzer --json > analysis-report.json

CLI Usage

The CLI provides a modern, interactive experience powered by @clack/prompts:

# Basic analysis
workspace-analyzer [path]

# With configuration file
workspace-analyzer --config workspace-analyzer.config.ts

# Output formats
workspace-analyzer --json          # JSON output
workspace-analyzer --markdown      # Markdown report

# Filtering options
workspace-analyzer --min-severity warning
workspace-analyzer --categories dependency,architecture

# Analysis control
workspace-analyzer --no-cache      # Disable caching
workspace-analyzer --verbose       # Detailed output
workspace-analyzer --dry-run       # Preview without analysis

CLI Options

OptionDescription
--config <path>Path to configuration file
--jsonOutput results as JSON
--markdownOutput results as Markdown
--min-severity <level>Minimum severity to report (info, warning, error, critical)
--categories <list>Comma-separated categories to analyze
--include <patterns>Glob patterns for files to include
--exclude <patterns>Glob patterns for files to exclude
--no-cacheDisable incremental analysis caching
--cache-dir <path>Custom cache directory
--concurrency <n>Maximum parallel operations
--verboseEnable verbose logging
--quietSuppress non-essential output
--dry-runPreview analysis without executing
--interactiveInteractive package selection
--fixApply auto-fixes where available (placeholder)

Visualization Command

Generate interactive dependency graph visualizations with the visualize command:

# Generate interactive HTML visualization
workspace-analyzer visualize

# Generate JSON data for external tools
workspace-analyzer visualize --format json --output graph.json

# Generate Mermaid diagram
workspace-analyzer visualize --format mermaid --output graph.mmd

# Interactive mode with options
workspace-analyzer visualize --interactive

# Custom title and node limits
workspace-analyzer visualize --title "My Project" --max-nodes 100

# Generate both HTML and JSON
workspace-analyzer visualize --format both

Visualization Options

OptionDescriptionDefault
--output <path>Output file pathworkspace-graph.html
--format <format>Output format: html, json, mermaid, bothhtml
--no-openDisable auto-opening in browserfalse (opens by default)
--title <title>Visualization titleWorkspace Dependency Graph
--max-nodes <number>Maximum nodes to render (performance)1000
--include-type-importsInclude type-only imports in graphfalse
--interactiveInteractive mode for options selectionfalse

Export Formats

HTML - Self-contained interactive visualization with D3.js:

  • Force-directed graph layout with zoom/pan controls
  • Filter by layer, severity, package scope
  • View modes: all, cycles-only, violations-only
  • Node tooltips with violation details
  • No external network requests (fully offline)

JSON - Structured data for external tools and custom processing:

{
  "nodes": [
    {
      "id": "src/utils/helpers.ts",
      "name": "helpers.ts",
      "filePath": "src/utils/helpers.ts",
      "packageName": "@myorg/utils",
      "layer": "infrastructure",
      "importsCount": 5,
      "importedByCount": 12,
      "isInCycle": false,
      "violations": [
        {
          "id": "v1",
          "message": "Layer violation: infrastructure importing from domain",
          "severity": "error",
          "ruleId": "layer-dependency"
        }
      ],
      "highestViolationSeverity": "error"
    }
  ],
  "edges": [
    {
      "source": "src/utils/helpers.ts",
      "target": "src/core/types.ts",
      "type": "static",
      "isInCycle": false
    }
  ],
  "cycles": [
    {
      "id": "cycle-1",
      "nodes": ["src/a.ts", "src/b.ts"],
      "edges": [
        {"from": "src/a.ts", "to": "src/b.ts"},
        {"from": "src/b.ts", "to": "src/a.ts"}
      ],
      "length": 2,
      "description": "Circular dependency: a.ts → b.ts → a.ts"
    }
  ],
  "statistics": {
    "totalNodes": 250,
    "totalEdges": 380,
    "totalCycles": 3,
    "nodesByLayer": {
      "domain": 50,
      "application": 80,
      "infrastructure": 120
    },
    "violationsBySeverity": {
      "critical": 0,
      "error": 5,
      "warning": 15,
      "info": 2
    },
    "packagesAnalyzed": 12,
    "filesAnalyzed": 250
  },
  "metadata": {
    "workspacePath": "/path/to/workspace",
    "generatedAt": "2025-12-10T00:00:00Z",
    "analyzerVersion": "0.1.0"
  }
}

Mermaid - Diagram markup for documentation and external rendering:

graph LR
  src_utils_helpers_ts["helpers.ts"]:::class-error
  src_core_types_ts["types.ts"]:::class-normal
  src_utils_helpers_ts --> src_core_types_ts

  classDef class-critical fill:#ff4444,stroke:#cc0000,stroke-width:3px,color:#fff
  classDef class-error fill:#ff8844,stroke:#cc4400,stroke-width:2px,color:#fff
  classDef class-warning fill:#ffcc44,stroke:#ccaa00,stroke-width:2px,color:#000
  classDef class-info fill:#4488ff,stroke:#0044cc,stroke-width:1px,color:#fff
  classDef class-normal fill:#88ccff,stroke:#0088cc,stroke-width:1px,color:#000

Common Visualization Scenarios

Investigate Circular Dependencies:

# Generate visualization focusing on cycles
workspace-analyzer visualize --title "Circular Dependencies" --output cycles.html

# Export cycle data for CI validation
workspace-analyzer visualize --format json --output cycles.json

# Generate Mermaid diagram for documentation
workspace-analyzer visualize --format mermaid --output cycles.mmd

Analyze Layer Architecture:

# Visualize architectural boundaries with violations highlighted
workspace-analyzer visualize --title "Architecture Review" --output architecture.html

# Focus on specific package scope
workspace-analyzer visualize --title "Core Packages" --output core.html

Performance Analysis:

# Limit visualization to high-impact nodes
workspace-analyzer visualize --max-nodes 200 --output critical-paths.html

# Export JSON for custom metrics calculation
workspace-analyzer visualize --format json --output metrics.json

CI/CD Integration:

# Generate artifacts for PR review
workspace-analyzer visualize --format both --no-open --output build/graph

# Validate no new circular dependencies
workspace-analyzer visualize --format json | jq '.statistics.totalCycles == 0'

Integration with External Tools

The JSON export format is designed for integration with custom analysis pipelines:

import {readFile} from 'node:fs/promises'

const data = JSON.parse(await readFile('graph.json', 'utf-8'))

// Find all files with critical violations
const criticalFiles = data.nodes.filter(
  node => node.highestViolationSeverity === 'critical'
)

// Identify largest cycles
const largeCycles = data.cycles
  .filter(cycle => cycle.length > 5)
  .sort((a, b) => b.length - a.length)

// Calculate dependency metrics
const avgImportsPerFile = data.statistics.totalEdges / data.statistics.totalNodes
const cycleRate = data.statistics.totalCycles / data.statistics.totalNodes

// Detect architectural hotspots
const layerViolations = data.nodes
  .filter(node => node.violations.some(v => v.ruleId === 'layer-dependency'))
  .map(node => ({
    file: node.filePath,
    layer: node.layer,
    violations: node.violations.length,
  }))
  .sort((a, b) => b.violations - a.violations)

// Find most connected nodes (potential coupling issues)
const highlyConnected = data.nodes
  .filter(node => node.importsCount + node.importedByCount > 20)
  .sort((a, b) =>
    (b.importsCount + b.importedByCount) - (a.importsCount + a.importedByCount)
  )

Programmatic API

analyzeWorkspace(path, options)

Analyzes an entire workspace for issues.

import {analyzeWorkspace} from '@bfra.me/workspace-analyzer'

const result = await analyzeWorkspace('./my-monorepo', {
  minSeverity: 'warning',
  categories: ['dependency', 'architecture'],
  onProgress: (progress) => {
    console.log(`${progress.phase}: ${progress.processed}/${progress.total}`)
  },
})

if (result.success) {
  console.log(`Found ${result.data.summary.totalIssues} issues`)
  for (const issue of result.data.issues) {
    console.log(`[${issue.severity}] ${issue.title}`)
    console.log(`  ${issue.location.filePath}:${issue.location.line}`)
    if (issue.suggestion) {
      console.log(`  Fix: ${issue.suggestion}`)
    }
  }
} else {
  console.error(`Analysis failed: ${result.error.message}`)
}

analyzePackages(path, packageNames, options)

Analyzes specific packages within a workspace.

import {analyzePackages} from '@bfra.me/workspace-analyzer'

const result = await analyzePackages('./my-monorepo', [
  '@myorg/core',
  '@myorg/utils',
])

if (result.success) {
  console.log(`Analyzed ${result.data.summary.packagesAnalyzed} packages`)
}

defineConfig(config)

Type-safe configuration helper.

import {defineConfig} from '@bfra.me/workspace-analyzer'

export default defineConfig({
  minSeverity: 'warning',
  categories: ['dependency', 'architecture'],
})

Configuration

Create a workspace-analyzer.config.ts file in your workspace root:

import {defineConfig} from '@bfra.me/workspace-analyzer'

export default defineConfig({
  // File patterns
  include: ['**/*.ts', '**/*.tsx'],
  exclude: ['**/node_modules/**', '**/lib/**', '**/dist/**'],

  // Analysis settings
  minSeverity: 'warning',
  categories: ['dependency', 'configuration', 'architecture'],

  // Performance
  cache: true,
  cacheDir: '.workspace-analyzer-cache',
  concurrency: 4,

  // Package patterns (for monorepo scanning)
  packagePatterns: ['packages/*', 'apps/*'],

  // Per-analyzer configuration
  analyzers: {
    'circular-import': {enabled: true, severity: 'error'},
    'unused-dependency': {enabled: true, severity: 'warning'},
    'config-consistency': {enabled: true},
    'tree-shaking-blocker': {enabled: true},
    'dead-code': {enabled: false}, // Disable specific analyzer
  },

  // Architectural rules
  architecture: {
    layers: [
      {name: 'domain', patterns: ['**/domain/**'], allowedImports: []},
      {name: 'application', patterns: ['**/application/**'], allowedImports: ['domain']},
      {name: 'infrastructure', patterns: ['**/infrastructure/**'], allowedImports: ['domain', 'application']},
    ],
    allowBarrelExports: ['**/index.ts'],
    enforcePublicApi: true,
  },
})

Configuration File Names

The analyzer searches for configuration in these files (in order):

  • workspace-analyzer.config.ts
  • workspace-analyzer.config.js
  • workspace-analyzer.config.mjs
  • workspace-analyzer.config.cjs

Built-in Analyzers

Configuration Analyzers

AnalyzerDescription
package-jsonValidates package.json structure, exports, and scripts
tsconfigChecks TypeScript configuration consistency
eslint-configValidates ESLint configuration patterns
build-configAnalyzes tsup/build configuration
config-consistencyCross-validates configuration across files
version-alignmentChecks dependency version consistency across packages
exports-fieldValidates exports field against actual source files

Dependency Analyzers

AnalyzerDescription
unused-dependencyDetects dependencies declared but not imported
circular-importFinds circular import chains using Tarjan's algorithm
peer-dependencyValidates peer dependency declarations
duplicate-dependencyFinds duplicate dependencies across packages

Architectural Analyzers

AnalyzerDescription
architecturalEnforces layer boundaries and import restrictions

Performance Analyzers

AnalyzerDescription
tree-shaking-blockerDetects patterns that prevent tree-shaking
dead-codeFinds unreachable/unused exports
duplicate-codeIdentifies similar code blocks via AST fingerprinting
large-dependencyFlags large dependencies that may impact bundle size

Issue Categories

CategoryDescription
configurationPackage.json, tsconfig.json, and build config issues
dependencyUnused, duplicate, or misversioned dependencies
architectureLayer violations, barrel export misuse, public API issues
performanceTree-shaking blockers, large dependencies
circular-importCircular dependency chains
unused-exportExports not used within the workspace
type-safetyTypeScript configuration issues

Severity Levels

LevelDescription
infoInformational findings, suggestions for improvement
warningPotential issues that should be reviewed
errorProblems that should be fixed
criticalSevere issues requiring immediate attention

Architectural Rules

Layer Violation Rule

Enforces architectural layer boundaries:

defineConfig({
  architecture: {
    layers: [
      {name: 'domain', patterns: ['**/domain/**'], allowedImports: []},
      {name: 'application', patterns: ['**/app/**'], allowedImports: ['domain']},
      {name: 'infrastructure', patterns: ['**/infra/**'], allowedImports: ['domain', 'application']},
    ],
  },
})

Barrel Export Rule

Controls export * usage:

defineConfig({
  architecture: {
    // Allow barrel exports only in specific files
    allowBarrelExports: ['**/index.ts'],
    // Or disable barrel exports entirely
    // allowBarrelExports: false,
  },
})

Public API Rule

Enforces explicit public API surface:

defineConfig({
  architecture: {
    enforcePublicApi: true,
  },
})

Output Formats

Console (Default)

Colorized terminal output with severity highlighting and file locations.

JSON

Machine-readable output for CI integration:

workspace-analyzer --json > report.json
{
  "issues": [],
  "summary": {
    "totalIssues": 5,
    "bySeverity": {"warning": 3, "error": 2},
    "byCategory": {"dependency": 2, "architecture": 3},
    "packagesAnalyzed": 8,
    "filesAnalyzed": 150,
    "durationMs": 2500
  }
}

Markdown

Human-readable report for documentation or PR comments:

workspace-analyzer --markdown > ANALYSIS.md

Caching

The analyzer supports incremental caching for improved performance:

defineConfig({
  cache: true,
  cacheDir: '.workspace-analyzer-cache',
  maxCacheAge: 7 * 24 * 60 * 60 * 1000, // 7 days
  hashAlgorithm: 'sha256',
})

Cache is automatically invalidated when:

  • Source files change (content hash)
  • Configuration files change
  • Analyzer versions change

CI Integration

GitHub Actions

- name: Run workspace analysis
  run: pnpm workspace-analyzer --json > analysis-report.json

- name: Check for errors
  run: |
    if jq -e '.summary.bySeverity.error > 0' analysis-report.json; then
      echo "Analysis found errors"
      exit 1
    fi

Pre-commit Hook

# package.json
{
  "lint-staged": {
    "*.{ts,tsx}": ["workspace-analyzer --categories dependency,architecture"]
  }
}

Development

# Build the package
pnpm --filter @bfra.me/workspace-analyzer build

# Run tests
pnpm --filter @bfra.me/workspace-analyzer test

# Type check
pnpm --filter @bfra.me/workspace-analyzer type-check
  • @bfra.me/es - Core utilities (Result type, async helpers)
  • @bfra.me/doc-sync - Documentation sync (shares TypeScript parsing infrastructure)
  • @bfra.me/eslint-config - ESLint configuration

License

MIT © Marcus R. Brown

Keywords

analyzer

FAQs

Package last updated on 16 May 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts