@bfra.me/workspace-analyzer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +402 -0
- package/lib/chunk-4LSFAAZW.js +1 -0
- package/lib/chunk-JDF7DQ4V.js +27 -0
- package/lib/chunk-WOJ4C7N7.js +7122 -0
- package/lib/cli.d.ts +1 -0
- package/lib/cli.js +318 -0
- package/lib/index.d.ts +3701 -0
- package/lib/index.js +1262 -0
- package/lib/types/index.d.ts +146 -0
- package/lib/types/index.js +28 -0
- package/package.json +89 -0
- package/src/analyzers/analyzer.ts +201 -0
- package/src/analyzers/architectural-analyzer.ts +304 -0
- package/src/analyzers/build-config-analyzer.ts +334 -0
- package/src/analyzers/circular-import-analyzer.ts +463 -0
- package/src/analyzers/config-consistency-analyzer.ts +335 -0
- package/src/analyzers/dead-code-analyzer.ts +565 -0
- package/src/analyzers/duplicate-code-analyzer.ts +626 -0
- package/src/analyzers/duplicate-dependency-analyzer.ts +381 -0
- package/src/analyzers/eslint-config-analyzer.ts +281 -0
- package/src/analyzers/exports-field-analyzer.ts +324 -0
- package/src/analyzers/index.ts +388 -0
- package/src/analyzers/large-dependency-analyzer.ts +535 -0
- package/src/analyzers/package-json-analyzer.ts +349 -0
- package/src/analyzers/peer-dependency-analyzer.ts +275 -0
- package/src/analyzers/tree-shaking-analyzer.ts +623 -0
- package/src/analyzers/tsconfig-analyzer.ts +382 -0
- package/src/analyzers/unused-dependency-analyzer.ts +356 -0
- package/src/analyzers/version-alignment-analyzer.ts +308 -0
- package/src/api/analyze-workspace.ts +245 -0
- package/src/api/index.ts +11 -0
- package/src/cache/cache-manager.ts +495 -0
- package/src/cache/cache-schema.ts +247 -0
- package/src/cache/change-detector.ts +169 -0
- package/src/cache/file-hasher.ts +65 -0
- package/src/cache/index.ts +47 -0
- package/src/cli/commands/analyze.ts +240 -0
- package/src/cli/commands/index.ts +5 -0
- package/src/cli/index.ts +61 -0
- package/src/cli/types.ts +65 -0
- package/src/cli/ui.ts +213 -0
- package/src/cli.ts +9 -0
- package/src/config/defaults.ts +183 -0
- package/src/config/index.ts +81 -0
- package/src/config/loader.ts +270 -0
- package/src/config/merger.ts +229 -0
- package/src/config/schema.ts +263 -0
- package/src/core/incremental-analyzer.ts +462 -0
- package/src/core/index.ts +34 -0
- package/src/core/orchestrator.ts +416 -0
- package/src/graph/dependency-graph.ts +408 -0
- package/src/graph/index.ts +19 -0
- package/src/index.ts +417 -0
- package/src/parser/config-parser.ts +491 -0
- package/src/parser/import-extractor.ts +340 -0
- package/src/parser/index.ts +54 -0
- package/src/parser/typescript-parser.ts +95 -0
- package/src/performance/bundle-estimator.ts +444 -0
- package/src/performance/index.ts +27 -0
- package/src/reporters/console-reporter.ts +355 -0
- package/src/reporters/index.ts +49 -0
- package/src/reporters/json-reporter.ts +273 -0
- package/src/reporters/markdown-reporter.ts +349 -0
- package/src/reporters/reporter.ts +399 -0
- package/src/rules/builtin-rules.ts +709 -0
- package/src/rules/index.ts +52 -0
- package/src/rules/rule-engine.ts +409 -0
- package/src/scanner/index.ts +18 -0
- package/src/scanner/workspace-scanner.ts +403 -0
- package/src/types/index.ts +176 -0
- package/src/types/result.ts +19 -0
- package/src/utils/index.ts +7 -0
- package/src/utils/pattern-matcher.ts +48 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main public API for workspace analysis.
|
|
3
|
+
*
|
|
4
|
+
* Provides the `analyzeWorkspace()` function as the primary entry point
|
|
5
|
+
* for programmatic workspace analysis.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {MergedConfig} from '../config/merger'
|
|
9
|
+
import type {AnalysisProgress, AnalysisResult} from '../types/index'
|
|
10
|
+
import type {Result} from '../types/result'
|
|
11
|
+
|
|
12
|
+
import path from 'node:path'
|
|
13
|
+
|
|
14
|
+
import {loadConfig} from '../config/loader'
|
|
15
|
+
import {mergeConfig} from '../config/merger'
|
|
16
|
+
import {createOrchestrator, type OrchestratorError} from '../core/orchestrator'
|
|
17
|
+
import {err, ok} from '../types/result'
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Options for the analyzeWorkspace function.
|
|
21
|
+
*/
|
|
22
|
+
export interface AnalyzeWorkspaceOptions {
|
|
23
|
+
/** Glob patterns for files to include */
|
|
24
|
+
readonly include?: readonly string[]
|
|
25
|
+
/** Glob patterns for files to exclude */
|
|
26
|
+
readonly exclude?: readonly string[]
|
|
27
|
+
/** Minimum severity level to report */
|
|
28
|
+
readonly minSeverity?: 'info' | 'warning' | 'error' | 'critical'
|
|
29
|
+
/** Categories of issues to check (empty means all) */
|
|
30
|
+
readonly categories?: readonly (
|
|
31
|
+
| 'configuration'
|
|
32
|
+
| 'dependency'
|
|
33
|
+
| 'architecture'
|
|
34
|
+
| 'performance'
|
|
35
|
+
| 'circular-import'
|
|
36
|
+
| 'unused-export'
|
|
37
|
+
| 'type-safety'
|
|
38
|
+
)[]
|
|
39
|
+
/** Enable incremental analysis caching */
|
|
40
|
+
readonly cache?: boolean
|
|
41
|
+
/** Custom rules configuration */
|
|
42
|
+
readonly rules?: Record<string, unknown>
|
|
43
|
+
/** Glob patterns for package locations */
|
|
44
|
+
readonly packagePatterns?: readonly string[]
|
|
45
|
+
/** Maximum parallel analysis operations */
|
|
46
|
+
readonly concurrency?: number
|
|
47
|
+
/** Directory for analysis cache files */
|
|
48
|
+
readonly cacheDir?: string
|
|
49
|
+
/** Maximum cache age in milliseconds */
|
|
50
|
+
readonly maxCacheAge?: number
|
|
51
|
+
/** Hash algorithm for file content */
|
|
52
|
+
readonly hashAlgorithm?: 'sha256' | 'md5'
|
|
53
|
+
/** Path to workspace-analyzer.config.ts file */
|
|
54
|
+
readonly configPath?: string
|
|
55
|
+
/** Callback for progress reporting */
|
|
56
|
+
readonly onProgress?: (progress: AnalysisProgress) => void
|
|
57
|
+
/** Per-analyzer configuration */
|
|
58
|
+
readonly analyzers?: Record<
|
|
59
|
+
string,
|
|
60
|
+
{
|
|
61
|
+
enabled?: boolean
|
|
62
|
+
severity?: 'info' | 'warning' | 'error' | 'critical'
|
|
63
|
+
options?: Record<string, unknown>
|
|
64
|
+
}
|
|
65
|
+
>
|
|
66
|
+
/** Architectural analysis rules */
|
|
67
|
+
readonly architecture?: {
|
|
68
|
+
layers?: {
|
|
69
|
+
name: string
|
|
70
|
+
patterns: string[]
|
|
71
|
+
allowedImports: string[]
|
|
72
|
+
}[]
|
|
73
|
+
allowBarrelExports?: boolean | string[]
|
|
74
|
+
enforcePublicApi?: boolean
|
|
75
|
+
}
|
|
76
|
+
/** Enable verbose logging */
|
|
77
|
+
readonly verbose?: boolean
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Error codes for workspace analysis.
|
|
82
|
+
*/
|
|
83
|
+
export type AnalyzeWorkspaceErrorCode =
|
|
84
|
+
| 'CONFIG_ERROR'
|
|
85
|
+
| 'SCAN_ERROR'
|
|
86
|
+
| 'ANALYSIS_ERROR'
|
|
87
|
+
| 'INVALID_PATH'
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Error that occurred during workspace analysis.
|
|
91
|
+
*/
|
|
92
|
+
export interface AnalyzeWorkspaceError {
|
|
93
|
+
readonly code: AnalyzeWorkspaceErrorCode
|
|
94
|
+
readonly message: string
|
|
95
|
+
readonly cause?: unknown
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Converts orchestrator error to analyze workspace error.
|
|
100
|
+
*/
|
|
101
|
+
function toAnalyzeError(error: OrchestratorError): AnalyzeWorkspaceError {
|
|
102
|
+
const codeMap: Record<string, AnalyzeWorkspaceErrorCode> = {
|
|
103
|
+
SCAN_FAILED: 'SCAN_ERROR',
|
|
104
|
+
NO_PACKAGES: 'SCAN_ERROR',
|
|
105
|
+
ANALYSIS_FAILED: 'ANALYSIS_ERROR',
|
|
106
|
+
INVALID_CONFIG: 'CONFIG_ERROR',
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return {
|
|
110
|
+
code: codeMap[error.code] ?? 'ANALYSIS_ERROR',
|
|
111
|
+
message: error.message,
|
|
112
|
+
cause: error.cause,
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Analyzes a workspace for configuration, dependency, and architectural issues.
|
|
118
|
+
*
|
|
119
|
+
* This is the main entry point for programmatic workspace analysis.
|
|
120
|
+
*
|
|
121
|
+
* @param workspacePath - Path to the workspace root directory
|
|
122
|
+
* @param options - Analysis options
|
|
123
|
+
* @returns Result containing analysis results or an error
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* ```ts
|
|
127
|
+
* import {analyzeWorkspace} from '@bfra.me/workspace-analyzer'
|
|
128
|
+
*
|
|
129
|
+
* const result = await analyzeWorkspace('./my-monorepo', {
|
|
130
|
+
* minSeverity: 'warning',
|
|
131
|
+
* categories: ['dependency', 'architecture'],
|
|
132
|
+
* onProgress: (progress) => {
|
|
133
|
+
* console.log(`${progress.phase}: ${progress.processed}/${progress.total}`)
|
|
134
|
+
* },
|
|
135
|
+
* })
|
|
136
|
+
*
|
|
137
|
+
* if (result.success) {
|
|
138
|
+
* console.log(`Found ${result.data.summary.totalIssues} issues`)
|
|
139
|
+
* for (const issue of result.data.issues) {
|
|
140
|
+
* console.log(`[${issue.severity}] ${issue.title}`)
|
|
141
|
+
* }
|
|
142
|
+
* } else {
|
|
143
|
+
* console.error(`Analysis failed: ${result.error.message}`)
|
|
144
|
+
* }
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
export async function analyzeWorkspace(
|
|
148
|
+
workspacePath: string,
|
|
149
|
+
options: AnalyzeWorkspaceOptions = {},
|
|
150
|
+
): Promise<Result<AnalysisResult, AnalyzeWorkspaceError>> {
|
|
151
|
+
const resolvedPath = path.resolve(workspacePath)
|
|
152
|
+
|
|
153
|
+
// Load configuration from file if not explicitly provided
|
|
154
|
+
const configResult = await loadConfig(resolvedPath, options.configPath)
|
|
155
|
+
|
|
156
|
+
if (!configResult.success) {
|
|
157
|
+
return err({
|
|
158
|
+
code: 'CONFIG_ERROR',
|
|
159
|
+
message: configResult.error.message,
|
|
160
|
+
cause: configResult.error.cause,
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Merge configuration from all sources
|
|
165
|
+
const mergedConfig: MergedConfig = mergeConfig(
|
|
166
|
+
configResult.data?.config,
|
|
167
|
+
options as Parameters<typeof mergeConfig>[1],
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
// Create orchestrator and run analysis
|
|
171
|
+
const orchestrator = createOrchestrator({
|
|
172
|
+
workspacePath: resolvedPath,
|
|
173
|
+
config: mergedConfig,
|
|
174
|
+
onProgress: options.onProgress,
|
|
175
|
+
verbose: options.verbose,
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
const result = await orchestrator.analyzeAll()
|
|
179
|
+
|
|
180
|
+
if (!result.success) {
|
|
181
|
+
return err(toAnalyzeError(result.error))
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return ok(result.data)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Analyzes specific packages within a workspace.
|
|
189
|
+
*
|
|
190
|
+
* @param workspacePath - Path to the workspace root directory
|
|
191
|
+
* @param packageNames - Names of packages to analyze
|
|
192
|
+
* @param options - Analysis options
|
|
193
|
+
* @returns Result containing analysis results or an error
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* ```ts
|
|
197
|
+
* import {analyzePackages} from '@bfra.me/workspace-analyzer'
|
|
198
|
+
*
|
|
199
|
+
* const result = await analyzePackages('./my-monorepo', ['@myorg/core', '@myorg/utils'])
|
|
200
|
+
*
|
|
201
|
+
* if (result.success) {
|
|
202
|
+
* console.log(`Analyzed ${result.data.summary.packagesAnalyzed} packages`)
|
|
203
|
+
* }
|
|
204
|
+
* ```
|
|
205
|
+
*/
|
|
206
|
+
export async function analyzePackages(
|
|
207
|
+
workspacePath: string,
|
|
208
|
+
packageNames: readonly string[],
|
|
209
|
+
options: AnalyzeWorkspaceOptions = {},
|
|
210
|
+
): Promise<Result<AnalysisResult, AnalyzeWorkspaceError>> {
|
|
211
|
+
const resolvedPath = path.resolve(workspacePath)
|
|
212
|
+
|
|
213
|
+
// Load configuration from file if not explicitly provided
|
|
214
|
+
const configResult = await loadConfig(resolvedPath, options.configPath)
|
|
215
|
+
|
|
216
|
+
if (!configResult.success) {
|
|
217
|
+
return err({
|
|
218
|
+
code: 'CONFIG_ERROR',
|
|
219
|
+
message: configResult.error.message,
|
|
220
|
+
cause: configResult.error.cause,
|
|
221
|
+
})
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Merge configuration from all sources
|
|
225
|
+
const mergedConfig: MergedConfig = mergeConfig(
|
|
226
|
+
configResult.data?.config,
|
|
227
|
+
options as Parameters<typeof mergeConfig>[1],
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
// Create orchestrator and run analysis
|
|
231
|
+
const orchestrator = createOrchestrator({
|
|
232
|
+
workspacePath: resolvedPath,
|
|
233
|
+
config: mergedConfig,
|
|
234
|
+
onProgress: options.onProgress,
|
|
235
|
+
verbose: options.verbose,
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
const result = await orchestrator.analyzePackages(packageNames)
|
|
239
|
+
|
|
240
|
+
if (!result.success) {
|
|
241
|
+
return err(toAnalyzeError(result.error))
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return ok(result.data)
|
|
245
|
+
}
|
package/src/api/index.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public API exports for workspace analyzer.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export {analyzePackages, analyzeWorkspace} from './analyze-workspace'
|
|
6
|
+
|
|
7
|
+
export type {
|
|
8
|
+
AnalyzeWorkspaceError,
|
|
9
|
+
AnalyzeWorkspaceErrorCode,
|
|
10
|
+
AnalyzeWorkspaceOptions,
|
|
11
|
+
} from './analyze-workspace'
|