vibertest 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/LICENSE +661 -0
- package/README.md +429 -0
- package/bin/vibertest.js +2 -0
- package/dist/chunk-TUE4IPY7.js +124 -0
- package/dist/chunk-TUE4IPY7.js.map +1 -0
- package/dist/defaults-E5ZXCZVE.js +12 -0
- package/dist/defaults-E5ZXCZVE.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +6639 -0
- package/dist/index.js.map +1 -0
- package/package.json +76 -0
package/README.md
ADDED
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<pre>
|
|
4
|
+
██╗ ██╗██╗██████╗ ███████╗██████╗
|
|
5
|
+
██║ ██║██║██╔══██╗██╔════╝██╔══██╗
|
|
6
|
+
██║ ██║██║██████╔╝█████╗ ██████╔╝
|
|
7
|
+
╚██╗ ██╔╝██║██╔══██╗██╔══╝ ██╔══██╗
|
|
8
|
+
╚████╔╝ ██║██████╔╝███████╗██║ ██║
|
|
9
|
+
╚═══╝ ╚═╝╚═════╝ ╚══════╝╚═╝ ╚═╝
|
|
10
|
+
TEST
|
|
11
|
+
</pre>
|
|
12
|
+
|
|
13
|
+
**Your AI writes code. ViberTest makes sure it doesn't suck.**
|
|
14
|
+
|
|
15
|
+
*Got sick of vibecoders' mess, so I vibecoded this.*
|
|
16
|
+
|
|
17
|
+
A CLI tool + Web Dashboard that analyzes JavaScript/TypeScript projects to detect quality issues commonly produced by AI-assisted development (vibecoding).
|
|
18
|
+
|
|
19
|
+
**[Full Documentation →](https://vibertest.chyste.dev/docs)**
|
|
20
|
+
|
|
21
|
+
[Getting Started](#getting-started) · [24 Rules](#the-24-rules) · [Grading System](#grading-system) · [Dashboard](#web-dashboard) · [Configuration](#configuration)
|
|
22
|
+
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## The Problem
|
|
28
|
+
|
|
29
|
+
AI coding tools (Cursor, Copilot, v0, Bolt) generate code that **works** but is often:
|
|
30
|
+
|
|
31
|
+
- Copy-pasted across files with no abstraction
|
|
32
|
+
- Missing error handling, tests, and proper architecture
|
|
33
|
+
- Full of `console.log`, generic variable names, and TODO comments
|
|
34
|
+
- Using outdated patterns (`var`, class components, callback hell)
|
|
35
|
+
- Dumping everything into god files with circular dependencies
|
|
36
|
+
|
|
37
|
+
**ViberTest catches all of this.** It scans your project, scores it 0-100, and tells you exactly what to fix.
|
|
38
|
+
|
|
39
|
+
## Getting Started
|
|
40
|
+
|
|
41
|
+
### Prerequisites
|
|
42
|
+
|
|
43
|
+
- **Node.js** >= 20.0.0
|
|
44
|
+
- **pnpm** >= 10.x
|
|
45
|
+
|
|
46
|
+
### Installation
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# Clone the repository
|
|
50
|
+
git clone https://github.com/Chyste/vibertest.git
|
|
51
|
+
cd vibertest
|
|
52
|
+
|
|
53
|
+
# Install dependencies
|
|
54
|
+
pnpm install
|
|
55
|
+
|
|
56
|
+
# Build all packages
|
|
57
|
+
pnpm run build
|
|
58
|
+
|
|
59
|
+
# Link the CLI globally
|
|
60
|
+
cd packages/cli
|
|
61
|
+
pnpm link --global
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Run Your First Scan
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Scan the current directory
|
|
68
|
+
vibertest scan .
|
|
69
|
+
|
|
70
|
+
# Scan a specific project
|
|
71
|
+
vibertest scan ~/my-project
|
|
72
|
+
|
|
73
|
+
# Export results as JSON
|
|
74
|
+
vibertest scan . --format json --output report.json
|
|
75
|
+
|
|
76
|
+
# Run only specific rules
|
|
77
|
+
vibertest scan . --rules oversized-files,dead-code,ai-smell
|
|
78
|
+
|
|
79
|
+
# Silent mode (no terminal output, just JSON)
|
|
80
|
+
vibertest scan . --format json --silent
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Initialize Config
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# Create a .vibertestrc.json in your project
|
|
87
|
+
vibertest init
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## The 24 Rules
|
|
93
|
+
|
|
94
|
+
ViberTest analyzes your codebase with **24 rules** organized by what they detect. Each rule is specifically designed to catch patterns that AI tools produce when developers accept generated code without review.
|
|
95
|
+
|
|
96
|
+
### Architecture & Structure
|
|
97
|
+
|
|
98
|
+
| Rule | Severity | What It Detects |
|
|
99
|
+
|------|----------|-----------------|
|
|
100
|
+
| **Oversized Files** | Medium | Files exceeding line threshold. AI dumps everything in one file. |
|
|
101
|
+
| **God File** | High | Files with >10 exports, mixed concerns, and high import fan-in. The "does everything" file. |
|
|
102
|
+
| **Bloated Barrel** | Medium/High | `index.ts` files with >15 re-exports. Kills tree-shaking and slows bundlers. |
|
|
103
|
+
| **Circular Dependencies** | High | Import cycles (A → B → C → A) detected via DFS graph traversal. Causes runtime errors. |
|
|
104
|
+
| **Separation of Concerns** | Medium | `fetch()` in React components, SQL outside data layers, business logic in route handlers. |
|
|
105
|
+
|
|
106
|
+
### Code Quality
|
|
107
|
+
|
|
108
|
+
| Rule | Severity | What It Detects |
|
|
109
|
+
|------|----------|-----------------|
|
|
110
|
+
| **Dead Code & Unused Exports** | High | Exported functions, types, and variables that are never imported anywhere. |
|
|
111
|
+
| **Code Duplication** | High/Medium | 6+ duplicate lines across different files. Copy-paste without abstraction. |
|
|
112
|
+
| **Poor Maintainability** | High/Medium/Low | Long functions (>50 lines), too many parameters (>4), excessive imports (>10), magic numbers. |
|
|
113
|
+
| **Missing Error Handling** | High/Medium | `async` functions without try/catch, unhandled Promise chains, empty/swallowed catch blocks, console-only error handling. |
|
|
114
|
+
| **Missing Tests** | High/Medium | No test files, low test-to-source ratio, empty tests, trivial assertions (`expect(true).toBe(true)`), generic test names, skipped/todo tests. |
|
|
115
|
+
|
|
116
|
+
### Style & Patterns
|
|
117
|
+
|
|
118
|
+
| Rule | Severity | What It Detects |
|
|
119
|
+
|------|----------|-----------------|
|
|
120
|
+
| **Style Inconsistency** | Medium | Mixed camelCase/snake_case, function declarations vs arrows, single vs double quotes, semicolons. |
|
|
121
|
+
| **Pattern Inconsistency** | Medium | Mixed styling approaches (Tailwind + CSS Modules + inline styles in the same project). |
|
|
122
|
+
| **Obsolete Patterns** | Medium | `var` declarations, `.then()` chains (3+ deep), React class components, CommonJS in `.ts` files, `arguments` keyword. |
|
|
123
|
+
|
|
124
|
+
### Dependencies & Config
|
|
125
|
+
|
|
126
|
+
| Rule | Severity | What It Detects |
|
|
127
|
+
|------|----------|-----------------|
|
|
128
|
+
| **Unused Dependencies** | High/Medium | Packages in `package.json` that are never imported in your code. |
|
|
129
|
+
| **Duplicate Dependencies** | High | Multiple packages for the same purpose: axios + fetch, jest + vitest, moment + dayjs, etc. |
|
|
130
|
+
| **Hardcoded Secrets** | Critical | API keys, tokens, passwords, and connection strings hardcoded in source files. |
|
|
131
|
+
|
|
132
|
+
### AI-Specific Smells
|
|
133
|
+
|
|
134
|
+
| Rule | Severity | What It Detects |
|
|
135
|
+
|------|----------|-----------------|
|
|
136
|
+
| **AI Smell** | High/Medium/Info | `console.log` in production, generic names (`data`, `result`, `temp`) as info-level, obvious comments, `utils.ts` dumping grounds, placeholder logic (`throw new Error('Not implemented')`) as high. |
|
|
137
|
+
| **Abandoned TODO/FIXME** | Medium/Low | Unresolved `TODO`, `FIXME`, `HACK`, `XXX` comments — unfinished work that shipped anyway. |
|
|
138
|
+
|
|
139
|
+
### Security & Compliance
|
|
140
|
+
|
|
141
|
+
| Rule | Severity | What It Detects |
|
|
142
|
+
|------|----------|-----------------|
|
|
143
|
+
| **Security Anti-Patterns** | Critical/High | SQL injection risks, `eval()` with dynamic input, hardcoded credentials, CORS wildcards, sensitive data in localStorage, `innerHTML` with user input, `Math.random()` for security, `dangerouslySetInnerHTML`. |
|
|
144
|
+
| **Missing Compliance Pages** | Critical/High | Missing Terms of Service, Privacy Policy, unresolved legal placeholders (`[Company Name]`), analytics without cookie consent, auth without account deletion. |
|
|
145
|
+
| **Accessibility Anti-Patterns** | Medium/Low | Images without `alt` text, non-semantic click handlers (`<div onClick>`), form inputs without labels, missing ARIA landmarks, non-descriptive link text ("click here"). |
|
|
146
|
+
|
|
147
|
+
### Ship-Readiness
|
|
148
|
+
|
|
149
|
+
| Rule | Severity | What It Detects |
|
|
150
|
+
|------|----------|-----------------|
|
|
151
|
+
| **Missing Project Standards** | High/Medium/Low | Missing `tsconfig.json`, no linter config (ESLint/Biome), missing `.gitignore`, `.env` without `.env.example`, no formatter config, missing `.editorconfig`, no `README.md`. |
|
|
152
|
+
| **Missing Production Basics** | Medium/Low | Generic page titles ("Create Next App"), missing meta description, default/missing favicon, no Open Graph tags, missing custom 404 page, no `robots.txt`, no `sitemap.xml`. |
|
|
153
|
+
| **React Performance** | High/Medium/Low | Array index as key, problematic `useEffect` patterns, `setState` in loops, nested component definitions, inline objects/functions in JSX, spreading all props. *(Disabled by default — very noisy)* |
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Grading System
|
|
158
|
+
|
|
159
|
+
ViberTest scores your project **0 to 100** and assigns a letter grade:
|
|
160
|
+
|
|
161
|
+
| Grade | Score | Meaning |
|
|
162
|
+
|-------|-------|---------|
|
|
163
|
+
| **A** | 90–100 | Excellent — Clean, well-structured code |
|
|
164
|
+
| **B** | 75–89 | Good — Minor issues, solid foundation |
|
|
165
|
+
| **C** | 60–74 | Needs Work — Noticeable quality gaps |
|
|
166
|
+
| **D** | 40–59 | Poor — Significant structural problems |
|
|
167
|
+
| **F** | 0–39 | Critical — Major issues across the board |
|
|
168
|
+
|
|
169
|
+
### How Scoring Works
|
|
170
|
+
|
|
171
|
+
Each issue deducts penalty points based on severity:
|
|
172
|
+
|
|
173
|
+
| Severity | Penalty | Scaling |
|
|
174
|
+
|----------|---------|---------|
|
|
175
|
+
| **Critical** | 5 pts | Linear — every instance fully counts |
|
|
176
|
+
| **High** | 3 pts | Linear — every instance fully counts |
|
|
177
|
+
| **Medium** | 1 pt | Diminishing returns — `log₂(count + 1)` per rule |
|
|
178
|
+
| **Low** | 0.5 pts | Diminishing returns — `log₂(count + 1)` per rule |
|
|
179
|
+
| **Info** | 0 pts | No penalty |
|
|
180
|
+
|
|
181
|
+
**Why diminishing returns?** Having 15 medium issues from the same rule shouldn't crush your score the same as 15 critical issues. The logarithmic curve means the first few instances of a medium/low rule matter, but additional ones have decreasing impact. This keeps the scoring fair while still rewarding cleanup.
|
|
182
|
+
|
|
183
|
+
**Example:** 15 medium issues from one rule = **4 points** (not 15). But 5 critical issues = **25 points** (every one counts).
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Web Dashboard
|
|
188
|
+
|
|
189
|
+
ViberTest includes a built-in web dashboard for visualizing scan results. Upload a JSON report and get interactive charts, file rankings, and a visual health thermometer.
|
|
190
|
+
|
|
191
|
+
<!-- Replace with your actual screenshot -->
|
|
192
|
+
<div align="center">
|
|
193
|
+
<img src="docs/assets/dashboard.png" alt="ViberTest Web Dashboard" width="800" />
|
|
194
|
+
</div>
|
|
195
|
+
|
|
196
|
+
### Features
|
|
197
|
+
|
|
198
|
+
- **Health Thermometer** — Vertical segmented gauge showing your score at a glance
|
|
199
|
+
- **Severity Breakdown** — Pie chart of issues by severity level
|
|
200
|
+
- **Rule Distribution** — Bar chart showing which rules found the most issues
|
|
201
|
+
- **File Ranking** — Top problematic files sorted by issue count
|
|
202
|
+
- **Scan Metadata** — Project name, scan duration, file count, timestamp
|
|
203
|
+
|
|
204
|
+
### Running the Dashboard Locally
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
# From the project root
|
|
208
|
+
cd packages/web
|
|
209
|
+
|
|
210
|
+
# Development mode (with hot reload)
|
|
211
|
+
pnpm dev
|
|
212
|
+
|
|
213
|
+
# Open http://localhost:3000
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### How to Use
|
|
217
|
+
|
|
218
|
+
1. **Generate a JSON report** from the CLI:
|
|
219
|
+
```bash
|
|
220
|
+
vibertest scan ~/my-project --format json --output report.json
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
2. **Open the dashboard** at `http://localhost:3000`
|
|
224
|
+
|
|
225
|
+
3. **Upload the JSON file** — drag & drop or click to browse
|
|
226
|
+
|
|
227
|
+
4. **Explore the results** — interactive charts, file rankings, and detailed breakdowns
|
|
228
|
+
|
|
229
|
+
### Production Build
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
cd packages/web
|
|
233
|
+
pnpm build
|
|
234
|
+
pnpm start
|
|
235
|
+
# Dashboard available at http://localhost:3000
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Configuration
|
|
241
|
+
|
|
242
|
+
Create a `.vibertestrc.json` in your project root to customize ViberTest:
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
vibertest init
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Default Configuration
|
|
249
|
+
|
|
250
|
+
```jsonc
|
|
251
|
+
{
|
|
252
|
+
"rules": {
|
|
253
|
+
// Architecture & Structure
|
|
254
|
+
"oversized-files": { "enabled": true },
|
|
255
|
+
"god-file": { "enabled": true },
|
|
256
|
+
"bloated-barrel": { "enabled": true },
|
|
257
|
+
"circular-deps": { "enabled": true },
|
|
258
|
+
"separation-of-concerns": { "enabled": true },
|
|
259
|
+
|
|
260
|
+
// Code Quality
|
|
261
|
+
"dead-code": { "enabled": true },
|
|
262
|
+
"code-duplication": { "enabled": true },
|
|
263
|
+
"poor-maintainability": { "enabled": true },
|
|
264
|
+
"missing-error-handling": { "enabled": true },
|
|
265
|
+
"missing-tests": { "enabled": true },
|
|
266
|
+
|
|
267
|
+
// Style & Patterns
|
|
268
|
+
"style-inconsistency": { "enabled": true },
|
|
269
|
+
"pattern-inconsistency": { "enabled": true },
|
|
270
|
+
"obsolete-patterns": { "enabled": true },
|
|
271
|
+
|
|
272
|
+
// Dependencies & Config
|
|
273
|
+
"unused-deps": { "enabled": true },
|
|
274
|
+
"duplicate-deps": { "enabled": true },
|
|
275
|
+
"hardcoded-secrets": { "enabled": true },
|
|
276
|
+
|
|
277
|
+
// AI-Specific Smells
|
|
278
|
+
"ai-smell": { "enabled": true },
|
|
279
|
+
"abandoned-todo": { "enabled": true },
|
|
280
|
+
|
|
281
|
+
// Security & Compliance
|
|
282
|
+
"security-antipatterns": { "enabled": true },
|
|
283
|
+
"missing-compliance": { "enabled": true },
|
|
284
|
+
"accessibility": { "enabled": true },
|
|
285
|
+
|
|
286
|
+
// Ship-Readiness
|
|
287
|
+
"missing-project-standards": { "enabled": true },
|
|
288
|
+
"missing-production-basics": { "enabled": true },
|
|
289
|
+
"react-performance": { "enabled": false } // Disabled by default (very noisy)
|
|
290
|
+
},
|
|
291
|
+
"ignore": [
|
|
292
|
+
"node_modules", "dist", "build",
|
|
293
|
+
".next", "coverage", ".turbo", ".git"
|
|
294
|
+
],
|
|
295
|
+
"thresholds": {
|
|
296
|
+
"maxFileLines": 300,
|
|
297
|
+
"maxFunctionLines": 50,
|
|
298
|
+
"maxFunctionParams": 4,
|
|
299
|
+
"maxImports": 10,
|
|
300
|
+
"minTestRatio": 0.05
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Disabling Rules
|
|
306
|
+
|
|
307
|
+
```jsonc
|
|
308
|
+
{
|
|
309
|
+
"rules": {
|
|
310
|
+
// Disable rules you don't need
|
|
311
|
+
"pattern-inconsistency": { "enabled": false },
|
|
312
|
+
"style-inconsistency": { "enabled": false }
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Custom Thresholds
|
|
318
|
+
|
|
319
|
+
```jsonc
|
|
320
|
+
{
|
|
321
|
+
"thresholds": {
|
|
322
|
+
"maxFileLines": 500, // Allow larger files
|
|
323
|
+
"maxFunctionLines": 80, // Allow longer functions
|
|
324
|
+
"maxFunctionParams": 5, // Allow more parameters
|
|
325
|
+
"maxImports": 15, // Allow more imports
|
|
326
|
+
"minTestRatio": 0.1 // Lower test coverage requirement
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
### Ignoring Files
|
|
332
|
+
|
|
333
|
+
```jsonc
|
|
334
|
+
{
|
|
335
|
+
"ignore": [
|
|
336
|
+
"node_modules", "dist", "build",
|
|
337
|
+
"generated", // Skip generated code
|
|
338
|
+
"legacy", // Skip legacy modules
|
|
339
|
+
"**/*.generated.ts" // Skip generated files
|
|
340
|
+
]
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## CI Integration
|
|
347
|
+
|
|
348
|
+
ViberTest exits with code **1** when issues are found, making it easy to integrate into CI pipelines:
|
|
349
|
+
|
|
350
|
+
```yaml
|
|
351
|
+
# GitHub Actions example
|
|
352
|
+
- name: Run ViberTest
|
|
353
|
+
run: vibertest scan . --format json --output vibertest-report.json
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
```bash
|
|
357
|
+
# Or in any CI script
|
|
358
|
+
vibertest scan . || echo "ViberTest found issues"
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## Project Structure
|
|
364
|
+
|
|
365
|
+
```
|
|
366
|
+
vibertest/
|
|
367
|
+
├── packages/
|
|
368
|
+
│ ├── cli/ # CLI tool (@vibertest/cli)
|
|
369
|
+
│ │ ├── src/
|
|
370
|
+
│ │ │ ├── rules/ # 24 analysis rules
|
|
371
|
+
│ │ │ ├── scorer/ # Scoring engine with diminishing returns
|
|
372
|
+
│ │ │ ├── scanner/ # File collection & orchestration
|
|
373
|
+
│ │ │ ├── reporter/ # Terminal & JSON output
|
|
374
|
+
│ │ │ └── config/ # Config loading & validation (Zod)
|
|
375
|
+
│ │ └── bin/ # CLI entry point
|
|
376
|
+
│ ├── shared/ # Shared types & constants (@vibertest/shared)
|
|
377
|
+
│ └── web/ # Web Dashboard (@vibertest/web)
|
|
378
|
+
│ └── src/
|
|
379
|
+
│ ├── app/ # Next.js 15 App Router pages
|
|
380
|
+
│ ├── components/ # Dashboard UI components
|
|
381
|
+
│ ├── stores/ # Zustand state management
|
|
382
|
+
│ └── lib/ # Utilities
|
|
383
|
+
├── docs/ # Specs & design system
|
|
384
|
+
├── turbo.json # Turborepo config
|
|
385
|
+
├── biome.json # Linting & formatting
|
|
386
|
+
└── pnpm-workspace.yaml # Monorepo workspace
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
## Tech Stack
|
|
390
|
+
|
|
391
|
+
| Package | Stack |
|
|
392
|
+
|---------|-------|
|
|
393
|
+
| **CLI** | TypeScript, Commander.js, Chalk, Ora, Zod 3, Cosmiconfig |
|
|
394
|
+
| **Shared** | TypeScript, tsup |
|
|
395
|
+
| **Web** | Next.js 15, React 19, Tailwind CSS 4, Zustand 5, Recharts, Lucide Icons |
|
|
396
|
+
| **Tooling** | pnpm workspaces, Turborepo, Biome, Vitest |
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
## Self-Scan Results
|
|
401
|
+
|
|
402
|
+
ViberTest analyzes itself and scores **88/100 (Grade B)** with 24 rules enabled:
|
|
403
|
+
|
|
404
|
+
```
|
|
405
|
+
HEALTH SCORE
|
|
406
|
+
|
|
407
|
+
██████╗
|
|
408
|
+
██╔══██╗
|
|
409
|
+
██████╔╝
|
|
410
|
+
██╔══██╗
|
|
411
|
+
██████╔╝
|
|
412
|
+
╚═════╝
|
|
413
|
+
|
|
414
|
+
88/100 ██████████████████████████░░░░ Good
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
419
|
+
## License
|
|
420
|
+
|
|
421
|
+
AGPL-3.0 — See [LICENSE](LICENSE) for details.
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
<div align="center">
|
|
426
|
+
|
|
427
|
+
**ViberTest** — Stop shipping AI slop.
|
|
428
|
+
|
|
429
|
+
</div>
|
package/bin/vibertest.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
+
}) : x)(function(x) {
|
|
5
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
// ../shared/dist/index.js
|
|
10
|
+
var SEVERITY = {
|
|
11
|
+
CRITICAL: "critical",
|
|
12
|
+
HIGH: "high",
|
|
13
|
+
MEDIUM: "medium",
|
|
14
|
+
LOW: "low",
|
|
15
|
+
INFO: "info"
|
|
16
|
+
};
|
|
17
|
+
var GRADE = {
|
|
18
|
+
A: "A",
|
|
19
|
+
B: "B",
|
|
20
|
+
C: "C",
|
|
21
|
+
D: "D",
|
|
22
|
+
F: "F"
|
|
23
|
+
};
|
|
24
|
+
var GRADE_LABEL = {
|
|
25
|
+
[GRADE.A]: "Excellent",
|
|
26
|
+
[GRADE.B]: "Good",
|
|
27
|
+
[GRADE.C]: "Needs Work",
|
|
28
|
+
[GRADE.D]: "Poor",
|
|
29
|
+
[GRADE.F]: "Critical"
|
|
30
|
+
};
|
|
31
|
+
var RULE_ID = {
|
|
32
|
+
OVERSIZED_FILES: "oversized-files",
|
|
33
|
+
DEAD_CODE: "dead-code",
|
|
34
|
+
HARDCODED_SECRETS: "hardcoded-secrets",
|
|
35
|
+
UNUSED_DEPS: "unused-deps",
|
|
36
|
+
MISSING_TESTS: "missing-tests",
|
|
37
|
+
PATTERN_INCONSISTENCY: "pattern-inconsistency",
|
|
38
|
+
POOR_MAINTAINABILITY: "poor-maintainability",
|
|
39
|
+
MISSING_ERROR_HANDLING: "missing-error-handling",
|
|
40
|
+
ABANDONED_TODO: "abandoned-todo",
|
|
41
|
+
BLOATED_BARREL: "bloated-barrel",
|
|
42
|
+
STYLE_INCONSISTENCY: "style-inconsistency",
|
|
43
|
+
DUPLICATE_DEPS: "duplicate-deps",
|
|
44
|
+
GOD_FILE: "god-file",
|
|
45
|
+
SEPARATION_OF_CONCERNS: "separation-of-concerns",
|
|
46
|
+
OBSOLETE_PATTERNS: "obsolete-patterns",
|
|
47
|
+
AI_SMELL: "ai-smell",
|
|
48
|
+
CODE_DUPLICATION: "code-duplication",
|
|
49
|
+
CIRCULAR_DEPS: "circular-deps",
|
|
50
|
+
SECURITY_ANTIPATTERNS: "security-antipatterns",
|
|
51
|
+
REACT_PERFORMANCE: "react-performance",
|
|
52
|
+
MISSING_PROJECT_STANDARDS: "missing-project-standards",
|
|
53
|
+
// Ship-Readiness Rules
|
|
54
|
+
MISSING_COMPLIANCE: "missing-compliance",
|
|
55
|
+
ACCESSIBILITY: "accessibility",
|
|
56
|
+
MISSING_PRODUCTION_BASICS: "missing-production-basics"
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// src/config/defaults.ts
|
|
60
|
+
var DEFAULT_CONFIG = {
|
|
61
|
+
rules: {
|
|
62
|
+
[RULE_ID.OVERSIZED_FILES]: { enabled: true },
|
|
63
|
+
[RULE_ID.DEAD_CODE]: { enabled: true },
|
|
64
|
+
[RULE_ID.HARDCODED_SECRETS]: { enabled: true },
|
|
65
|
+
[RULE_ID.UNUSED_DEPS]: { enabled: true },
|
|
66
|
+
[RULE_ID.MISSING_TESTS]: { enabled: false },
|
|
67
|
+
// Disabled by default - testing strategy varies by project
|
|
68
|
+
[RULE_ID.PATTERN_INCONSISTENCY]: { enabled: true },
|
|
69
|
+
[RULE_ID.POOR_MAINTAINABILITY]: { enabled: true },
|
|
70
|
+
[RULE_ID.MISSING_ERROR_HANDLING]: { enabled: true },
|
|
71
|
+
[RULE_ID.ABANDONED_TODO]: { enabled: true },
|
|
72
|
+
[RULE_ID.BLOATED_BARREL]: { enabled: true },
|
|
73
|
+
[RULE_ID.STYLE_INCONSISTENCY]: { enabled: true },
|
|
74
|
+
[RULE_ID.DUPLICATE_DEPS]: { enabled: true },
|
|
75
|
+
[RULE_ID.GOD_FILE]: { enabled: true },
|
|
76
|
+
[RULE_ID.SEPARATION_OF_CONCERNS]: { enabled: true },
|
|
77
|
+
[RULE_ID.OBSOLETE_PATTERNS]: { enabled: true },
|
|
78
|
+
[RULE_ID.AI_SMELL]: { enabled: true },
|
|
79
|
+
[RULE_ID.CODE_DUPLICATION]: { enabled: true },
|
|
80
|
+
[RULE_ID.CIRCULAR_DEPS]: { enabled: true },
|
|
81
|
+
[RULE_ID.SECURITY_ANTIPATTERNS]: { enabled: true },
|
|
82
|
+
[RULE_ID.REACT_PERFORMANCE]: { enabled: false },
|
|
83
|
+
// Disabled by default - too noisy for most projects
|
|
84
|
+
[RULE_ID.MISSING_PROJECT_STANDARDS]: { enabled: true },
|
|
85
|
+
// Ship-Readiness Rules (022-024)
|
|
86
|
+
[RULE_ID.MISSING_COMPLIANCE]: { enabled: true },
|
|
87
|
+
[RULE_ID.ACCESSIBILITY]: { enabled: true },
|
|
88
|
+
[RULE_ID.MISSING_PRODUCTION_BASICS]: { enabled: true }
|
|
89
|
+
},
|
|
90
|
+
ignore: ["node_modules", "dist", "build", ".next", "coverage", ".turbo", ".git"],
|
|
91
|
+
thresholds: {
|
|
92
|
+
maxFileLines: 500,
|
|
93
|
+
maxFunctionLines: 60,
|
|
94
|
+
maxFunctionParams: 5,
|
|
95
|
+
maxImports: 20,
|
|
96
|
+
minTestRatio: 0.05
|
|
97
|
+
// 5% is realistic for most projects (was 10%)
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
var SOURCE_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx"];
|
|
101
|
+
var DEFAULT_IGNORE_PATTERNS = [
|
|
102
|
+
"**/node_modules/**",
|
|
103
|
+
"**/dist/**",
|
|
104
|
+
"**/build/**",
|
|
105
|
+
"**/.next/**",
|
|
106
|
+
"**/coverage/**",
|
|
107
|
+
"**/.turbo/**",
|
|
108
|
+
"**/.git/**",
|
|
109
|
+
"**/vendor/**",
|
|
110
|
+
"**/*.min.js",
|
|
111
|
+
"**/*.bundle.js"
|
|
112
|
+
];
|
|
113
|
+
|
|
114
|
+
export {
|
|
115
|
+
__require,
|
|
116
|
+
SEVERITY,
|
|
117
|
+
GRADE,
|
|
118
|
+
GRADE_LABEL,
|
|
119
|
+
RULE_ID,
|
|
120
|
+
DEFAULT_CONFIG,
|
|
121
|
+
SOURCE_EXTENSIONS,
|
|
122
|
+
DEFAULT_IGNORE_PATTERNS
|
|
123
|
+
};
|
|
124
|
+
//# sourceMappingURL=chunk-TUE4IPY7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../shared/src/types/constants.ts","../src/config/defaults.ts"],"sourcesContent":["// =============================================================================\n// ViberTest Constants (Const Types Pattern)\n// =============================================================================\n\n// -----------------------------------------------------------------------------\n// Severity\n// -----------------------------------------------------------------------------\n\nexport const SEVERITY = {\n CRITICAL: 'critical',\n HIGH: 'high',\n MEDIUM: 'medium',\n LOW: 'low',\n INFO: 'info',\n} as const;\n\nexport type Severity = (typeof SEVERITY)[keyof typeof SEVERITY];\n\n// -----------------------------------------------------------------------------\n// Grade\n// -----------------------------------------------------------------------------\n\nexport const GRADE = {\n A: 'A',\n B: 'B',\n C: 'C',\n D: 'D',\n F: 'F',\n} as const;\n\nexport type Grade = (typeof GRADE)[keyof typeof GRADE];\n\nexport const GRADE_LABEL = {\n [GRADE.A]: 'Excellent',\n [GRADE.B]: 'Good',\n [GRADE.C]: 'Needs Work',\n [GRADE.D]: 'Poor',\n [GRADE.F]: 'Critical',\n} as const;\n\nexport type GradeLabel = (typeof GRADE_LABEL)[Grade];\n\n// -----------------------------------------------------------------------------\n// Rule IDs\n// -----------------------------------------------------------------------------\n\nexport const RULE_ID = {\n OVERSIZED_FILES: 'oversized-files',\n DEAD_CODE: 'dead-code',\n HARDCODED_SECRETS: 'hardcoded-secrets',\n UNUSED_DEPS: 'unused-deps',\n MISSING_TESTS: 'missing-tests',\n PATTERN_INCONSISTENCY: 'pattern-inconsistency',\n POOR_MAINTAINABILITY: 'poor-maintainability',\n MISSING_ERROR_HANDLING: 'missing-error-handling',\n ABANDONED_TODO: 'abandoned-todo',\n BLOATED_BARREL: 'bloated-barrel',\n STYLE_INCONSISTENCY: 'style-inconsistency',\n DUPLICATE_DEPS: 'duplicate-deps',\n GOD_FILE: 'god-file',\n SEPARATION_OF_CONCERNS: 'separation-of-concerns',\n OBSOLETE_PATTERNS: 'obsolete-patterns',\n AI_SMELL: 'ai-smell',\n CODE_DUPLICATION: 'code-duplication',\n CIRCULAR_DEPS: 'circular-deps',\n SECURITY_ANTIPATTERNS: 'security-antipatterns',\n REACT_PERFORMANCE: 'react-performance',\n MISSING_PROJECT_STANDARDS: 'missing-project-standards',\n // Ship-Readiness Rules\n MISSING_COMPLIANCE: 'missing-compliance',\n ACCESSIBILITY: 'accessibility',\n MISSING_PRODUCTION_BASICS: 'missing-production-basics',\n} as const;\n\nexport type RuleId = (typeof RULE_ID)[keyof typeof RULE_ID];\n\n// -----------------------------------------------------------------------------\n// Report Format\n// -----------------------------------------------------------------------------\n\nexport const REPORT_FORMAT = {\n TERMINAL: 'terminal',\n JSON: 'json',\n HTML: 'html',\n} as const;\n\nexport type ReportFormat = (typeof REPORT_FORMAT)[keyof typeof REPORT_FORMAT];\n","import { RULE_ID } from '@vibertest/shared';\nimport type { ViberTestConfig } from '@vibertest/shared';\n\n/**\n * Default configuration used when no .vibertestrc.json is found.\n * All rules enabled with sensible thresholds for real-world projects.\n *\n * Thresholds are intentionally lenient to avoid frustrating users\n * with too many issues on their first scan. Projects can tighten\n * these values in their own .vibertestrc.json as they improve.\n */\nexport const DEFAULT_CONFIG: ViberTestConfig = {\n rules: {\n [RULE_ID.OVERSIZED_FILES]: { enabled: true },\n [RULE_ID.DEAD_CODE]: { enabled: true },\n [RULE_ID.HARDCODED_SECRETS]: { enabled: true },\n [RULE_ID.UNUSED_DEPS]: { enabled: true },\n [RULE_ID.MISSING_TESTS]: { enabled: false }, // Disabled by default - testing strategy varies by project\n [RULE_ID.PATTERN_INCONSISTENCY]: { enabled: true },\n [RULE_ID.POOR_MAINTAINABILITY]: { enabled: true },\n [RULE_ID.MISSING_ERROR_HANDLING]: { enabled: true },\n [RULE_ID.ABANDONED_TODO]: { enabled: true },\n [RULE_ID.BLOATED_BARREL]: { enabled: true },\n [RULE_ID.STYLE_INCONSISTENCY]: { enabled: true },\n [RULE_ID.DUPLICATE_DEPS]: { enabled: true },\n [RULE_ID.GOD_FILE]: { enabled: true },\n [RULE_ID.SEPARATION_OF_CONCERNS]: { enabled: true },\n [RULE_ID.OBSOLETE_PATTERNS]: { enabled: true },\n [RULE_ID.AI_SMELL]: { enabled: true },\n [RULE_ID.CODE_DUPLICATION]: { enabled: true },\n [RULE_ID.CIRCULAR_DEPS]: { enabled: true },\n [RULE_ID.SECURITY_ANTIPATTERNS]: { enabled: true },\n [RULE_ID.REACT_PERFORMANCE]: { enabled: false }, // Disabled by default - too noisy for most projects\n [RULE_ID.MISSING_PROJECT_STANDARDS]: { enabled: true },\n // Ship-Readiness Rules (022-024)\n [RULE_ID.MISSING_COMPLIANCE]: { enabled: true },\n [RULE_ID.ACCESSIBILITY]: { enabled: true },\n [RULE_ID.MISSING_PRODUCTION_BASICS]: { enabled: true },\n },\n ignore: ['node_modules', 'dist', 'build', '.next', 'coverage', '.turbo', '.git'],\n thresholds: {\n maxFileLines: 500,\n maxFunctionLines: 60,\n maxFunctionParams: 5,\n maxImports: 20,\n minTestRatio: 0.05, // 5% is realistic for most projects (was 10%)\n },\n};\n\n/** File extensions ViberTest analyzes */\nexport const SOURCE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx'] as const;\n\n/** Default ignore patterns for file collection */\nexport const DEFAULT_IGNORE_PATTERNS = [\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n '**/.next/**',\n '**/coverage/**',\n '**/.turbo/**',\n '**/.git/**',\n '**/vendor/**',\n '**/*.min.js',\n '**/*.bundle.js',\n] as const;\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_CONFIG,
|
|
4
|
+
DEFAULT_IGNORE_PATTERNS,
|
|
5
|
+
SOURCE_EXTENSIONS
|
|
6
|
+
} from "./chunk-TUE4IPY7.js";
|
|
7
|
+
export {
|
|
8
|
+
DEFAULT_CONFIG,
|
|
9
|
+
DEFAULT_IGNORE_PATTERNS,
|
|
10
|
+
SOURCE_EXTENSIONS
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=defaults-E5ZXCZVE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/index.d.ts
ADDED