Skip to content

Commit 3b9cb80

Browse files
committed
feat: configure Biome + Husky + lint-staged for code quality
- Add Biome v2.3.8 as unified formatter and linter (replaces Prettier + ESLint) - Configure Husky v9.1.7 for git hooks - Setup lint-staged v16.2.7 to run Biome on staged files - Update VS Code settings to use Biome as default formatter - Add comprehensive scripts: format, lint, check, check:ci - Remove Prettier configuration files - Update DEVELOPMENT.md with code quality guidelines Benefits: - 25x faster than Prettier (Rust-based) - Single tool instead of 6+ dependencies - Built-in TypeScript support - Automatic formatting on commit
1 parent f0fd317 commit 3b9cb80

File tree

23 files changed

+634
-348
lines changed

23 files changed

+634
-348
lines changed

.husky/pre-commit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
bunx lint-staged

.prettierignore

Lines changed: 0 additions & 19 deletions
This file was deleted.

.prettierrc

Lines changed: 0 additions & 10 deletions
This file was deleted.

.vscode/extensions.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
{
22
"recommendations": [
3-
"dbaeumer.vscode-eslint",
4-
"esbenp.prettier-vscode",
3+
"biomejs.biome",
54
"oven.bun-vscode",
65
"editorconfig.editorconfig",
76
"github.vscode-github-actions",

biome.json

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
{
2+
"$schema": "https://biomejs.dev/schemas/2.3.8/schema.json",
3+
"vcs": {
4+
"enabled": true,
5+
"clientKind": "git",
6+
"useIgnoreFile": true
7+
},
8+
"files": {
9+
"ignoreUnknown": true,
10+
"includes": [
11+
"**",
12+
"!**/node_modules",
13+
"!**/dist",
14+
"!**/build",
15+
"!**/.vscode",
16+
"!**/coverage",
17+
"!**/*.log"
18+
]
19+
},
20+
"formatter": {
21+
"enabled": true,
22+
"indentStyle": "space",
23+
"indentWidth": 2,
24+
"lineWidth": 100,
25+
"lineEnding": "lf"
26+
},
27+
"linter": {
28+
"enabled": true,
29+
"rules": {
30+
"recommended": true,
31+
"complexity": {
32+
"noExtraBooleanCast": "error",
33+
"noUselessCatch": "error",
34+
"noUselessTypeConstraint": "error",
35+
"noAdjacentSpacesInRegex": "error",
36+
"noArguments": "error"
37+
},
38+
"correctness": {
39+
"noConstAssign": "error",
40+
"noConstantCondition": "error",
41+
"noEmptyCharacterClassInRegex": "error",
42+
"noEmptyPattern": "error",
43+
"noGlobalObjectCalls": "error",
44+
"noInvalidConstructorSuper": "error",
45+
"noNonoctalDecimalEscape": "error",
46+
"noPrecisionLoss": "error",
47+
"noSelfAssign": "error",
48+
"noSetterReturn": "error",
49+
"noSwitchDeclarations": "error",
50+
"noUndeclaredVariables": "error",
51+
"noUnreachable": "error",
52+
"noUnreachableSuper": "error",
53+
"noUnsafeFinally": "error",
54+
"noUnsafeOptionalChaining": "error",
55+
"noUnusedLabels": "error",
56+
"noUnusedVariables": "error",
57+
"useIsNan": "error",
58+
"useValidForDirection": "error",
59+
"useYield": "error",
60+
"noInvalidBuiltinInstantiation": "error",
61+
"useValidTypeof": "error"
62+
},
63+
"style": {
64+
"useConst": "error"
65+
},
66+
"suspicious": {
67+
"noAsyncPromiseExecutor": "error",
68+
"noCatchAssign": "error",
69+
"noClassAssign": "error",
70+
"noCompareNegZero": "error",
71+
"noControlCharactersInRegex": "error",
72+
"noDebugger": "error",
73+
"noDoubleEquals": "warn",
74+
"noDuplicateCase": "error",
75+
"noDuplicateClassMembers": "error",
76+
"noDuplicateObjectKeys": "error",
77+
"noDuplicateParameters": "error",
78+
"noEmptyBlockStatements": "warn",
79+
"noExplicitAny": "error",
80+
"noExtraNonNullAssertion": "error",
81+
"noFallthroughSwitchClause": "error",
82+
"noFunctionAssign": "error",
83+
"noGlobalAssign": "error",
84+
"noImportAssign": "error",
85+
"noMisleadingCharacterClass": "error",
86+
"noMisleadingInstantiator": "error",
87+
"noPrototypeBuiltins": "error",
88+
"noRedeclare": "error",
89+
"noShadowRestrictedNames": "error",
90+
"noUnsafeDeclarationMerging": "error",
91+
"noUnsafeNegation": "error",
92+
"useGetterReturn": "error",
93+
"noWith": "error",
94+
"noVar": "error"
95+
}
96+
}
97+
},
98+
"javascript": {
99+
"formatter": {
100+
"quoteStyle": "single",
101+
"jsxQuoteStyle": "double",
102+
"quoteProperties": "asNeeded",
103+
"trailingCommas": "es5",
104+
"semicolons": "always",
105+
"arrowParentheses": "always",
106+
"bracketSpacing": true,
107+
"bracketSameLine": false
108+
},
109+
"globals": ["Bun"]
110+
},
111+
"json": {
112+
"formatter": {
113+
"enabled": true,
114+
"indentStyle": "space",
115+
"indentWidth": 2,
116+
"lineWidth": 100
117+
}
118+
},
119+
"overrides": [
120+
{
121+
"includes": ["**/*.test.ts", "**/*.spec.ts", "**/__tests__/**"],
122+
"linter": {
123+
"rules": {
124+
"suspicious": {
125+
"noExplicitAny": "off"
126+
}
127+
}
128+
}
129+
},
130+
{
131+
"includes": ["**/build.ts"],
132+
"linter": {
133+
"rules": {
134+
"suspicious": {
135+
"useIterableCallbackReturn": "off"
136+
}
137+
}
138+
}
139+
},
140+
{
141+
"includes": ["**/src/**/*.ts", "**/cli.ts", "**/mcp-server.ts", "**/extension.ts"],
142+
"linter": {
143+
"rules": {
144+
"complexity": {
145+
"noStaticOnlyClass": "warn"
146+
}
147+
}
148+
}
149+
}
150+
]
151+
}

build.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ try {
6565
const totalPackageTime = [coreResult, ...results].reduce((sum, r) => sum + r.duration, 0);
6666
const timeSaved = totalPackageTime - totalDuration;
6767

68-
console.log('\n' + '='.repeat(60));
68+
console.log(`\n${'='.repeat(60)}`);
6969
console.log('🎉 All packages built successfully!');
7070
console.log(`⏱️ Total time: ${totalDuration}ms`);
7171
console.log(`💾 Time saved by parallelization: ~${timeSaved}ms`);

docs/DEVELOPMENT.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,14 @@ bun run dev:extension # Extension en modo watch
7070

7171
# Type checking
7272
bun run typecheck
73+
74+
# Code quality (Biome)
75+
bun run format # Formatear todo el código
76+
bun run format:check # Verificar formato sin modificar
77+
bun run lint # Ejecutar linter
78+
bun run lint:fix # Aplicar fixes automáticos del linter
79+
bun run check # Formatear + lint + aplicar fixes
80+
bun run check:ci # Check completo para CI (sin modificar)
7381
```
7482

7583
### Por Paquete
@@ -288,10 +296,81 @@ bun run build
288296
- [ ] Backup/restore functionality
289297
- [ ] Settings panel en VS Code
290298

299+
## Code Quality
300+
301+
### Biome - Unified Linting & Formatting
302+
303+
Cortex usa **Biome** como herramienta unificada para formateo y linting (reemplaza Prettier + ESLint).
304+
305+
#### Configuración
306+
307+
- **Archivo principal**: `biome.json` en la raíz
308+
- **Pre-commit hook**: Husky + lint-staged ejecutan Biome automáticamente
309+
- **VS Code**: La extensión `biomejs.biome` está recomendada
310+
311+
#### Comandos útiles
312+
313+
```bash
314+
# Formatear todo
315+
bun run format
316+
317+
# Solo verificar formato
318+
bun run format:check
319+
320+
# Linting
321+
bun run lint
322+
323+
# Linting con fixes automáticos
324+
bun run lint:fix
325+
326+
# Todo junto (format + lint + fix)
327+
bun run check
328+
329+
# Check completo para CI (no modifica archivos)
330+
bun run check:ci
331+
```
332+
333+
#### Reglas principales
334+
335+
- **Quotes**: Single quotes (`'`)
336+
- **Semicolons**: Always (`;`)
337+
- **Line width**: 100 caracteres
338+
- **Indentation**: 2 espacios
339+
- **Trailing commas**: ES5 style
340+
- **TypeScript**: Preferir `node:` protocol para imports de Node.js
341+
342+
#### Pre-commit Hook
343+
344+
El hook de Husky ejecuta automáticamente Biome en archivos staged antes de cada commit:
345+
346+
```bash
347+
# .husky/pre-commit
348+
bunx lint-staged
349+
```
350+
351+
Configuración en `package.json`:
352+
```json
353+
{
354+
"lint-staged": {
355+
"*.{ts,tsx,js,jsx,json,jsonc}": [
356+
"biome check --write --no-errors-on-unmatched --files-ignore-unknown=true"
357+
]
358+
}
359+
}
360+
```
361+
362+
#### Warnings vs Errors
363+
364+
- **Errors**: Bloquean el commit (p.ej. sintaxis inválida)
365+
- **Warnings**: No bloquean pero deben corregirse (p.ej. `any` explícitos)
366+
367+
Los warnings de `noExplicitAny` son comunes en el proyecto y están configurados como warnings en los archivos de código fuente.
368+
291369
## Resources
292370

293371
- [VS Code Extension API](https://code.visualstudio.com/api)
294372
- [Bun Documentation](https://bun.sh/docs)
373+
- [Biome Documentation](https://biomejs.dev)
295374
- [MCP SDK](https://github.com/modelcontextprotocol/sdk)
296375
- [TreeView Guide](https://code.visualstudio.com/api/extension-guides/tree-view)
297376
- [Webview Guide](https://code.visualstudio.com/api/extension-guides/webview)

package.json

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,19 @@
1919
"test:core": "bun --cwd packages/core test",
2020
"test:watch": "bun test --watch --recursive",
2121
"test:coverage": "bun test --coverage --recursive",
22-
"typecheck": "bunx tsc --noEmit"
22+
"typecheck": "bunx tsc --noEmit",
23+
"format": "biome format --write .",
24+
"format:check": "biome format .",
25+
"lint": "biome lint .",
26+
"lint:fix": "biome lint --write .",
27+
"check": "biome check --write .",
28+
"check:ci": "biome ci .",
29+
"prepare": "husky"
30+
},
31+
"lint-staged": {
32+
"*.{ts,tsx,js,jsx,json,jsonc}": [
33+
"biome check --write --no-errors-on-unmatched --files-ignore-unknown=true"
34+
]
2335
},
2436
"keywords": [
2537
"mcp",
@@ -42,9 +54,12 @@
4254
},
4355
"homepage": "https://github.com/AngelAlexQC/Cortex#readme",
4456
"devDependencies": {
57+
"@biomejs/biome": "^2.3.8",
4558
"@types/bun": "^1.1.13",
4659
"@types/node": "^24.10.2",
4760
"@types/vscode": "^1.85.0",
61+
"husky": "^9.1.7",
62+
"lint-staged": "^16.2.7",
4863
"typescript": "^5.7.3"
4964
},
5065
"engines": {

packages/cli/src/cli.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
import { homedir } from 'node:os';
2+
import { join } from 'node:path';
3+
import { type Memory, MemoryStore } from '@cortex/core';
14
import { Command } from 'commander';
2-
import { MemoryStore } from '@cortex/core';
3-
import { join } from 'path';
4-
import { homedir } from 'os';
55

66
const program = new Command();
77
const store = new MemoryStore();
@@ -40,7 +40,7 @@ program
4040
.action((query, options) => {
4141
const results = store.search(query, {
4242
type: options.type,
43-
limit: parseInt(options.limit),
43+
limit: parseInt(options.limit, 10),
4444
});
4545

4646
if (results.length === 0) {
@@ -49,7 +49,7 @@ program
4949
}
5050

5151
console.log(`\nFound ${results.length} memories:\n`);
52-
results.forEach((memory: any, i: number) => {
52+
results.forEach((memory: Memory, i: number) => {
5353
console.log(`${i + 1}. [${memory.type}] ${memory.content}`);
5454
console.log(` Source: ${memory.source}`);
5555
console.log(` Created: ${memory.createdAt}`);
@@ -69,7 +69,7 @@ program
6969
.action((options) => {
7070
const memories = store.list({
7171
type: options.type,
72-
limit: parseInt(options.limit),
72+
limit: parseInt(options.limit, 10),
7373
});
7474

7575
if (memories.length === 0) {
@@ -78,7 +78,7 @@ program
7878
}
7979

8080
console.log(`\n${memories.length} memories:\n`);
81-
memories.forEach((memory: any, i: number) => {
81+
memories.forEach((memory: Memory, i: number) => {
8282
console.log(`${i + 1}. [${memory.type}] ${memory.content}`);
8383
console.log(` Source: ${memory.source}`);
8484
console.log('');
@@ -110,7 +110,7 @@ program
110110
.command('delete <id>')
111111
.description('Delete a memory by ID')
112112
.action((id) => {
113-
const deleted = store.delete(parseInt(id));
113+
const deleted = store.delete(parseInt(id, 10));
114114
if (deleted) {
115115
console.log(`✓ Memory ${id} deleted`);
116116
} else {

packages/cli/tsconfig.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
"@cortex/core": ["../core/src/index.ts"]
99
}
1010
},
11-
"references": [
12-
{ "path": "../core" }
13-
],
11+
"references": [{ "path": "../core" }],
1412
"include": ["src/**/*"]
1513
}

0 commit comments

Comments
 (0)