chocolatito-code 1.6.8 → 1.6.9
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 +11 -1
- package/dist/tools/gitAudit.d.ts +28 -1
- package/dist/tools/gitAudit.js +95 -3
- package/extension/manifest.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# 🦊 Chocolatito Code
|
|
1
|
+
# 🦊 Chocolatito Code
|
|
2
2
|
|
|
3
3
|
> **Agente Autónomo de Programación para la Terminal**, desarrollado por **Chocolatito** con la arquitectura del **Motor Espectro**.
|
|
4
4
|
|
|
@@ -278,6 +278,16 @@ Antes de hacer un commit o desplegar cambios, corre `/audit` o `/review`:
|
|
|
278
278
|
- **Limpieza de depuración:** localiza sentencias residuales como `console.log`, `debugger;` o `print()`.
|
|
279
279
|
- **Sugerencia de Conventional Commits:** genera automáticamente la propuesta de commit semántico según los archivos modificados (ej. `feat(tools): ...`, `test: ...`).
|
|
280
280
|
|
|
281
|
+
Y se le puede decir dónde callarse. En una herramienta de terminal, `console.log` no es
|
|
282
|
+
un olvido: es la salida del programa. Las rutas que pongas en un `.chocolatitoauditignore`
|
|
283
|
+
—una por línea, `#` para comentar— dejan de salir en la sección de calidad, y el informe
|
|
284
|
+
dice cuántas calló, para que nadie se encuentre el fichero un año después sin saberlo.
|
|
285
|
+
|
|
286
|
+
**Lo que ese fichero NO puede callar: un secreto.** Una clave, un `.env` o una clave
|
|
287
|
+
privada se avisan siempre, esté la ruta ignorada o no. Una herramienta que se deja
|
|
288
|
+
configurar para callarse una credencial es peor que no tenerla, porque da la
|
|
289
|
+
tranquilidad sin el aviso.
|
|
290
|
+
|
|
281
291
|
---
|
|
282
292
|
|
|
283
293
|
## 📌 Widget de Tareas en Vivo y Selector /resume
|
package/dist/tools/gitAudit.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ export interface AuditReport {
|
|
|
19
19
|
secrets: AuditFinding[];
|
|
20
20
|
debugLogs: AuditFinding[];
|
|
21
21
|
residualLogs: AuditFinding[];
|
|
22
|
+
/** Cuantas sentencias se callaron por `.chocolatitoauditignore`. Se dice siempre. */
|
|
23
|
+
debugSilenciados: number;
|
|
22
24
|
sensitiveFiles: string[];
|
|
23
25
|
suggestedCommit: string;
|
|
24
26
|
rawDiff: string;
|
|
@@ -35,7 +37,32 @@ export declare const DEBUG_PATTERNS: Array<{
|
|
|
35
37
|
export declare function esDocumentacion(archivo: string): boolean;
|
|
36
38
|
/** Quita los trozos entre comillas invertidas: `asi` y ``asi``. */
|
|
37
39
|
export declare function sinCitasEnLinea(texto: string): string;
|
|
38
|
-
|
|
40
|
+
/**
|
|
41
|
+
* SE PUEDE CALLAR EL RUIDO, NUNCA UN SECRETO
|
|
42
|
+
*
|
|
43
|
+
* En un programa de terminal, `console.log` NO es un resto de depuracion: es la
|
|
44
|
+
* interfaz. Este repositorio tiene ocho en `src/index.ts` que son justo eso -el
|
|
45
|
+
* enlace de `--servir`, el aviso de que solo escucha en esta maquina- y salian
|
|
46
|
+
* los ocho en cada auditoria. Ocho avisos que hay que ignorar a mano cada vez
|
|
47
|
+
* son ocho razones para dejar de leer la seccion entera.
|
|
48
|
+
*
|
|
49
|
+
* Adivinar cual es interfaz y cual es un olvido no se puede hacer desde fuera:
|
|
50
|
+
* es la misma llamada. Asi que lo dice el proyecto, en un `.chocolatitoauditignore`
|
|
51
|
+
* al lado del `.gitignore`, una ruta o un patron por linea, y `#` para comentar.
|
|
52
|
+
*
|
|
53
|
+
* Con un limite que no se negocia: **esto solo calla la seccion de calidad**. Un
|
|
54
|
+
* secreto, un archivo sensible o una clave privada se avisan siempre, este la
|
|
55
|
+
* ruta ignorada o no. Una herramienta que se puede configurar para callarse una
|
|
56
|
+
* credencial es peor que no tenerla, porque da la tranquilidad sin el aviso.
|
|
57
|
+
*
|
|
58
|
+
* Y lo que se calla se cuenta: el informe dice cuantos silencio, para que nadie
|
|
59
|
+
* descubra el fichero un año despues sin saber que estaba puesto.
|
|
60
|
+
*/
|
|
61
|
+
export declare const ARCHIVO_DE_IGNORADOS = ".chocolatitoauditignore";
|
|
62
|
+
export declare function leerPatronesIgnorados(cwd: string): string[];
|
|
63
|
+
/** Un patron de `.chocolatitoauditignore` contra una ruta del diff. */
|
|
64
|
+
export declare function rutaIgnorada(archivo: string, patrones: string[]): boolean;
|
|
65
|
+
export declare function auditDiffText(rawDiff: string, changedFiles?: string[], patronesIgnorados?: string[]): AuditReport;
|
|
39
66
|
export declare function auditGitDiff(cwd?: string, mockDiff?: string): Promise<AuditReport>;
|
|
40
67
|
export declare function suggestConventionalCommit(files: string[], _insertions: number, _deletions: number): string;
|
|
41
68
|
export declare function formatAuditReport(report: AuditReport): string;
|
package/dist/tools/gitAudit.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
1
3
|
import chalk from "chalk";
|
|
2
4
|
import { ejecutarGit } from "./gitTools.js";
|
|
3
5
|
export const SECRET_PATTERNS = [
|
|
@@ -16,7 +18,11 @@ export const SENSITIVE_FILE_PATTERN = /(?:^|[/\\])(\.env(?:\.[a-zA-Z0-9_-]+)?|id
|
|
|
16
18
|
export const DEBUG_PATTERNS = [
|
|
17
19
|
{ name: "console.log", pattern: /\bconsole\.log\s*\(/ },
|
|
18
20
|
{ name: "console.debug", pattern: /\bconsole\.debug\s*\(/ },
|
|
19
|
-
|
|
21
|
+
// `debugger` como PALABRA sale tambien dentro de una frase: el propio aviso
|
|
22
|
+
// de esta herramienta dice "ni console.log ni debugger" y se denunciaba solo.
|
|
23
|
+
// Un `debugger` de verdad es una sentencia: lleva punto y coma, o esta sola en
|
|
24
|
+
// su linea. Eso es lo que se busca.
|
|
25
|
+
{ name: "debugger", pattern: /(?:^|[;{}])\s*debugger\s*(?:;|$)/ },
|
|
20
26
|
{ name: "print()", pattern: /(?<![\w.])print\s*\(/ },
|
|
21
27
|
{ name: "var_dump", pattern: /\bvar_dump\s*\(/ },
|
|
22
28
|
{ name: "dd()", pattern: /(?<![\w.])dd\s*\(/ },
|
|
@@ -60,10 +66,79 @@ export function esDocumentacion(archivo) {
|
|
|
60
66
|
export function sinCitasEnLinea(texto) {
|
|
61
67
|
return texto.replace(/``[^`]*``/g, " ").replace(/`[^`]*`/g, " ");
|
|
62
68
|
}
|
|
63
|
-
|
|
69
|
+
/**
|
|
70
|
+
* SE PUEDE CALLAR EL RUIDO, NUNCA UN SECRETO
|
|
71
|
+
*
|
|
72
|
+
* En un programa de terminal, `console.log` NO es un resto de depuracion: es la
|
|
73
|
+
* interfaz. Este repositorio tiene ocho en `src/index.ts` que son justo eso -el
|
|
74
|
+
* enlace de `--servir`, el aviso de que solo escucha en esta maquina- y salian
|
|
75
|
+
* los ocho en cada auditoria. Ocho avisos que hay que ignorar a mano cada vez
|
|
76
|
+
* son ocho razones para dejar de leer la seccion entera.
|
|
77
|
+
*
|
|
78
|
+
* Adivinar cual es interfaz y cual es un olvido no se puede hacer desde fuera:
|
|
79
|
+
* es la misma llamada. Asi que lo dice el proyecto, en un `.chocolatitoauditignore`
|
|
80
|
+
* al lado del `.gitignore`, una ruta o un patron por linea, y `#` para comentar.
|
|
81
|
+
*
|
|
82
|
+
* Con un limite que no se negocia: **esto solo calla la seccion de calidad**. Un
|
|
83
|
+
* secreto, un archivo sensible o una clave privada se avisan siempre, este la
|
|
84
|
+
* ruta ignorada o no. Una herramienta que se puede configurar para callarse una
|
|
85
|
+
* credencial es peor que no tenerla, porque da la tranquilidad sin el aviso.
|
|
86
|
+
*
|
|
87
|
+
* Y lo que se calla se cuenta: el informe dice cuantos silencio, para que nadie
|
|
88
|
+
* descubra el fichero un año despues sin saber que estaba puesto.
|
|
89
|
+
*/
|
|
90
|
+
export const ARCHIVO_DE_IGNORADOS = ".chocolatitoauditignore";
|
|
91
|
+
export function leerPatronesIgnorados(cwd) {
|
|
92
|
+
try {
|
|
93
|
+
const crudo = fs.readFileSync(path.join(cwd, ARCHIVO_DE_IGNORADOS), "utf-8");
|
|
94
|
+
return crudo
|
|
95
|
+
.split(/\r?\n/)
|
|
96
|
+
.map((l) => l.trim())
|
|
97
|
+
.filter((l) => l.length > 0 && !l.startsWith("#"));
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return [];
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/** Un patron de `.chocolatitoauditignore` contra una ruta del diff. */
|
|
104
|
+
export function rutaIgnorada(archivo, patrones) {
|
|
105
|
+
if (!archivo || patrones.length === 0)
|
|
106
|
+
return false;
|
|
107
|
+
const ruta = archivo.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
108
|
+
const base = ruta.split("/").pop() || ruta;
|
|
109
|
+
for (const crudo of patrones) {
|
|
110
|
+
const patron = crudo.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
111
|
+
// Una carpeta: "src/ui/" tapa todo lo que hay dentro.
|
|
112
|
+
if (patron.endsWith("/")) {
|
|
113
|
+
if (ruta.startsWith(patron))
|
|
114
|
+
return true;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
// "**" cruza barras, "*" no: src/*.ts no baja a src/ui/marco.ts, src/**/*.ts si.
|
|
118
|
+
const comoRegex = patron
|
|
119
|
+
.split("**")
|
|
120
|
+
.map((trozo) => trozo
|
|
121
|
+
.replace(/[.+^$(){}|[\]\\]/g, (m) => "\\" + m)
|
|
122
|
+
.replace(/\*/g, "[^/]*")
|
|
123
|
+
.replace(/\?/g, "[^/]"))
|
|
124
|
+
.join(".*");
|
|
125
|
+
const re = new RegExp(`^${comoRegex}$`);
|
|
126
|
+
if (re.test(ruta))
|
|
127
|
+
return true;
|
|
128
|
+
// Un patron sin barras ("*.min.js") mira tambien solo el nombre.
|
|
129
|
+
if (!patron.includes("/") && re.test(base))
|
|
130
|
+
return true;
|
|
131
|
+
// Una carpeta escrita sin barra final ("src/ui") tapa igual lo de dentro.
|
|
132
|
+
if (ruta.startsWith(`${patron}/`))
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
export function auditDiffText(rawDiff, changedFiles = [], patronesIgnorados = []) {
|
|
64
138
|
const secrets = [];
|
|
65
139
|
const debugLogs = [];
|
|
66
140
|
const sensitiveFiles = [];
|
|
141
|
+
let debugSilenciados = 0;
|
|
67
142
|
for (const f of changedFiles) {
|
|
68
143
|
if (SENSITIVE_FILE_PATTERN.test(f) && !sensitiveFiles.includes(f)) {
|
|
69
144
|
sensitiveFiles.push(f);
|
|
@@ -119,9 +194,16 @@ export function auditDiffText(rawDiff, changedFiles = []) {
|
|
|
119
194
|
});
|
|
120
195
|
}
|
|
121
196
|
}
|
|
197
|
+
const silenciado = rutaIgnorada(currentFile || "", patronesIgnorados);
|
|
122
198
|
for (const dp of DEBUG_PATTERNS) {
|
|
123
199
|
if (enDocumentacion)
|
|
124
200
|
break;
|
|
201
|
+
if (silenciado) {
|
|
202
|
+
// Se cuenta aunque no se liste: callar no es esconder.
|
|
203
|
+
if (dp.pattern.test(addedContent))
|
|
204
|
+
debugSilenciados++;
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
125
207
|
if (dp.pattern.test(addedContent)) {
|
|
126
208
|
debugLogs.push({
|
|
127
209
|
type: "debug",
|
|
@@ -156,6 +238,7 @@ export function auditDiffText(rawDiff, changedFiles = []) {
|
|
|
156
238
|
secrets,
|
|
157
239
|
debugLogs,
|
|
158
240
|
residualLogs: debugLogs,
|
|
241
|
+
debugSilenciados,
|
|
159
242
|
sensitiveFiles,
|
|
160
243
|
suggestedCommit,
|
|
161
244
|
rawDiff,
|
|
@@ -174,6 +257,7 @@ export async function auditGitDiff(cwd = process.cwd(), mockDiff) {
|
|
|
174
257
|
secrets: [],
|
|
175
258
|
debugLogs: [],
|
|
176
259
|
residualLogs: [],
|
|
260
|
+
debugSilenciados: 0,
|
|
177
261
|
sensitiveFiles: [],
|
|
178
262
|
suggestedCommit: "chore: update project",
|
|
179
263
|
rawDiff: statusRes.error,
|
|
@@ -188,6 +272,7 @@ export async function auditGitDiff(cwd = process.cwd(), mockDiff) {
|
|
|
188
272
|
secrets: [],
|
|
189
273
|
debugLogs: [],
|
|
190
274
|
residualLogs: [],
|
|
275
|
+
debugSilenciados: 0,
|
|
191
276
|
sensitiveFiles: [],
|
|
192
277
|
suggestedCommit: "chore: no pending changes",
|
|
193
278
|
rawDiff: "",
|
|
@@ -205,7 +290,7 @@ export async function auditGitDiff(cwd = process.cwd(), mockDiff) {
|
|
|
205
290
|
diffRes = await ejecutarGit(["diff"], cwd);
|
|
206
291
|
}
|
|
207
292
|
const rawDiff = diffRes.ok ? diffRes.stdout : "";
|
|
208
|
-
return auditDiffText(rawDiff, changedFiles);
|
|
293
|
+
return auditDiffText(rawDiff, changedFiles, leerPatronesIgnorados(cwd));
|
|
209
294
|
}
|
|
210
295
|
export function suggestConventionalCommit(files, _insertions, _deletions) {
|
|
211
296
|
if (files.length === 0)
|
|
@@ -268,8 +353,15 @@ export function formatAuditReport(report) {
|
|
|
268
353
|
if (report.debugLogs.length > 5) {
|
|
269
354
|
lines.push(chalk.gray(` ... y ${report.debugLogs.length - 5} más.`));
|
|
270
355
|
}
|
|
356
|
+
if (report.debugSilenciados > 0) {
|
|
357
|
+
lines.push(chalk.gray(` (${report.debugSilenciados} más en rutas de ${ARCHIVO_DE_IGNORADOS}, sin listar.)`));
|
|
358
|
+
}
|
|
271
359
|
lines.push("");
|
|
272
360
|
}
|
|
361
|
+
else if (report.debugSilenciados > 0) {
|
|
362
|
+
lines.push(chalk.green(" ✔ Calidad: Sin rastros nuevos de console.log ni debugger") +
|
|
363
|
+
chalk.gray(` (${report.debugSilenciados} en rutas de ${ARCHIVO_DE_IGNORADOS}, sin listar).`));
|
|
364
|
+
}
|
|
273
365
|
else {
|
|
274
366
|
lines.push(chalk.green(" ✔ Calidad: Sin rastros de console.log ni debugger en líneas nuevas."));
|
|
275
367
|
}
|
package/extension/manifest.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"manifest_version": 3,
|
|
3
3
|
"minimum_chrome_version": "102",
|
|
4
4
|
"name": "Chocolatito Code",
|
|
5
|
-
"version": "1.6.
|
|
5
|
+
"version": "1.6.9",
|
|
6
6
|
"description": "Deja que Chocolatito Code trabaje dentro de tu Chrome, en segundo plano y con tus sesiones ya iniciadas.",
|
|
7
7
|
"permissions": [
|
|
8
8
|
"tabs",
|
package/package.json
CHANGED