
Security News
The Hidden Blast Radius of the Axios Compromise
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.
@context-action/dependency-linker
Advanced tools
Multi-language AST-based code analysis framework with extensible plugin architecture. Supports TypeScript, Go, Java, Markdown, and custom analysis types through tree-sitter parsers.
π― Advanced Multi-Language AST Analysis Framework with Extensible Plugin Architecture
This project provides a comprehensive multi-language code analysis framework with both command-line interface and programmatic API access, built on tree-sitter for maximum performance and reliability. Supports TypeScript, Go, Java, Markdown, and custom analysis types through extensible plugin architecture.
TypeScriptAnalyzer with dependency injectionanalyzeTypeScriptFile, analyzeMarkdownFile)BatchAnalyzer with concurrency control and resource monitoringConsistent caching and path handling regardless of execution location:
./src/file.ts)// All paths normalized to project root - same cache key
await analyzer.analyzeFile('./src/component.tsx'); // From project root
await analyzer.analyzeFile('src/component.tsx'); // From project root
await analyzer.analyzeFile('/full/path/src/component.tsx'); // Absolute path
await analyzer.analyzeFile('../project/src/component.tsx'); // From subdirectory
// All generate the same normalized path: "./src/component.tsx"
π Complete Guide: Path Normalization Documentation
# λͺ¨λ μμ λ₯Ό μλμΌλ‘ λΆμνκ³ κ²°κ³Ό μμ±
./demo/run-demo.sh
ν¬ν¨λ λ°λͺ¨:
π μμΈ κ°μ΄λ: demo/README.md
demo/ λλ ν 리μλ μ€μ μ€ν κ°λ₯ν μμ νμΌλ€κ³Ό μλνλ ν
μ€νΈ μ€ν¬λ¦½νΈκ° ν¬ν¨λμ΄ μμ΅λλ€. κ° μμ λ λ€μν 볡μ‘λμ μμ‘΄μ± ν¨ν΄μ 보μ¬μ£Όμ΄ μ€μ νλ‘μ νΈμμμ νμ©λ²μ μ΄ν΄ν μ μλλ‘ κ΅¬μ±λμμ΅λλ€.
λ°λͺ¨ μ€ν κ²°κ³Ό (μ΅μ κ²μ¦):
# Install from npm
npm install @context-action/dependency-linker
# Or use locally after building
npm run build
// Multi-language analysis API
const { analyzeTypeScriptFile, GoParser, JavaParser, MarkdownParser } = require('@context-action/dependency-linker');
// TypeScript/JavaScript analysis
const result = await analyzeTypeScriptFile('./src/component.tsx');
console.log(result.dependencies);
// Go analysis
const goParser = new GoParser();
const goResult = await goParser.parseFile('./main.go');
// Java analysis
const javaParser = new JavaParser();
const javaResult = await javaParser.parseFile('./Main.java');
// Markdown link extraction
const mdParser = new MarkdownParser();
const mdResult = await mdParser.parseFile('./README.md');
# Multi-language file analysis (auto-detects language)
./analyze-file src/component.tsx # TypeScript
./analyze-file main.go # Go
./analyze-file Main.java # Java
./analyze-file README.md # Markdown
# Human-readable format
./analyze-file src/component.tsx --format summary
# Include source locations
./analyze-file src/component.tsx --include-sources
# Enhanced integrated analysis (recommended)
./analyze-file src/component.tsx --use-integrated --preset fast
# Configuration management
./analyze-file config list
./analyze-file config show --preset comprehensive
# Help
./analyze-file --help
The CLI now supports advanced configuration options for optimized analysis:
# Use predefined presets
./analyze-file src/app.tsx --use-integrated --preset fast # Fast processing
./analyze-file src/app.tsx --use-integrated --preset balanced # Balanced (default)
./analyze-file src/app.tsx --use-integrated --preset comprehensive # Maximum detail
./analyze-file src/app.tsx --use-integrated --preset lightweight # Minimal memory
./analyze-file src/app.tsx --use-integrated --preset debug # Development/debugging
# Custom configuration options
./analyze-file src/app.tsx --use-integrated \
--detail-level comprehensive \
--optimization-mode accuracy \
--enabled-views summary,table,tree \
--max-string-length 2000 \
--max-array-length 200 \
--max-depth 15
# Configuration management
./analyze-file config list # List all presets
./analyze-file config show --preset fast # Show preset details
./analyze-file config validate --preset comprehensive # Validate preset
./analyze-file config list --format json # JSON output
The tool supports multiple output formats optimized for different use cases:
# Standard formats
./analyze-file src/app.tsx --format json # Full JSON (default)
./analyze-file src/app.tsx --format text # Human-readable
./analyze-file src/app.tsx --format compact # Minified JSON
./analyze-file src/app.tsx --format summary # Key metrics summary
./analyze-file src/app.tsx --format table # Formatted table
./analyze-file src/app.tsx --format tree # Tree visualization
./analyze-file src/app.tsx --format csv # CSV for spreadsheets
./analyze-file src/app.tsx --format deps-only # Dependencies only
# Enhanced integrated formats (--use-integrated)
./analyze-file src/app.tsx --use-integrated --format minimal # Compact one-line
./analyze-file src/app.tsx --use-integrated --format report # Comprehensive report
{
"filePath": "example.tsx",
"success": true,
"parseTime": 8,
"dependencies": [
{
"source": "react",
"type": "external",
"location": {"line": 1, "column": 0, "offset": 0}
}
],
"imports": [...],
"exports": [...]
}
{
"core": {
"filePath": "example.tsx",
"success": true,
"dependencies": [...],
"performanceMetrics": {
"parseTime": 8,
"totalTime": 15,
"memoryUsage": 2.5
}
},
"views": {
"summary": {
"fileName": "example.tsx",
"totalDependencies": 5,
"externalDependencies": 3,
"internalDependencies": 2,
"analysisTime": "15ms"
},
"table": {
"headers": ["Dependency", "Type", "Location"],
"rows": [
["react", "external", "line 1"],
["./utils", "internal", "line 3"]
]
},
"tree": {
"name": "example.tsx",
"children": [
{"name": "react", "type": "external"},
{"name": "./utils", "type": "internal"}
]
}
},
"metadata": {
"generatedAt": "2024-01-15T10:30:00Z",
"analysisVersion": "2.0.0",
"configuration": {
"preset": "balanced",
"detailLevel": "standard"
}
}
}
The tool provides five built-in configuration presets optimized for different use cases:
./analyze-file src/app.tsx --use-integrated --preset fast
./analyze-file src/app.tsx --use-integrated --preset balanced
./analyze-file src/app.tsx --use-integrated --preset comprehensive
./analyze-file src/app.tsx --use-integrated --preset lightweight
./analyze-file src/app.tsx --use-integrated --preset debug
Override any preset with custom options:
./analyze-file src/app.tsx --use-integrated \
--preset balanced \
--detail-level comprehensive \
--enabled-views summary,table \
--max-string-length 1500 \
--optimization-mode accuracy
Available options:
--detail-level: minimal | standard | comprehensive--optimization-mode: speed | balanced | accuracy--enabled-views: Comma-separated list of summary,table,tree,csv,minimal--max-string-length: Maximum string length in output (default: 1000)--max-array-length: Maximum array length in output (default: 100)--max-depth: Maximum nesting depth in output (default: 10)ν¨ν€μ§ ν¬κΈ° μ΅μ νλ₯Ό μν΄ νμν λͺ¨λλ§ μ νμ μΌλ‘ μν¬νΈν μ μμ΅λλ€:
// νμλ§ νμν κ²½μ°
import { TypeScriptParser } from '@context-action/dependency-linker/dist/parsers/TypeScriptParser';
import { JavaParser } from '@context-action/dependency-linker/dist/parsers/JavaParser';
import { GoParser } from '@context-action/dependency-linker/dist/parsers/GoParser';
import { MarkdownParser } from '@context-action/dependency-linker/dist/parsers/MarkdownParser';
// μΆμΆκΈ°λ§ νμν κ²½μ°
import { DependencyExtractor } from '@context-action/dependency-linker/dist/extractors/DependencyExtractor';
// μΈν°ν리ν°λ§ νμν κ²½μ°
import { PathResolverInterpreter } from '@context-action/dependency-linker/dist/interpreters/PathResolverInterpreter';
// λͺ¨λΈλ§ νμν κ²½μ°
import { PathInfo, createPathInfo } from '@context-action/dependency-linker/dist/models/PathInfo';
import { AnalysisResult } from '@context-action/dependency-linker/dist/models/AnalysisResult';
// μλΉμ€λ§ νμν κ²½μ°
import { AnalysisEngine } from '@context-action/dependency-linker/dist/services/AnalysisEngine';
import { CacheManager } from '@context-action/dependency-linker/dist/services/CacheManager';
// μ νΈλ¦¬ν°λ§ νμν κ²½μ°
import { createLogger } from '@context-action/dependency-linker/dist/utils/logger';
import { normalizePath } from '@context-action/dependency-linker/dist/utils/PathUtils';
| λͺ¨λ μΉ΄ν κ³ λ¦¬ | μν¬νΈ κ²½λ‘ | μ£Όμ ν΄λμ€/ν¨μ |
|---|---|---|
| νμ | /dist/parsers/ | TypeScriptParser, JavaParser, GoParser, MarkdownParser |
| μΆμΆκΈ° | /dist/extractors/ | DependencyExtractor |
| μΈν°νλ¦¬ν° | /dist/interpreters/ | PathResolverInterpreter |
| λͺ¨λΈ | /dist/models/ | PathInfo, AnalysisResult, PerformanceMetrics |
| μλΉμ€ | /dist/services/ | AnalysisEngine, CacheManager, ExtractorRegistry |
| μ νΈλ¦¬ν° | /dist/utils/ | logger, PathUtils, PathResolutionUtils |
| API | /dist/api/ | factory-functions, TypeScriptAnalyzer, BatchAnalyzer |
// β μ 체 ν¨ν€μ§ μν¬νΈ (ν° λ²λ€ ν¬κΈ°)
import * as DependencyLinker from '@context-action/dependency-linker';
// β
νμν κΈ°λ₯λ§ μν¬νΈ (μ΅μ νλ λ²λ€ ν¬κΈ°)
import { TypeScriptParser } from '@context-action/dependency-linker/dist/parsers/TypeScriptParser';
import { DependencyExtractor } from '@context-action/dependency-linker/dist/extractors/DependencyExtractor';
import { createPathInfo } from '@context-action/dependency-linker/dist/models/PathInfo';
// μ΅μνμ TypeScript λΆμκΈ°λ§ μ¬μ©
const parser = new TypeScriptParser();
const extractor = new DependencyExtractor();
async function analyzeTypeScriptOnly(filePath) {
const parseResult = await parser.parse(filePath);
if (!parseResult.ast) return null;
const dependencies = extractor.extract(parseResult.ast, filePath);
const pathInfo = createPathInfo(filePath);
return { dependencies, pathInfo };
}
1. TypeScript μ μ© λΆμ (μ΅μ ν¨ν€μ§)
import { TypeScriptParser } from '@context-action/dependency-linker/dist/parsers/TypeScriptParser';
import { DependencyExtractor } from '@context-action/dependency-linker/dist/extractors/DependencyExtractor';
2. λ€μ€ μΈμ΄ λΆμ (μ νμ νμ)
import { TypeScriptParser } from '@context-action/dependency-linker/dist/parsers/TypeScriptParser';
import { JavaParser } from '@context-action/dependency-linker/dist/parsers/JavaParser';
import { GoParser } from '@context-action/dependency-linker/dist/parsers/GoParser';
3. κ²½λ‘ λΆμ μ μ© (μ νΈλ¦¬ν° μ€μ¬)
import { PathInfo, createPathInfo } from '@context-action/dependency-linker/dist/models/PathInfo';
import { normalizePath, isProjectPath } from '@context-action/dependency-linker/dist/utils/PathUtils';
4. κ³ μ±λ₯ λ°°μΉ λΆμ (μλΉμ€ μ€μ¬)
import { AnalysisEngine } from '@context-action/dependency-linker/dist/services/AnalysisEngine';
import { CacheManager } from '@context-action/dependency-linker/dist/services/CacheManager';
import { BatchAnalyzer } from '@context-action/dependency-linker/dist/api/BatchAnalyzer';
| μν¬νΈ λ°©μ | λ²λ€ ν¬κΈ° (μμΆ) | λ‘λ© μκ° | λ©λͺ¨λ¦¬ μ¬μ©λ |
|---|---|---|---|
| μ 체 ν¨ν€μ§ | ~250KB | ~50ms | ~15MB |
| TypeScriptλ§ | ~120KB | ~25ms | ~8MB |
| μ νΈλ¦¬ν°λ§ | ~45KB | ~10ms | ~3MB |
| κ°λ³ λͺ¨λ | ~30KB | ~8ms | ~2MB |
λͺ¨λ λͺ¨λλ³ μν¬νΈμμ μμ ν νμ μ§μμ μ 곡ν©λλ€:
import type { ParseResult } from '@context-action/dependency-linker/dist/parsers/ILanguageParser';
import type { DependencyExtractionResult } from '@context-action/dependency-linker/dist/extractors/DependencyExtractor';
import type { PathInfo as IPathInfo } from '@context-action/dependency-linker/dist/models/PathInfo';
// μμ ν νμ
μμ μ± λ³΄μ₯
const parser: TypeScriptParser = new TypeScriptParser();
const result: ParseResult = await parser.parse('file.ts');
Our multi-language analysis framework provides specialized capabilities for each supported language, with dedicated parsers, extractors, and interpreters working together to deliver comprehensive code analysis.
Parser: TypeScriptParser, JavaScriptParser
Primary Extractors: DependencyExtractor, EnhancedDependencyExtractor, EnhancedExportExtractor, IdentifierExtractor, ComplexityExtractor
Interpreters: DependencyAnalysisInterpreter, IdentifierAnalysisInterpreter, PathResolverInterpreter
// Named import usage analysis
import { analyzeTypeScriptFile } from '@context-action/dependency-linker';
const result = await analyzeTypeScriptFile('./src/component.tsx', {
useIntegrated: true,
preset: 'comprehensive'
});
// Access TypeScript-specific analysis
console.log('Dependencies:', result.extractedData.dependencies);
console.log('Export analysis:', result.extractedData.exports);
console.log('Usage patterns:', result.interpretedData.usageAnalysis);
Parser: MarkdownParser
Primary Extractors: MarkdownLinkExtractor
Interpreters: LinkDependencyInterpreter
// Comprehensive markdown link analysis
import { analyzeMarkdownFile } from '@context-action/dependency-linker';
const result = await analyzeMarkdownFile('./docs/README.md');
// Access markdown-specific analysis
const linkAnalysis = result.interpretedData['link-analysis'];
console.log('Total links:', linkAnalysis.summary.totalLinks);
console.log('Broken links:', linkAnalysis.summary.brokenLinks);
console.log('Security issues:', linkAnalysis.issues.filter(i => i.type === 'security_risk'));
console.log('Accessibility warnings:', linkAnalysis.issues.filter(i => i.type === 'accessibility_issue'));
Parser: JavaParser
Primary Extractors: DependencyExtractor, IdentifierExtractor, ComplexityExtractor
Interpreters: DependencyAnalysisInterpreter, PathResolverInterpreter
// Java dependency analysis
import { JavaParser, DependencyExtractor } from '@context-action/dependency-linker';
const parser = new JavaParser();
const extractor = new DependencyExtractor();
const parseResult = await parser.parse('./src/Main.java');
const dependencies = extractor.extract(parseResult.ast, './src/Main.java');
console.log('Java imports:', dependencies.filter(d => d.type === 'external'));
console.log('Internal classes:', dependencies.filter(d => d.type === 'internal'));
Parser: GoParser
Primary Extractors: DependencyExtractor, IdentifierExtractor, ComplexityExtractor
Interpreters: DependencyAnalysisInterpreter, PathResolverInterpreter
// Go dependency analysis
import { GoParser, DependencyExtractor } from '@context-action/dependency-linker';
const parser = new GoParser();
const extractor = new DependencyExtractor();
const parseResult = await parser.parse('./cmd/main.go');
const dependencies = extractor.extract(parseResult.ast, './cmd/main.go');
console.log('Go imports:', dependencies.filter(d => d.type === 'external'));
console.log('Local packages:', dependencies.filter(d => d.type === 'internal'));
All parsers share common capabilities through unified interfaces:
// Universal analysis interface
interface AnalysisResult {
filePath: string;
language: string;
extractedData: Record<string, any>; // Parser-specific data
interpretedData: Record<string, any>; // Analysis results
performanceMetrics: PerformanceMetrics;
errors: AnalysisError[];
}
// All parsers implement ILanguageParser
interface ILanguageParser {
parse(filePath: string, content?: string): Promise<ParseResult>;
supports(language: string): boolean;
getMetadata(): ParserMetadata;
}
// Multi-language project analysis
import { AnalysisEngine, ParserFactory } from '@context-action/dependency-linker';
const engine = new AnalysisEngine();
const factory = new ParserFactory();
// Analyze entire project
const projectFiles = [
'./src/index.ts', // TypeScript
'./docs/README.md', // Markdown
'./backend/Main.java', // Java
'./services/main.go' // Go
];
const results = await Promise.all(
projectFiles.map(file => engine.analyzeFile(file))
);
// Unified analysis across languages
results.forEach(result => {
console.log(`${result.language} file: ${result.filePath}`);
console.log(`Dependencies: ${Object.keys(result.extractedData).length}`);
console.log(`Performance: ${result.performanceMetrics.parseTime}ms`);
});
The EnhancedDependencyExtractor extends the basic dependency analysis to provide detailed insights into named import usage, dead code detection, and tree-shaking optimization opportunities.
// ES6/TypeScript import
import { EnhancedDependencyExtractor } from '@context-action/dependency-linker';
// CommonJS import
const { EnhancedDependencyExtractor } = require('@context-action/dependency-linker');
// Tree-shaking optimized import
import { EnhancedDependencyExtractor } from '@context-action/dependency-linker/dist/extractors/EnhancedDependencyExtractor';
import { EnhancedDependencyExtractor } from '@context-action/dependency-linker';
import { TypeScriptParser } from '@context-action/dependency-linker';
async function analyzeNamedImports() {
const code = `
import { useState, useEffect, useMemo } from 'react';
import { format, addDays } from 'date-fns';
import { debounce, throttle } from 'lodash';
function MyComponent() {
const [date, setDate] = useState(new Date());
useEffect(() => {
const tomorrow = addDays(date, 1);
console.log(format(tomorrow, 'yyyy-MM-dd'));
}, [date]);
const debouncedUpdate = debounce(() => {
setDate(new Date());
}, 1000);
// throttle is imported but never used
return <div onClick={debouncedUpdate}>Click me</div>;
}
`;
const parser = new TypeScriptParser();
const parseResult = await parser.parse('/example.tsx', code);
const extractor = new EnhancedDependencyExtractor();
const result = extractor.extractEnhanced(parseResult.ast, '/example.tsx');
console.log('π Analysis Results:');
console.log(`Total imports: ${result.usageAnalysis.totalImports}`);
console.log(`Used methods: ${result.usageAnalysis.usedImports}`);
console.log(`Unused imports: ${result.usageAnalysis.unusedImports}`);
// Detailed per-dependency analysis
result.enhancedDependencies.forEach(dep => {
console.log(`\nπ¦ ${dep.source}:`);
console.log(` Imported: ${dep.importedNames?.join(', ')}`);
console.log(` Used: ${dep.usedMethods?.map(m => `${m.methodName}(${m.callCount}x)`).join(', ') || 'None'}`);
if (dep.unusedImports?.length) {
console.log(` β οΈ Unused: ${dep.unusedImports.join(', ')}`);
}
});
}
async function analyzeTreeShaking() {
const lodashCode = `
import _ from 'lodash';
import { debounce } from 'lodash';
// Inefficient: default import usage
const uniqueData = _.uniq([1, 2, 2, 3]);
const sortedData = _.sortBy([3, 1, 2]);
// Efficient: named import usage
const debouncedFn = debounce(() => console.log('debounced'), 100);
`;
const parser = new TypeScriptParser();
const parseResult = await parser.parse('/optimization.ts', lodashCode);
const extractor = new EnhancedDependencyExtractor();
const result = extractor.extractEnhanced(parseResult.ast, '/optimization.ts');
// Tree-shaking recommendations
result.enhancedDependencies.forEach(dep => {
if (dep.source === 'lodash') {
console.log('π³ Tree-shaking Recommendations:');
if (dep.usedMethods) {
const defaultImportMethods = dep.usedMethods.filter(m => m.methodName.startsWith('_'));
if (defaultImportMethods.length > 0) {
console.log('β οΈ Inefficient default imports found:');
defaultImportMethods.forEach(method => {
const methodName = method.methodName.replace('_.', '');
console.log(` ${method.methodName} β import { ${methodName} } from 'lodash/${methodName}';`);
});
}
}
if (dep.unusedImports?.length) {
console.log(`ποΈ Remove unused: ${dep.unusedImports.join(', ')}`);
}
}
});
}
async function analyzeUsagePatterns() {
const complexCode = `
import React, { useState, useEffect, useCallback } from 'react';
import { format, isAfter, isBefore } from 'date-fns';
import { debounce, merge, isEmpty } from 'lodash';
const Dashboard = () => {
const [data, setData] = useState([]);
// High frequency: format used multiple times
const formatDate = useCallback((date) => format(date, 'yyyy-MM-dd'), []);
const formatTime = (date) => format(date, 'HH:mm');
const displayDate = (date) => format(date, 'PPP');
// Medium frequency: debounce, merge
const debouncedSearch = debounce((query) => {
const filters = merge({}, { search: query });
console.log(filters);
}, 300);
// Low frequency: isEmpty
const processData = (rawData) => {
if (isEmpty(rawData)) return [];
return rawData;
};
return <div>Dashboard</div>;
};
`;
const parser = new TypeScriptParser();
const parseResult = await parser.parse('/dashboard.tsx', complexCode);
const extractor = new EnhancedDependencyExtractor();
const result = extractor.extractEnhanced(parseResult.ast, '/dashboard.tsx');
console.log('π Usage Pattern Analysis:');
// Categorize by usage frequency
const highUsage = result.usageAnalysis.mostUsedMethods.filter(m => m.count >= 3);
const mediumUsage = result.usageAnalysis.mostUsedMethods.filter(m => m.count >= 2 && m.count < 3);
const lowUsage = result.usageAnalysis.mostUsedMethods.filter(m => m.count === 1);
console.log('π₯ High usage (3+ calls):', highUsage.map(m => `${m.method}(${m.count}x)`));
console.log('πΆ Medium usage (2 calls):', mediumUsage.map(m => `${m.method}(${m.count}x)`));
console.log('π· Low usage (1 call):', lowUsage.map(m => `${m.method}(${m.count}x)`));
// Package utilization analysis
result.enhancedDependencies.forEach(dep => {
const totalImports = dep.importedNames?.length || 0;
const usedImports = dep.usedMethods?.length || 0;
const utilizationRate = totalImports > 0 ? ((usedImports / totalImports) * 100).toFixed(1) : 0;
console.log(`π¦ ${dep.source}: ${utilizationRate}% utilization (${usedImports}/${totalImports})`);
});
}
interface EnhancedDependencyInfo {
// Basic dependency info
source: string;
type: "external" | "internal" | "relative";
location?: SourceLocation;
isTypeOnly?: boolean;
// Enhanced analysis
importedNames?: string[]; // All imported named items
usedMethods?: UsedMethodInfo[]; // Actually used methods
unusedImports?: string[]; // Imported but unused items
usageCount?: number; // Total usage count
usageLocations?: SourceLocation[]; // All usage locations
}
interface UsedMethodInfo {
methodName: string; // Method name
originalName?: string; // Original name if aliased
usageType: "call" | "property" | "reference"; // Usage type
locations: SourceLocation[]; // All usage locations
callCount: number; // Number of times called
contextInfo?: {
parentFunction?: string;
isInCondition?: boolean;
isInLoop?: boolean;
callArguments?: string[];
};
}
interface EnhancedDependencyExtractionResult extends DependencyExtractionResult {
enhancedDependencies: EnhancedDependencyInfo[];
usageAnalysis: {
totalImports: number;
usedImports: number;
unusedImports: number;
mostUsedMethods: Array<{
method: string;
count: number;
source: string;
}>;
unusedImportsList: Array<{
source: string;
unusedItems: string[];
}>;
};
}
The EnhancedExportExtractor provides comprehensive analysis of TypeScript/JavaScript export patterns, including classes, functions, variables, types, and detailed class member analysis with full test coverage (23/23 tests passing).
export { foo } from 'module' and export * patternsnpm install @context-action/dependency-linker
import {
EnhancedExportExtractor,
TypeScriptParser
} from '@context-action/dependency-linker';
// Initialize components
const parser = new TypeScriptParser();
const extractor = new EnhancedExportExtractor();
// Analyze a TypeScript file
async function analyzeExports(filePath: string) {
const parseResult = await parser.parse(filePath);
if (parseResult.ast) {
const exportData = extractor.extractExports(parseResult.ast, filePath);
console.log('π Export Summary:');
console.log(` Functions: ${exportData.statistics.functionExports}`);
console.log(` Classes: ${exportData.statistics.classExports}`);
console.log(` Variables: ${exportData.statistics.variableExports}`);
console.log(` Types: ${exportData.statistics.typeExports}`);
console.log(` Total: ${exportData.statistics.totalExports}`);
// Detailed export information
exportData.exportMethods.forEach(exp => {
console.log(`${exp.name} (${exp.exportType})`);
if (exp.parentClass) {
console.log(` ββ Class: ${exp.parentClass}`);
}
});
}
}
async function robustExportAnalysis(filePath: string) {
const parser = new TypeScriptParser();
const extractor = new EnhancedExportExtractor();
// Configure for production use
extractor.configure({
enabled: true,
timeout: 15000, // 15 seconds for large files
memoryLimit: 100 * 1024 * 1024, // 100MB memory limit
defaultOptions: {
includeLocations: true,
includeComments: false,
maxDepth: 20
}
});
try {
const parseResult = await parser.parse(filePath);
if (!parseResult.ast || parseResult.errors.length > 0) {
console.error('Parsing failed:', parseResult.errors);
return null;
}
const result = extractor.extractExports(parseResult.ast, filePath);
// Validate results
const validation = extractor.validate(result);
if (!validation.isValid) {
console.error('Validation failed:', validation.errors);
return null;
}
if (validation.warnings.length > 0) {
console.warn('Warnings:', validation.warnings);
}
return result;
} catch (error) {
console.error('Analysis failed:', error);
return null;
}
}
interface EnhancedExportExtractionResult {
exportMethods: ExportMethodInfo[]; // All export items
statistics: ExportStatistics; // Summary statistics
classes: ClassExportInfo[]; // Detailed class info
}
interface ExportMethodInfo {
name: string;
exportType: ExportType;
declarationType: DeclarationType;
location: SourceLocation;
parentClass?: string;
isAsync?: boolean;
isStatic?: boolean;
visibility?: 'public' | 'private' | 'protected';
parameters?: ParameterInfo[];
returnType?: string;
}
interface ClassExportInfo {
className: string;
location: SourceLocation;
methods: ClassMethodInfo[];
properties: ClassPropertyInfo[];
isDefaultExport: boolean;
superClass?: string;
implementsInterfaces?: string[];
}
interface ExportStatistics {
totalExports: number;
functionExports: number;
classExports: number;
variableExports: number;
typeExports: number;
defaultExports: number;
classMethodsExports: number;
classPropertiesExports: number;
}
type ExportType =
| 'function' // export function foo()
| 'class' // export class Bar
| 'variable' // export const API_URL
| 'type' // export interface User
| 'enum' // export enum Status
| 'default' // export default
| 'class_method' // class method
| 'class_property'// class property
| 're_export'; // export { foo } from 'module'
export function foo(), export async function bar()export class MyClass, export abstract class Baseexport const API_URL, export let counterexport interface User, export type Configexport enum Status { ACTIVE = 'active' }export default class, export default functionexport { foo, bar as baz }export { Utils } from './utils', export * from './types'// λΆμ κ²°κ³Ό μμ
const exportData = extractor.extractExports(parseResult.ast, filePath);
// λ°νλλ λ°μ΄ν° ꡬ쑰:
{
exportMethods: [
{
name: "getUserData",
exportType: "function",
declarationType: "named_export",
location: { line: 4, column: 0 },
isAsync: true,
parameters: [{ name: "id", optional: false, type: "string" }],
returnType: "Promise<User>"
},
{
name: "UserService",
exportType: "class",
declarationType: "named_export",
location: { line: 15, column: 0 }
},
{
name: "getUser",
exportType: "class_method",
declarationType: "class_member",
location: { line: 20, column: 2 },
parentClass: "UserService",
visibility: "public",
isAsync: true,
isStatic: false
}
],
statistics: {
totalExports: 8,
functionExports: 2,
classExports: 1,
variableExports: 2,
typeExports: 2,
defaultExports: 1,
classMethodsExports: 3,
classPropertiesExports: 1
},
classes: [
{
className: "UserService",
location: { line: 15, column: 0 },
methods: [
{
name: "getUser",
visibility: "public",
isStatic: false,
isAsync: true,
parameters: [{ name: "id", optional: false }]
}
],
properties: [
{
name: "apiUrl",
visibility: "private",
isStatic: false,
type: "string"
}
],
isDefaultExport: false,
superClass: "BaseService"
}
]
}
// 1. ν΅κ³ κΈ°λ° λΆμ
const { statistics } = exportData;
console.log(`API 볡μ‘λ: ${statistics.totalExports}κ° export`);
console.log(`ν΄λμ€ μ€μ¬λ: ${statistics.classMethodsExports}κ° λ©μλ`);
// 2. Export μ νλ³ νν°λ§
const publicAPI = exportData.exportMethods.filter(exp =>
exp.exportType === 'function' ||
(exp.exportType === 'class_method' && exp.visibility === 'public')
);
// 3. ν΄λμ€ κ΅¬μ‘° λΆμ
exportData.classes.forEach(cls => {
console.log(`ν΄λμ€ ${cls.className}:`);
console.log(`- λ©μλ ${cls.methods.length}κ°`);
console.log(`- νλ‘νΌν° ${cls.properties.length}κ°`);
if (cls.superClass) {
console.log(`- ${cls.superClass} μμ`);
}
});
// 4. μμΉ μ 보 νμ©
const exportsByLine = exportData.exportMethods
.sort((a, b) => a.location.line - b.location.line);
// 5. λΉλκΈ° ν¨μ μ°ΎκΈ°
const asyncFunctions = exportData.exportMethods.filter(exp => exp.isAsync);
console.log(`λΉλκΈ° ν¨μ: ${asyncFunctions.length}κ°`);
Memory Issues
extractor.configure({
memoryLimit: 200 * 1024 * 1024 // Increase to 200MB
});
Timeout Issues
extractor.configure({
timeout: 30000 // Increase to 30 seconds
});
Parser Errors
const parseResult = await parser.parse(filePath, sourceCode);
if (parseResult.errors.length > 0) {
console.log('Parser errors:', parseResult.errors);
}
The EnhancedExportExtractor is production-ready with comprehensive testing and provides detailed insights for code analysis, documentation generation, API discovery, and export management workflows.
const {
analyzeTypeScriptFile,
extractDependencies,
getBatchAnalysis,
analyzeDirectory
} = require('@context-action/dependency-linker');
// Standard analysis
const result = await analyzeTypeScriptFile('./src/index.ts', {
format: 'json',
includeSources: true,
parseTimeout: 10000
});
// Enhanced integrated analysis (recommended)
const integratedResult = await analyzeTypeScriptFile('./src/index.ts', {
useIntegrated: true,
preset: 'balanced',
format: 'report'
});
// Custom integrated configuration
const customResult = await analyzeTypeScriptFile('./src/index.ts', {
useIntegrated: true,
detailLevel: 'comprehensive',
optimizationMode: 'accuracy',
enabledViews: ['summary', 'table', 'tree'],
maxStringLength: 2000
});
// Batch processing with presets
const results = await getBatchAnalysis([
'./src/index.ts',
'./src/utils.ts'
], {
concurrency: 3,
useIntegrated: true,
preset: 'fast',
onProgress: (completed, total) => console.log(`${completed}/${total}`)
});
// Directory analysis with configuration
const dirResults = await analyzeDirectory('./src', {
extensions: ['.ts', '.tsx'],
ignorePatterns: ['**/*.test.ts', '**/node_modules/**'],
useIntegrated: true,
preset: 'balanced'
});
const { TypeScriptAnalyzer } = require('@context-action/dependency-linker');
// Create analyzer with options
const analyzer = new TypeScriptAnalyzer({
enableCache: true,
cacheSize: 1000,
defaultTimeout: 30000
});
// Analyze file with options
const result = await analyzer.analyzeFile('./src/index.ts', {
format: 'json',
includeSources: true
});
// Convenience methods
const dependencies = await analyzer.extractDependencies('./src/index.ts');
const imports = await analyzer.getImports('./src/index.ts');
const exports = await analyzer.getExports('./src/index.ts');
// Batch processing
const batchResult = await analyzer.analyzeFiles([
'./src/index.ts',
'./src/utils.ts'
], {
concurrency: 5,
continueOnError: true
});
// Clean up
analyzer.clearCache();
const { TypeScriptAnalyzer, resetFactoryAnalyzers, resetSharedAnalyzer } = require('@context-action/dependency-linker');
const analyzer = new TypeScriptAnalyzer();
// κ°λ³ λΆμκΈ° μΊμ μ΄κΈ°ν
analyzer.clearCache();
// ν©ν 리 곡μ λΆμκΈ° μ΄κΈ°ν (κΆμ₯: ν
μ€νΈ νκ²½)
resetFactoryAnalyzers();
resetSharedAnalyzer();
// μΊμ ν΅κ³ νμΈ
const stats = analyzer.getCacheStats();
console.log(`Cache size: ${stats.size}, hits: ${stats.hits}`);
const { BatchAnalyzer } = require('@context-action/dependency-linker/dist/api/BatchAnalyzer');
const batchAnalyzer = new BatchAnalyzer(analyzer, {
maxConcurrency: 5,
enableResourceMonitoring: true,
memoryLimit: 512 // MB
});
const result = await batchAnalyzer.processBatch(filePaths, {
continueOnError: true,
onProgress: (completed, total) => {
console.log(`Progress: ${completed}/${total}`);
},
onFileError: (filePath, error) => {
console.log(`Error in ${filePath}: ${error.message}`);
}
});
console.log('Resource metrics:', batchAnalyzer.getResourceMetrics());
batchAnalyzer.dispose();
The examples/ directory contains production-ready integration examples:
basic-usage.js: Simple API usage patterns and error handlingbatch-processing.js: Advanced batch processing with progress trackingwebpack-plugin.js: Custom Webpack plugin for build-time analysisvscode-extension.js: VS Code extension development example# Run any example
node examples/basic-usage.js
node examples/batch-processing.js
π See examples/README.md for detailed guides and integration patterns.
# νλ‘μ νΈμ λͺ¨λ μΈλΆ ν¨ν€μ§ μ°ΎκΈ°
find src -name "*.ts" -o -name "*.tsx" | while read file; do
./analyze-file "$file" | jq '.dependencies[] | select(.type == "external") | .source'
done | sort | uniq
// webpack.config.jsμμ μ¬μ©
const { execSync } = require('child_process');
function analyzeDependencies(filePath) {
const output = execSync(`./analyze-file ${filePath}`, { encoding: 'utf8' });
return JSON.parse(output).dependencies;
}
# GitHub Actionsμμ μμ‘΄μ± κ²μ¬
- name: Check dependencies
run: ./analyze-file src/index.ts | jq '.dependencies[].source'
# μμ‘΄μ± μ€μΉ (μ΄λ―Έ μλ£λ¨)
npm install
# tree-sitter 리λΉλ (νμν κ²½μ°)
npm rebuild tree-sitter
# νλ‘μ νΈ λΉλ (μ΄λ―Έ μλ£λ¨)
npm run build
# μ½λ νμ§ κ²μ¬ (Biome)
npm run lint
# μ½λ ν¬λ§·ν
npm run format
# CLI μ€ν κΆν νμΈ
chmod +x analyze-file
# ν
μ€νΈ μ€ν
npm test
# μ¬μ© μμ!
./analyze-file --help
λͺ¨λ μμΈ λ¬Έμλ docs/ λλ ν 리μμ μ°Ύμ μ μμ΅λλ€:
PathInfo μμ€ν μ λͺ¨λ μ£Όμ μ΄μ체μ μμ μ΅μ νλ μ±λ₯μ μ 곡ν©λλ€:
C:\, D:\ λ± Windows λλΌμ΄λΈ μ²λ¦¬\\server\share\file λ€νΈμν¬ κ²½λ‘ μ§μ%USERPROFILE%, %PROGRAMFILES% λ± μλ νμ₯Windows λ°λͺ¨ μ€ν:
npx tsx demo-windows-pathinfo.ts
.app ν¨ν€μ§ ꡬ쑰 μΈμ λ° λΆμ~/Documents ν λλ ν 리 μλ νμ₯/Applications, /Library, /System νΉλ³ μ²λ¦¬/opt/homebrew ν¨ν€μ§ κ²½λ‘ μ§μmacOS λ°λͺ¨ μ€ν:
npx tsx demo-macos-pathinfo.ts
/usr, /etc, /var λ± νμ€ κ²½λ‘Linux λ°λͺ¨ μ€ν:
npx tsx demo-linux-pathinfo.ts
λͺ¨λ νλ«νΌμ κΈ°λ₯μ ν λ²μ 체ν:
npx tsx demo-multi-os-pathinfo.ts
// νλ«νΌ κ°μ§ λ° μ΅μ ν
const { createPathInfo } = require('./src/lib/index');
// Windows
const windowsPath = createPathInfo('C:\\Users\\Name\\file.txt');
console.log(windowsPath.separator); // '\'
// macOS
const macosPath = createPathInfo('/Applications/App.app/Contents/MacOS/App');
console.log(macosPath.isWithinProject); // false (μμ€ν
μ±)
// Linux
const linuxPath = createPathInfo('/usr/local/bin/tool');
console.log(linuxPath.depth); // 4
# λͺ¨λ νλ«νΌ νΈνμ± ν
μ€νΈ
npx tsx test-cross-platform-paths.ts
# νλ«νΌλ³ μ±λ₯ λ²€μΉλ§ν¬
npm run benchmark:cross-platform
MIT λΌμ΄μ μ€λ‘ μ 곡λ©λλ€.
β
κ°λ° μλ£: λͺ¨λ κΈ°λ₯ ꡬν λ° ν
μ€νΈ μλ£
π λ°°ν¬ μ€λΉ: λΉλ μ±κ³΅, νμ
μλ¬ ν΄κ²° μλ£
π¦ μ¬μ© κ°λ₯: CLI λꡬ μ¦μ μ€ν κ°λ₯
π§ μ μ§λ³΄μ: μμ μ μΈ μ½λλ² μ΄μ€, ν¬κ΄μ ν
μ€νΈ
π― μ€λΉ μλ£! λ°λ‘ μ¬μ©νμΈμ!
FAQs
Multi-language AST-based code analysis framework with extensible plugin architecture. Supports TypeScript, Go, Java, Markdown, and custom analysis types through tree-sitter parsers.
We found that @context-action/dependency-linker demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.Β It has 1 open source maintainer collaborating on the project.
Did you know?

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.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the projectβs GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.