@oxog/codeguardian 1.0.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 +21 -0
- package/README.md +242 -0
- package/dist/cli.cjs +3498 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +3472 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +3158 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +169 -0
- package/dist/index.d.ts +169 -0
- package/dist/index.js +3130 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/index.cjs +1329 -0
- package/dist/plugins/index.cjs.map +1 -0
- package/dist/plugins/index.d.cts +138 -0
- package/dist/plugins/index.d.ts +138 -0
- package/dist/plugins/index.js +1316 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/types-CQZEdzEa.d.cts +487 -0
- package/dist/types-CQZEdzEa.d.ts +487 -0
- package/package.json +88 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Ersin Koc
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# @oxog/codeguardian
|
|
2
|
+
|
|
3
|
+
**Zero-dependency TypeScript codebase guardian** that enforces architecture, security, performance, and quality rules as a pre-commit hook.
|
|
4
|
+
|
|
5
|
+
Unlike traditional linters that check syntax, codeguardian builds a **knowledge graph** of your codebase and evaluates every change against that graph. It understands your project's architectural patterns, detects security anti-patterns, catches performance pitfalls, and blocks or warns based on severity.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Codebase Knowledge Graph** — Maps all files, symbols, imports, and dependencies
|
|
10
|
+
- **Incremental Analysis** — Only re-parses changed files (< 2s pre-commit)
|
|
11
|
+
- **29 Built-in Rules** — Architecture, security, performance, and quality checks
|
|
12
|
+
- **Plugin System** — Extend with custom rules and plugins
|
|
13
|
+
- **Zero Dependencies** — Only TypeScript as a peer dependency
|
|
14
|
+
- **Pre-commit Hook** — Blocks commits with critical/error findings
|
|
15
|
+
- **Multiple Output Formats** — Terminal, JSON, SARIF (GitHub Code Scanning)
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @oxog/codeguardian --save-dev
|
|
21
|
+
npx codeguardian init
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
That's it. codeguardian will now run on every commit.
|
|
25
|
+
|
|
26
|
+
## Programmatic Usage
|
|
27
|
+
|
|
28
|
+
```typescript
|
|
29
|
+
import { createGuardian } from '@oxog/codeguardian';
|
|
30
|
+
|
|
31
|
+
const guardian = createGuardian({
|
|
32
|
+
rootDir: process.cwd(),
|
|
33
|
+
tsconfig: './tsconfig.json',
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Full scan
|
|
37
|
+
const graph = await guardian.scan();
|
|
38
|
+
console.log(`${graph.files.size} files, ${graph.symbols.size} symbols`);
|
|
39
|
+
|
|
40
|
+
// Run analysis
|
|
41
|
+
const result = await guardian.run({ staged: true });
|
|
42
|
+
if (result.blocked) {
|
|
43
|
+
console.error('Commit blocked!');
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## CLI
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
codeguardian init # Setup project
|
|
52
|
+
codeguardian run # Analyze all files
|
|
53
|
+
codeguardian run --staged # Analyze staged files (pre-commit)
|
|
54
|
+
codeguardian run --format json # JSON output
|
|
55
|
+
codeguardian run --format sarif # SARIF for GitHub
|
|
56
|
+
codeguardian run --plugin security # Run specific plugin
|
|
57
|
+
codeguardian run --verbose # Include info findings
|
|
58
|
+
codeguardian stats # Show graph statistics
|
|
59
|
+
codeguardian rules # List all rules
|
|
60
|
+
codeguardian conventions # Show detected conventions
|
|
61
|
+
codeguardian scan --full # Force full re-scan
|
|
62
|
+
codeguardian uninstall # Remove hook
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Configuration
|
|
66
|
+
|
|
67
|
+
Create `.codeguardian.json` in your project root:
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"include": ["src/**/*.ts"],
|
|
72
|
+
"exclude": ["**/*.test.ts"],
|
|
73
|
+
"severity": {
|
|
74
|
+
"blockOn": ["critical", "error"],
|
|
75
|
+
"warnOn": ["warning"]
|
|
76
|
+
},
|
|
77
|
+
"plugins": {
|
|
78
|
+
"architecture": {
|
|
79
|
+
"enabled": true,
|
|
80
|
+
"layers": ["controller", "service", "repository", "util"],
|
|
81
|
+
"enforceDirection": true,
|
|
82
|
+
"maxFileLines": 300,
|
|
83
|
+
"maxFunctionLines": 50
|
|
84
|
+
},
|
|
85
|
+
"security": {
|
|
86
|
+
"enabled": true,
|
|
87
|
+
"checkInjection": true,
|
|
88
|
+
"checkSecrets": true,
|
|
89
|
+
"checkXSS": true
|
|
90
|
+
},
|
|
91
|
+
"performance": {
|
|
92
|
+
"enabled": true,
|
|
93
|
+
"checkN1Queries": true,
|
|
94
|
+
"checkMemoryLeaks": true
|
|
95
|
+
},
|
|
96
|
+
"quality": {
|
|
97
|
+
"enabled": true,
|
|
98
|
+
"maxCyclomaticComplexity": 15
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Core Plugins & Rules
|
|
105
|
+
|
|
106
|
+
### Architecture (6 rules)
|
|
107
|
+
| Rule | Severity | Description |
|
|
108
|
+
|------|----------|-------------|
|
|
109
|
+
| `architecture/layer-violation` | error | Lower layer importing from higher layer |
|
|
110
|
+
| `architecture/circular-dependency` | error | Circular import chains (A -> B -> C -> A) |
|
|
111
|
+
| `architecture/file-role-mismatch` | warning | File content doesn't match directory role |
|
|
112
|
+
| `architecture/god-file` | warning | File exceeds max line count |
|
|
113
|
+
| `architecture/god-function` | warning | Function exceeds max line count |
|
|
114
|
+
| `architecture/barrel-explosion` | info | Barrel files re-exporting too many symbols |
|
|
115
|
+
|
|
116
|
+
### Security (8 rules)
|
|
117
|
+
| Rule | Severity | Description |
|
|
118
|
+
|------|----------|-------------|
|
|
119
|
+
| `security/sql-injection` | critical | String concatenation in SQL queries |
|
|
120
|
+
| `security/hardcoded-secret` | critical | API keys, tokens, passwords in code |
|
|
121
|
+
| `security/eval-usage` | critical | eval(), Function(), setTimeout(string) |
|
|
122
|
+
| `security/prototype-pollution` | error | Direct prototype assignment |
|
|
123
|
+
| `security/xss-risk` | error | innerHTML, document.write |
|
|
124
|
+
| `security/missing-auth-check` | warning | Controllers without auth references |
|
|
125
|
+
| `security/insecure-random` | warning | Math.random() in security contexts |
|
|
126
|
+
| `security/path-traversal` | error | Dynamic paths in file operations |
|
|
127
|
+
|
|
128
|
+
### Performance (7 rules)
|
|
129
|
+
| Rule | Severity | Description |
|
|
130
|
+
|------|----------|-------------|
|
|
131
|
+
| `performance/n1-query` | warning | Database calls inside loops |
|
|
132
|
+
| `performance/sync-in-async` | warning | readFileSync in async functions |
|
|
133
|
+
| `performance/memory-leak-risk` | warning | addEventListener without cleanup |
|
|
134
|
+
| `performance/unbounded-query` | warning | Queries without LIMIT |
|
|
135
|
+
| `performance/missing-index-hint` | info | Queries needing indexes |
|
|
136
|
+
| `performance/heavy-import` | info | Full library imports |
|
|
137
|
+
| `performance/blocking-operation` | warning | CPU-heavy ops in handlers |
|
|
138
|
+
|
|
139
|
+
### Quality (8 rules)
|
|
140
|
+
| Rule | Severity | Description |
|
|
141
|
+
|------|----------|-------------|
|
|
142
|
+
| `quality/cyclomatic-complexity` | warning | Functions exceeding complexity limit |
|
|
143
|
+
| `quality/dead-code` | warning | Exported symbols never imported |
|
|
144
|
+
| `quality/any-type` | warning | Usage of `any` type |
|
|
145
|
+
| `quality/no-error-handling` | warning | Async functions without try-catch |
|
|
146
|
+
| `quality/inconsistent-naming` | info | Non-camelCase function names |
|
|
147
|
+
| `quality/magic-number` | info | Numeric literals without constants |
|
|
148
|
+
| `quality/empty-catch` | warning | Empty catch blocks |
|
|
149
|
+
| `quality/nested-callbacks` | warning | Deeply nested callbacks (> 3 levels) |
|
|
150
|
+
|
|
151
|
+
## Custom Rules
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
import { defineRule, type Finding } from '@oxog/codeguardian';
|
|
155
|
+
|
|
156
|
+
const noConsole = defineRule({
|
|
157
|
+
name: 'custom/no-console',
|
|
158
|
+
severity: 'warning',
|
|
159
|
+
description: 'No console.log in production',
|
|
160
|
+
category: 'quality',
|
|
161
|
+
check: (context) => {
|
|
162
|
+
const findings: Finding[] = [];
|
|
163
|
+
context.walk(context.ast, {
|
|
164
|
+
CallExpression(node) {
|
|
165
|
+
if (context.isConsoleCall(node as any, 'log')) {
|
|
166
|
+
findings.push({
|
|
167
|
+
message: 'Remove console.log',
|
|
168
|
+
file: context.file.path,
|
|
169
|
+
line: 1,
|
|
170
|
+
column: 1,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
return findings;
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Custom Plugins
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
import { definePlugin, defineRule } from '@oxog/codeguardian';
|
|
184
|
+
|
|
185
|
+
const myPlugin = definePlugin({
|
|
186
|
+
name: 'my-team-rules',
|
|
187
|
+
version: '1.0.0',
|
|
188
|
+
install: (kernel) => {
|
|
189
|
+
kernel.registerRule(noConsole);
|
|
190
|
+
kernel.registerRule(anotherRule);
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
guardian.use(myPlugin);
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Inline Suppression
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
// codeguardian-disable-next-line security/sql-injection
|
|
201
|
+
const query = `SELECT * FROM users WHERE id = ${id}`;
|
|
202
|
+
|
|
203
|
+
// codeguardian-disable security/hardcoded-secret -- legacy code
|
|
204
|
+
const key = 'secret_live_abc123xyz';
|
|
205
|
+
// codeguardian-enable security/hardcoded-secret
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Severity Levels
|
|
209
|
+
|
|
210
|
+
| Level | Blocks Commit | When Shown |
|
|
211
|
+
|-------|--------------|------------|
|
|
212
|
+
| `critical` | Yes | Always |
|
|
213
|
+
| `error` | Yes | Always |
|
|
214
|
+
| `warning` | No | Always |
|
|
215
|
+
| `info` | No | Only with `--verbose` |
|
|
216
|
+
|
|
217
|
+
## Requirements
|
|
218
|
+
|
|
219
|
+
- Node.js >= 18
|
|
220
|
+
- TypeScript >= 5.0 (peer dependency)
|
|
221
|
+
|
|
222
|
+
## Documentation
|
|
223
|
+
|
|
224
|
+
| Document | Description |
|
|
225
|
+
|----------|-------------|
|
|
226
|
+
| [API Reference](docs/API_DOCS.md) | Complete API reference for all public functions, types, and plugins |
|
|
227
|
+
| [Contributing](CONTRIBUTING.md) | Development setup, testing, writing rules/plugins, PR process |
|
|
228
|
+
| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common issues and solutions |
|
|
229
|
+
| [Security Policy](SECURITY.md) | Vulnerability reporting and disclosure policy |
|
|
230
|
+
| [Changelog](CHANGELOG.md) | Version history and release notes |
|
|
231
|
+
| [Specification](docs/SPECIFICATION.md) | Package specification and design decisions |
|
|
232
|
+
| [Implementation](docs/IMPLEMENTATION.md) | Architecture decisions and implementation guide |
|
|
233
|
+
|
|
234
|
+
## Links
|
|
235
|
+
|
|
236
|
+
- [Documentation](https://codeguardian.oxog.dev)
|
|
237
|
+
- [GitHub](https://github.com/ersinkoc/codeguardian)
|
|
238
|
+
- [npm](https://www.npmjs.com/package/@oxog/codeguardian)
|
|
239
|
+
|
|
240
|
+
## License
|
|
241
|
+
|
|
242
|
+
MIT - Ersin Koc
|