fcis 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/.plans/001-fcis-analyzer.md +832 -0
- package/.plans/002-fcis-analyzer-improvements.md +205 -0
- package/README.md +272 -0
- package/TECHNICAL.md +386 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1836 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +709 -0
- package/dist/index.js +1845 -0
- package/dist/index.js.map +1 -0
- package/package.json +47 -0
- package/pnpm-workspace.yaml +0 -0
- package/src/analyzer.ts +266 -0
- package/src/classification/classifier.ts +156 -0
- package/src/classification/derive-status.ts +171 -0
- package/src/classification/quality-scorer.ts +481 -0
- package/src/cli.ts +286 -0
- package/src/detection/detect-markers.ts +480 -0
- package/src/detection/markers.ts +332 -0
- package/src/extraction/extract-functions.ts +570 -0
- package/src/extraction/extractor.ts +188 -0
- package/src/index.ts +111 -0
- package/src/reporting/report-console.ts +416 -0
- package/src/reporting/report-json.ts +232 -0
- package/src/scoring/scorer.ts +504 -0
- package/src/types.ts +248 -0
- package/tests/classifier.test.ts +480 -0
- package/tests/derive-status.test.ts +464 -0
- package/tests/detect-markers.test.ts +639 -0
- package/tests/extractor.test.ts +155 -0
- package/tests/integration.test.ts +706 -0
- package/tests/quality-scorer.test.ts +650 -0
- package/tests/scorer.test.ts +768 -0
- package/tsconfig.json +34 -0
- package/tsup.config.ts +17 -0
- package/vendor/ts-morph/.editorconfig +10 -0
- package/vendor/ts-morph/.gitattributes +11 -0
- package/vendor/ts-morph/.github/CODE_OF_CONDUCT.md +77 -0
- package/vendor/ts-morph/.github/ISSUE_TEMPLATE/bug_report.md +29 -0
- package/vendor/ts-morph/.github/ISSUE_TEMPLATE/custom.md +4 -0
- package/vendor/ts-morph/.github/ISSUE_TEMPLATE/feature_request.md +18 -0
- package/vendor/ts-morph/.github/workflows/ci.yml +50 -0
- package/vendor/ts-morph/.github/workflows/publish.yml +53 -0
- package/vendor/ts-morph/.vscode/settings.json +10 -0
- package/vendor/ts-morph/CONTRIBUTING.md +23 -0
- package/vendor/ts-morph/DEVELOPMENT.md +32 -0
- package/vendor/ts-morph/LICENSE +21 -0
- package/vendor/ts-morph/deno.json +8 -0
- package/vendor/ts-morph/deno.lock +1233 -0
- package/vendor/ts-morph/docs/CNAME +1 -0
- package/vendor/ts-morph/docs/Gemfile +2 -0
- package/vendor/ts-morph/docs/_config.yml +5 -0
- package/vendor/ts-morph/docs/_layouts/default.html +159 -0
- package/vendor/ts-morph/docs/_script-templates/main.ts +116 -0
- package/vendor/ts-morph/docs/assets/css/style.scss +212 -0
- package/vendor/ts-morph/docs/details/ambient.md +38 -0
- package/vendor/ts-morph/docs/details/async.md +31 -0
- package/vendor/ts-morph/docs/details/classes.md +314 -0
- package/vendor/ts-morph/docs/details/comment-ranges.md +7 -0
- package/vendor/ts-morph/docs/details/comments.md +122 -0
- package/vendor/ts-morph/docs/details/decorators.md +119 -0
- package/vendor/ts-morph/docs/details/documentation.md +73 -0
- package/vendor/ts-morph/docs/details/enums.md +117 -0
- package/vendor/ts-morph/docs/details/exports.md +308 -0
- package/vendor/ts-morph/docs/details/expressions.md +46 -0
- package/vendor/ts-morph/docs/details/functions.md +150 -0
- package/vendor/ts-morph/docs/details/generators.md +27 -0
- package/vendor/ts-morph/docs/details/identifiers.md +79 -0
- package/vendor/ts-morph/docs/details/imports.md +191 -0
- package/vendor/ts-morph/docs/details/index.md +52 -0
- package/vendor/ts-morph/docs/details/initializers.md +40 -0
- package/vendor/ts-morph/docs/details/interfaces.md +218 -0
- package/vendor/ts-morph/docs/details/literals.md +20 -0
- package/vendor/ts-morph/docs/details/modifiers.md +38 -0
- package/vendor/ts-morph/docs/details/modules.md +113 -0
- package/vendor/ts-morph/docs/details/namespaces.md +7 -0
- package/vendor/ts-morph/docs/details/object-literal-expressions.md +106 -0
- package/vendor/ts-morph/docs/details/parameters.md +64 -0
- package/vendor/ts-morph/docs/details/signatures.md +41 -0
- package/vendor/ts-morph/docs/details/source-files.md +292 -0
- package/vendor/ts-morph/docs/details/type-aliases.md +34 -0
- package/vendor/ts-morph/docs/details/type-parameters.md +72 -0
- package/vendor/ts-morph/docs/details/types.md +254 -0
- package/vendor/ts-morph/docs/details/variables.md +110 -0
- package/vendor/ts-morph/docs/emitting.md +151 -0
- package/vendor/ts-morph/docs/index.md +25 -0
- package/vendor/ts-morph/docs/manipulation/code-writer.md +20 -0
- package/vendor/ts-morph/docs/manipulation/formatting.md +76 -0
- package/vendor/ts-morph/docs/manipulation/index.md +136 -0
- package/vendor/ts-morph/docs/manipulation/order.md +14 -0
- package/vendor/ts-morph/docs/manipulation/performance.md +222 -0
- package/vendor/ts-morph/docs/manipulation/removing.md +31 -0
- package/vendor/ts-morph/docs/manipulation/renaming.md +106 -0
- package/vendor/ts-morph/docs/manipulation/settings.md +76 -0
- package/vendor/ts-morph/docs/manipulation/structures.md +117 -0
- package/vendor/ts-morph/docs/manipulation/transforms.md +84 -0
- package/vendor/ts-morph/docs/metrics/performance.json +4 -0
- package/vendor/ts-morph/docs/navigation/ambient-modules.md +22 -0
- package/vendor/ts-morph/docs/navigation/compiler-nodes.md +82 -0
- package/vendor/ts-morph/docs/navigation/directories.md +287 -0
- package/vendor/ts-morph/docs/navigation/example.md +50 -0
- package/vendor/ts-morph/docs/navigation/finding-references.md +53 -0
- package/vendor/ts-morph/docs/navigation/getting-source-files.md +59 -0
- package/vendor/ts-morph/docs/navigation/images/getChildrenVsForEachChild.gif +0 -0
- package/vendor/ts-morph/docs/navigation/index.md +94 -0
- package/vendor/ts-morph/docs/navigation/language-service.md +23 -0
- package/vendor/ts-morph/docs/navigation/program.md +25 -0
- package/vendor/ts-morph/docs/navigation/type-checker.md +33 -0
- package/vendor/ts-morph/docs/setup/adding-source-files.md +145 -0
- package/vendor/ts-morph/docs/setup/ast-viewers.md +46 -0
- package/vendor/ts-morph/docs/setup/diagnostics.md +109 -0
- package/vendor/ts-morph/docs/setup/file-system.md +106 -0
- package/vendor/ts-morph/docs/setup/images/atom-ast.png +0 -0
- package/vendor/ts-morph/docs/setup/images/atom-ast_small.png +0 -0
- package/vendor/ts-morph/docs/setup/images/atom-command-palette.png +0 -0
- package/vendor/ts-morph/docs/setup/images/atom-file.png +0 -0
- package/vendor/ts-morph/docs/setup/images/ts-ast-viewer.png +0 -0
- package/vendor/ts-morph/docs/setup/index.md +94 -0
- package/vendor/ts-morph/docs/utilities.md +55 -0
- package/vendor/ts-morph/dprint.json +23 -0
- package/vendor/ts-morph/package.json +30 -0
- package/vendor/ts-morph/packages/bootstrap/LICENSE +21 -0
- package/vendor/ts-morph/packages/bootstrap/lib/ts-morph-bootstrap.d.ts +397 -0
- package/vendor/ts-morph/packages/bootstrap/package.json +46 -0
- package/vendor/ts-morph/packages/bootstrap/readme.md +200 -0
- package/vendor/ts-morph/packages/common/LICENSE +21 -0
- package/vendor/ts-morph/packages/common/lib/ts-morph-common.d.ts +1082 -0
- package/vendor/ts-morph/packages/common/lib/typescript.d.ts +11439 -0
- package/vendor/ts-morph/packages/common/package.json +65 -0
- package/vendor/ts-morph/packages/common/readme.md +5 -0
- package/vendor/ts-morph/packages/scripts/changeTypeScriptVersion.ts +28 -0
- package/vendor/ts-morph/packages/scripts/createDeclarationProject.ts +47 -0
- package/vendor/ts-morph/packages/scripts/deps.ts +2 -0
- package/vendor/ts-morph/packages/scripts/execScript.ts +31 -0
- package/vendor/ts-morph/packages/scripts/folders.ts +11 -0
- package/vendor/ts-morph/packages/scripts/getDevCompilerVersions.ts +19 -0
- package/vendor/ts-morph/packages/scripts/mod.ts +7 -0
- package/vendor/ts-morph/packages/scripts/utils/Memoize.ts +36 -0
- package/vendor/ts-morph/packages/scripts/utils/forEachTypeText.ts +23 -0
- package/vendor/ts-morph/packages/scripts/utils/makeConstructorsPrivate.ts +26 -0
- package/vendor/ts-morph/packages/scripts/utils/mod.ts +4 -0
- package/vendor/ts-morph/packages/scripts/utils/printDiagnostics.ts +10 -0
- package/vendor/ts-morph/packages/ts-morph/LICENSE +21 -0
- package/vendor/ts-morph/packages/ts-morph/lib/ts-morph.d.ts +11198 -0
- package/vendor/ts-morph/packages/ts-morph/package.json +78 -0
- package/vendor/ts-morph/packages/ts-morph/readme.md +111 -0
- package/vendor/ts-morph/readme.md +14 -0
- package/vendor/ts-morph/rfcs/README.md +13 -0
- package/vendor/ts-morph/rfcs/RFC-0001 - Inserting Into Statements Handling Comments.md +181 -0
- package/vendor/ts-morph/tsconfig.common.json +17 -0
- package/vitest.config.ts +16 -0
package/src/cli.ts
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* FCIS CLI - Command Line Interface
|
|
4
|
+
*
|
|
5
|
+
* Entry point for the FCIS analyzer. Supports running analysis against
|
|
6
|
+
* a TypeScript project and outputting results in various formats.
|
|
7
|
+
*
|
|
8
|
+
* Exit codes:
|
|
9
|
+
* - 0: Success, all thresholds passed
|
|
10
|
+
* - 1: Analysis completed but below threshold
|
|
11
|
+
* - 2: Configuration error
|
|
12
|
+
* - 3: Analysis error (zero files could be analyzed)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { cli } from 'cleye'
|
|
16
|
+
import { z } from 'zod'
|
|
17
|
+
import chalk from 'chalk'
|
|
18
|
+
import * as fs from 'node:fs'
|
|
19
|
+
import * as path from 'node:path'
|
|
20
|
+
|
|
21
|
+
import { analyze, checkThresholds } from './analyzer.js'
|
|
22
|
+
import { stripJsonComments } from './extraction/extractor.js'
|
|
23
|
+
import {
|
|
24
|
+
printConsoleReport,
|
|
25
|
+
generateSummaryLine,
|
|
26
|
+
} from './reporting/report-console.js'
|
|
27
|
+
import { generateJsonReport, writeJsonReport } from './reporting/report-json.js'
|
|
28
|
+
import type { AnalyzerConfig } from './types.js'
|
|
29
|
+
|
|
30
|
+
const EXIT_SUCCESS = 0
|
|
31
|
+
const EXIT_THRESHOLD_FAILED = 1
|
|
32
|
+
const EXIT_CONFIG_ERROR = 2
|
|
33
|
+
const EXIT_ANALYSIS_ERROR = 3
|
|
34
|
+
|
|
35
|
+
const ThresholdSchema = z.number().min(0).max(100)
|
|
36
|
+
|
|
37
|
+
const argv = cli({
|
|
38
|
+
name: 'fcis',
|
|
39
|
+
version: '0.1.0',
|
|
40
|
+
flags: {
|
|
41
|
+
json: {
|
|
42
|
+
type: Boolean,
|
|
43
|
+
description: 'Output JSON to stdout (for piping/parsing)',
|
|
44
|
+
default: false,
|
|
45
|
+
},
|
|
46
|
+
output: {
|
|
47
|
+
type: String,
|
|
48
|
+
alias: 'o',
|
|
49
|
+
description: 'Write JSON report to file',
|
|
50
|
+
},
|
|
51
|
+
minHealth: {
|
|
52
|
+
type: Number,
|
|
53
|
+
description: 'Exit with code 1 if project health < N (0-100)',
|
|
54
|
+
},
|
|
55
|
+
minPurity: {
|
|
56
|
+
type: Number,
|
|
57
|
+
description: 'Exit with code 1 if purity < N (0-100)',
|
|
58
|
+
},
|
|
59
|
+
minQuality: {
|
|
60
|
+
type: Number,
|
|
61
|
+
description: 'Exit with code 1 if impurity quality < N (0-100)',
|
|
62
|
+
},
|
|
63
|
+
files: {
|
|
64
|
+
type: String,
|
|
65
|
+
alias: 'f',
|
|
66
|
+
description:
|
|
67
|
+
'Analyze only files matching glob (for incremental/pre-commit)',
|
|
68
|
+
},
|
|
69
|
+
format: {
|
|
70
|
+
type: String,
|
|
71
|
+
description: 'Output format: console (default), json, summary',
|
|
72
|
+
default: 'console',
|
|
73
|
+
},
|
|
74
|
+
quiet: {
|
|
75
|
+
type: Boolean,
|
|
76
|
+
alias: 'q',
|
|
77
|
+
description: 'Suppress all output except errors; rely on exit code',
|
|
78
|
+
default: false,
|
|
79
|
+
},
|
|
80
|
+
verbose: {
|
|
81
|
+
type: Boolean,
|
|
82
|
+
alias: 'v',
|
|
83
|
+
description: 'Show per-file scores and all classified functions',
|
|
84
|
+
default: false,
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
parameters: ['<tsconfig>'],
|
|
88
|
+
help: {
|
|
89
|
+
description:
|
|
90
|
+
'Analyze TypeScript code for Functional Core, Imperative Shell patterns',
|
|
91
|
+
examples: [
|
|
92
|
+
'fcis analyze tsconfig.json',
|
|
93
|
+
'fcis analyze tsconfig.json --min-health 70',
|
|
94
|
+
'fcis analyze tsconfig.json --format json --output report.json',
|
|
95
|
+
'fcis analyze tsconfig.json --files "src/services/**/*.ts"',
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
async function main(): Promise<void> {
|
|
101
|
+
const { flags, _: args } = argv
|
|
102
|
+
|
|
103
|
+
const tsconfigPath = args.tsconfig
|
|
104
|
+
|
|
105
|
+
// Validate tsconfig exists
|
|
106
|
+
if (!tsconfigPath) {
|
|
107
|
+
console.error(chalk.red('Error: tsconfig path is required'))
|
|
108
|
+
console.error('Usage: fcis <tsconfig> [options]')
|
|
109
|
+
process.exit(EXIT_CONFIG_ERROR)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const absoluteTsconfigPath = path.resolve(tsconfigPath)
|
|
113
|
+
if (!fs.existsSync(absoluteTsconfigPath)) {
|
|
114
|
+
console.error(
|
|
115
|
+
chalk.red(`Error: tsconfig.json not found at: ${absoluteTsconfigPath}`),
|
|
116
|
+
)
|
|
117
|
+
process.exit(EXIT_CONFIG_ERROR)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Validate tsconfig is valid JSON (strip comments first since TypeScript allows them)
|
|
121
|
+
try {
|
|
122
|
+
const content = fs.readFileSync(absoluteTsconfigPath, 'utf-8')
|
|
123
|
+
const strippedContent = stripJsonComments(content)
|
|
124
|
+
JSON.parse(strippedContent)
|
|
125
|
+
} catch (e) {
|
|
126
|
+
console.error(
|
|
127
|
+
chalk.red(`Error: Invalid tsconfig.json at ${absoluteTsconfigPath}`),
|
|
128
|
+
)
|
|
129
|
+
console.error(e instanceof Error ? e.message : String(e))
|
|
130
|
+
process.exit(EXIT_CONFIG_ERROR)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Validate threshold values
|
|
134
|
+
if (flags.minHealth !== undefined) {
|
|
135
|
+
const result = ThresholdSchema.safeParse(flags.minHealth)
|
|
136
|
+
if (!result.success) {
|
|
137
|
+
console.error(
|
|
138
|
+
chalk.red('Error: --min-health must be a number between 0 and 100'),
|
|
139
|
+
)
|
|
140
|
+
process.exit(EXIT_CONFIG_ERROR)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (flags.minPurity !== undefined) {
|
|
145
|
+
const result = ThresholdSchema.safeParse(flags.minPurity)
|
|
146
|
+
if (!result.success) {
|
|
147
|
+
console.error(
|
|
148
|
+
chalk.red('Error: --min-purity must be a number between 0 and 100'),
|
|
149
|
+
)
|
|
150
|
+
process.exit(EXIT_CONFIG_ERROR)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (flags.minQuality !== undefined) {
|
|
155
|
+
const result = ThresholdSchema.safeParse(flags.minQuality)
|
|
156
|
+
if (!result.success) {
|
|
157
|
+
console.error(
|
|
158
|
+
chalk.red('Error: --min-quality must be a number between 0 and 100'),
|
|
159
|
+
)
|
|
160
|
+
process.exit(EXIT_CONFIG_ERROR)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Validate format
|
|
165
|
+
const validFormats = ['console', 'json', 'summary']
|
|
166
|
+
if (!validFormats.includes(flags.format)) {
|
|
167
|
+
console.error(
|
|
168
|
+
chalk.red(`Error: --format must be one of: ${validFormats.join(', ')}`),
|
|
169
|
+
)
|
|
170
|
+
process.exit(EXIT_CONFIG_ERROR)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Validate output path if provided
|
|
174
|
+
if (flags.output) {
|
|
175
|
+
const outputDir = path.dirname(path.resolve(flags.output))
|
|
176
|
+
if (!fs.existsSync(outputDir)) {
|
|
177
|
+
try {
|
|
178
|
+
fs.mkdirSync(outputDir, { recursive: true })
|
|
179
|
+
} catch (e) {
|
|
180
|
+
console.error(
|
|
181
|
+
chalk.red(`Error: Cannot create output directory: ${outputDir}`),
|
|
182
|
+
)
|
|
183
|
+
process.exit(EXIT_CONFIG_ERROR)
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Run analysis
|
|
189
|
+
try {
|
|
190
|
+
if (!flags.quiet && flags.format === 'console') {
|
|
191
|
+
console.log(chalk.gray(`Analyzing ${process.cwd()}...`))
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Build config with proper undefined handling
|
|
195
|
+
const config: AnalyzerConfig = {
|
|
196
|
+
tsconfigPath: absoluteTsconfigPath,
|
|
197
|
+
format: flags.format as 'console' | 'json' | 'summary',
|
|
198
|
+
quiet: flags.quiet,
|
|
199
|
+
verbose: flags.verbose,
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Only add optional properties if they are defined
|
|
203
|
+
if (flags.files !== undefined) {
|
|
204
|
+
config.filesGlob = flags.files
|
|
205
|
+
}
|
|
206
|
+
if (flags.minHealth !== undefined) {
|
|
207
|
+
config.minHealth = flags.minHealth
|
|
208
|
+
}
|
|
209
|
+
if (flags.minPurity !== undefined) {
|
|
210
|
+
config.minPurity = flags.minPurity
|
|
211
|
+
}
|
|
212
|
+
if (flags.minQuality !== undefined) {
|
|
213
|
+
config.minQuality = flags.minQuality
|
|
214
|
+
}
|
|
215
|
+
if (flags.output !== undefined) {
|
|
216
|
+
config.outputPath = flags.output
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const score = await analyze(config)
|
|
220
|
+
|
|
221
|
+
// Output results based on format
|
|
222
|
+
if (!flags.quiet) {
|
|
223
|
+
if (flags.json || flags.format === 'json') {
|
|
224
|
+
console.log(generateJsonReport(score, { pretty: true }))
|
|
225
|
+
} else if (flags.format === 'summary') {
|
|
226
|
+
console.log(generateSummaryLine(score))
|
|
227
|
+
} else {
|
|
228
|
+
printConsoleReport(score, { verbose: flags.verbose })
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Write JSON to file if requested
|
|
233
|
+
if (flags.output) {
|
|
234
|
+
writeJsonReport(score, flags.output, { pretty: true })
|
|
235
|
+
if (!flags.quiet && flags.format !== 'json') {
|
|
236
|
+
console.log(chalk.green(`Report written to: ${flags.output}`))
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Check thresholds - build object only with defined values
|
|
241
|
+
const thresholdConfig: {
|
|
242
|
+
minHealth?: number
|
|
243
|
+
minPurity?: number
|
|
244
|
+
minQuality?: number
|
|
245
|
+
} = {}
|
|
246
|
+
|
|
247
|
+
if (flags.minHealth !== undefined) {
|
|
248
|
+
thresholdConfig.minHealth = flags.minHealth
|
|
249
|
+
}
|
|
250
|
+
if (flags.minPurity !== undefined) {
|
|
251
|
+
thresholdConfig.minPurity = flags.minPurity
|
|
252
|
+
}
|
|
253
|
+
if (flags.minQuality !== undefined) {
|
|
254
|
+
thresholdConfig.minQuality = flags.minQuality
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
const thresholdResult = checkThresholds(score, thresholdConfig)
|
|
258
|
+
|
|
259
|
+
if (!thresholdResult.passed) {
|
|
260
|
+
if (!flags.quiet) {
|
|
261
|
+
console.log()
|
|
262
|
+
console.log(chalk.red.bold('Threshold check failed:'))
|
|
263
|
+
for (const failure of thresholdResult.failures) {
|
|
264
|
+
console.log(chalk.red(` ✗ ${failure}`))
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
process.exit(EXIT_THRESHOLD_FAILED)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
process.exit(EXIT_SUCCESS)
|
|
271
|
+
} catch (error) {
|
|
272
|
+
if (!flags.quiet) {
|
|
273
|
+
console.error(chalk.red('Analysis failed:'))
|
|
274
|
+
console.error(error instanceof Error ? error.message : String(error))
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Check if it's a "no files" error
|
|
278
|
+
if (error instanceof Error && error.message.includes('No source files')) {
|
|
279
|
+
process.exit(EXIT_ANALYSIS_ERROR)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
process.exit(EXIT_ANALYSIS_ERROR)
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
main()
|