skhaall-codeguard 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.
Files changed (119) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +125 -0
  3. package/dist/cli.d.ts +16 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +295 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/core/indexer.d.ts +21 -0
  8. package/dist/core/indexer.d.ts.map +1 -0
  9. package/dist/core/indexer.js +96 -0
  10. package/dist/core/indexer.js.map +1 -0
  11. package/dist/graph/dependency-graph.d.ts +37 -0
  12. package/dist/graph/dependency-graph.d.ts.map +1 -0
  13. package/dist/graph/dependency-graph.js +94 -0
  14. package/dist/graph/dependency-graph.js.map +1 -0
  15. package/dist/graph/impact-resolver.d.ts +40 -0
  16. package/dist/graph/impact-resolver.d.ts.map +1 -0
  17. package/dist/graph/impact-resolver.js +108 -0
  18. package/dist/graph/impact-resolver.js.map +1 -0
  19. package/dist/index.d.ts +8 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +299 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/parsers/base-parser.d.ts +111 -0
  24. package/dist/parsers/base-parser.d.ts.map +1 -0
  25. package/dist/parsers/base-parser.js +7 -0
  26. package/dist/parsers/base-parser.js.map +1 -0
  27. package/dist/parsers/detector.d.ts +10 -0
  28. package/dist/parsers/detector.d.ts.map +1 -0
  29. package/dist/parsers/detector.js +61 -0
  30. package/dist/parsers/detector.js.map +1 -0
  31. package/dist/parsers/extractors/api-calls.d.ts +10 -0
  32. package/dist/parsers/extractors/api-calls.d.ts.map +1 -0
  33. package/dist/parsers/extractors/api-calls.js +99 -0
  34. package/dist/parsers/extractors/api-calls.js.map +1 -0
  35. package/dist/parsers/extractors/auth-guards.d.ts +8 -0
  36. package/dist/parsers/extractors/auth-guards.d.ts.map +1 -0
  37. package/dist/parsers/extractors/auth-guards.js +23 -0
  38. package/dist/parsers/extractors/auth-guards.js.map +1 -0
  39. package/dist/parsers/prisma-parser.d.ts +45 -0
  40. package/dist/parsers/prisma-parser.d.ts.map +1 -0
  41. package/dist/parsers/prisma-parser.js +197 -0
  42. package/dist/parsers/prisma-parser.js.map +1 -0
  43. package/dist/parsers/typescript-parser.d.ts +28 -0
  44. package/dist/parsers/typescript-parser.d.ts.map +1 -0
  45. package/dist/parsers/typescript-parser.js +374 -0
  46. package/dist/parsers/typescript-parser.js.map +1 -0
  47. package/dist/setup.d.ts +10 -0
  48. package/dist/setup.d.ts.map +1 -0
  49. package/dist/setup.js +135 -0
  50. package/dist/setup.js.map +1 -0
  51. package/dist/storage/index-store.d.ts +36 -0
  52. package/dist/storage/index-store.d.ts.map +1 -0
  53. package/dist/storage/index-store.js +108 -0
  54. package/dist/storage/index-store.js.map +1 -0
  55. package/dist/tools/changelog.d.ts +36 -0
  56. package/dist/tools/changelog.d.ts.map +1 -0
  57. package/dist/tools/changelog.js +212 -0
  58. package/dist/tools/changelog.js.map +1 -0
  59. package/dist/tools/check.d.ts +31 -0
  60. package/dist/tools/check.d.ts.map +1 -0
  61. package/dist/tools/check.js +180 -0
  62. package/dist/tools/check.js.map +1 -0
  63. package/dist/tools/graph.d.ts +20 -0
  64. package/dist/tools/graph.d.ts.map +1 -0
  65. package/dist/tools/graph.js +192 -0
  66. package/dist/tools/graph.js.map +1 -0
  67. package/dist/tools/guard.d.ts +30 -0
  68. package/dist/tools/guard.d.ts.map +1 -0
  69. package/dist/tools/guard.js +132 -0
  70. package/dist/tools/guard.js.map +1 -0
  71. package/dist/tools/health.d.ts +33 -0
  72. package/dist/tools/health.d.ts.map +1 -0
  73. package/dist/tools/health.js +241 -0
  74. package/dist/tools/health.js.map +1 -0
  75. package/dist/tools/impact.d.ts +10 -0
  76. package/dist/tools/impact.d.ts.map +1 -0
  77. package/dist/tools/impact.js +45 -0
  78. package/dist/tools/impact.js.map +1 -0
  79. package/dist/tools/regression.d.ts +29 -0
  80. package/dist/tools/regression.d.ts.map +1 -0
  81. package/dist/tools/regression.js +151 -0
  82. package/dist/tools/regression.js.map +1 -0
  83. package/dist/tools/routes.d.ts +40 -0
  84. package/dist/tools/routes.d.ts.map +1 -0
  85. package/dist/tools/routes.js +203 -0
  86. package/dist/tools/routes.js.map +1 -0
  87. package/dist/tools/schema.d.ts +37 -0
  88. package/dist/tools/schema.d.ts.map +1 -0
  89. package/dist/tools/schema.js +214 -0
  90. package/dist/tools/schema.js.map +1 -0
  91. package/dist/tools/search.d.ts +18 -0
  92. package/dist/tools/search.d.ts.map +1 -0
  93. package/dist/tools/search.js +99 -0
  94. package/dist/tools/search.js.map +1 -0
  95. package/dist/tools/tool-definitions.d.ts +15 -0
  96. package/dist/tools/tool-definitions.d.ts.map +1 -0
  97. package/dist/tools/tool-definitions.js +157 -0
  98. package/dist/tools/tool-definitions.js.map +1 -0
  99. package/dist/utils/import-resolver.d.ts +33 -0
  100. package/dist/utils/import-resolver.d.ts.map +1 -0
  101. package/dist/utils/import-resolver.js +150 -0
  102. package/dist/utils/import-resolver.js.map +1 -0
  103. package/dist/utils/logger.d.ts +15 -0
  104. package/dist/utils/logger.d.ts.map +1 -0
  105. package/dist/utils/logger.js +49 -0
  106. package/dist/utils/logger.js.map +1 -0
  107. package/dist/utils/path.d.ts +6 -0
  108. package/dist/utils/path.d.ts.map +1 -0
  109. package/dist/utils/path.js +12 -0
  110. package/dist/utils/path.js.map +1 -0
  111. package/dist/utils/scanner.d.ts +13 -0
  112. package/dist/utils/scanner.d.ts.map +1 -0
  113. package/dist/utils/scanner.js +55 -0
  114. package/dist/utils/scanner.js.map +1 -0
  115. package/dist/utils/validators.d.ts +45 -0
  116. package/dist/utils/validators.d.ts.map +1 -0
  117. package/dist/utils/validators.js +54 -0
  118. package/dist/utils/validators.js.map +1 -0
  119. package/package.json +57 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Skhaall
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,125 @@
1
+ # @skhaall/codeguard
2
+
3
+ Serveur MCP qui analyse le code TypeScript/Prisma d'un projet, construit un graphe de dependances, et protege contre les modifications dangereuses.
4
+
5
+ **Ecosysteme** : TypeScript, JavaScript, Prisma (support Python/Go/Rust prevu via tree-sitter en v0.2)
6
+
7
+ ## Ce que ca fait
8
+
9
+ - **Impact analysis** — "je modifie ce fichier, qu'est-ce qui casse ?"
10
+ - **Guard** — "est-ce safe de modifier ce fichier ?" (pre-change, bloque si risque critique)
11
+ - **Check** — detecte les imports casses apres modification (post-change)
12
+ - **Health** — score de sante global du projet (A-F, scoring adaptatif)
13
+ - **Schema check** — coherence Prisma ↔ DTOs backend ↔ types frontend
14
+ - **Regression map** — quelles pages/routes retester apres un changement
15
+ - **Graph** — diagramme Mermaid du graphe de dependances
16
+ - **Search** — "qui utilise cette fonction/type/hook ?"
17
+
18
+ ## Prerequis
19
+
20
+ - Node.js >= 20
21
+ - Claude Code (pour les hooks MCP)
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ npm install -g @skhaall/codeguard
27
+ ```
28
+
29
+ Ou depuis les sources :
30
+
31
+ ```bash
32
+ git clone https://github.com/Skhaaall/codeguard.git
33
+ cd codeguard
34
+ npm install
35
+ npm run build
36
+ ```
37
+
38
+ ## Setup (hooks automatiques)
39
+
40
+ Installe les hooks guard + check globalement dans Claude Code :
41
+
42
+ ```bash
43
+ codeguard-setup setup
44
+ ```
45
+
46
+ Pour les retirer :
47
+
48
+ ```bash
49
+ codeguard-setup unsetup
50
+ ```
51
+
52
+ ## Utilisation
53
+
54
+ ### Serveur MCP (pour Claude Code)
55
+
56
+ Ajouter dans le `.mcp.json` du projet :
57
+
58
+ ```json
59
+ {
60
+ "mcpServers": {
61
+ "codeguard": {
62
+ "command": "node",
63
+ "args": ["/chemin/vers/codeguard/dist/index.js"]
64
+ }
65
+ }
66
+ }
67
+ ```
68
+
69
+ ### CLI
70
+
71
+ ```bash
72
+ codeguard-cli init [project-root] # Indexer le projet
73
+ codeguard-cli status [project-root] # Etat de l'index
74
+ codeguard-cli health [project-root] # Score de sante (A-F)
75
+ codeguard-cli impact <fichier> [project-root] # Analyse d'impact
76
+ codeguard-cli regression <fichier> [project-root] # Pages a retester
77
+ codeguard-cli graph [fichier] [project-root] # Diagramme Mermaid
78
+ codeguard-cli schema [project-root] # Coherence Prisma ↔ TS
79
+ ```
80
+
81
+ ## Outils MCP (11)
82
+
83
+ | Outil | Description | Quand |
84
+ |---|---|---|
85
+ | `impact` | Fichiers impactes si on modifie un fichier | Avant modification |
86
+ | `guard` | Risques, fichiers a verifier, recommandation go/no-go | Avant modification |
87
+ | `check` | Imports casses, exports supprimes, types changes | Apres modification |
88
+ | `health` | Score A-F, imports casses, cycles, orphelins | A la demande |
89
+ | `schema_check` | Coherence Prisma ↔ DTOs ↔ types frontend | Apres modif schema |
90
+ | `search` | Recherche fonctions, types, hooks, routes | A la demande |
91
+ | `dependencies` | Graphe d'un fichier (importe / importe par) | A la demande |
92
+ | `reindex` | Re-indexer le projet (complet ou incremental) | Debut de session |
93
+ | `status` | Date, nombre de fichiers, fraicheur de l'index | A la demande |
94
+ | `regression_map` | Pages et routes a retester apres modification | Avant deploy |
95
+ | `graph` | Diagramme Mermaid (complet ou focus sur un fichier) | A la demande |
96
+
97
+ ## Langages supportes
98
+
99
+ | Langage | Parser | Profondeur |
100
+ |---|---|---|
101
+ | TypeScript/TSX | ts-morph | Complet (types, generics, routes Next.js/NestJS) |
102
+ | JavaScript/JSX | ts-morph | Imports, exports, fonctions, classes |
103
+ | Prisma | Parser custom | Modeles, champs, relations, enums |
104
+
105
+ Path aliases TypeScript (`@/` → `src/`) et barrel exports (`from './dir'` → `dir/index.ts`) sont geres automatiquement via la lecture du `tsconfig.json`.
106
+
107
+ ## Stack
108
+
109
+ - TypeScript strict
110
+ - **ts-morph** — parsing profond TypeScript
111
+ - **@modelcontextprotocol/sdk** — protocole MCP standard (stdio)
112
+ - Index JSON cache dans `.codeguard/`
113
+ - Zero dependance lourde (pas de Docker, pas de base de donnees)
114
+
115
+ ## Securite
116
+
117
+ - Path traversal bloque (les chemins doivent rester dans le projet)
118
+ - Validation des inputs MCP a runtime
119
+ - Limites DoS (stdin 1 Mo, index 50 Mo)
120
+ - Liens symboliques ignores
121
+ - CodeGuard lit le code source mais ne le modifie JAMAIS
122
+
123
+ ## Licence
124
+
125
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CodeGuard CLI — deux modes :
4
+ *
5
+ * Mode hook (guard/check) — appele par les hooks Claude Code :
6
+ * echo '{"tool_input":{"file_path":"..."}}' | codeguard-cli guard
7
+ *
8
+ * Mode CLI (init/status/impact/health/regression) — appele manuellement :
9
+ * codeguard-cli init [project-root]
10
+ * codeguard-cli status [project-root]
11
+ * codeguard-cli impact <file> [project-root]
12
+ * codeguard-cli health [project-root]
13
+ * codeguard-cli regression <file> [project-root]
14
+ */
15
+ export {};
16
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;GAYG"}
package/dist/cli.js ADDED
@@ -0,0 +1,295 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CodeGuard CLI — deux modes :
4
+ *
5
+ * Mode hook (guard/check) — appele par les hooks Claude Code :
6
+ * echo '{"tool_input":{"file_path":"..."}}' | codeguard-cli guard
7
+ *
8
+ * Mode CLI (init/status/impact/health/regression) — appele manuellement :
9
+ * codeguard-cli init [project-root]
10
+ * codeguard-cli status [project-root]
11
+ * codeguard-cli impact <file> [project-root]
12
+ * codeguard-cli health [project-root]
13
+ * codeguard-cli regression <file> [project-root]
14
+ */
15
+ import { resolve } from 'node:path';
16
+ import { IndexStore } from './storage/index-store.js';
17
+ import { initLogger, logger } from './utils/logger.js';
18
+ import { validateHookInput } from './utils/validators.js';
19
+ import { indexProject } from './core/indexer.js';
20
+ import { runGuard, formatGuardResult } from './tools/guard.js';
21
+ import { runCheck, formatCheckResult } from './tools/check.js';
22
+ import { runHealth, formatHealthResult } from './tools/health.js';
23
+ import { runRegressionMap, formatRegressionResult } from './tools/regression.js';
24
+ import { runImpactAnalysis, formatImpactResult } from './tools/impact.js';
25
+ import { generateGraph, formatGraphResult } from './tools/graph.js';
26
+ import { runSchemaCheck, formatSchemaResult } from './tools/schema.js';
27
+ import { runRouteGuard, formatRouteGuardResult } from './tools/routes.js';
28
+ import { runChangelog, formatChangelogResult } from './tools/changelog.js';
29
+ import { DependencyGraph } from './graph/dependency-graph.js';
30
+ const COMMANDS_HOOK = ['guard', 'check'];
31
+ const COMMANDS_CLI = ['init', 'status', 'impact', 'health', 'regression', 'graph', 'schema', 'routes', 'changelog'];
32
+ const ALL_COMMANDS = [...COMMANDS_HOOK, ...COMMANDS_CLI];
33
+ // --- Lecture stdin ---
34
+ const MAX_STDIN_BYTES = 1_048_576; // 1 Mo
35
+ async function readStdin() {
36
+ return new Promise((resolve) => {
37
+ let data = '';
38
+ let truncated = false;
39
+ process.stdin.setEncoding('utf-8');
40
+ process.stdin.on('data', (chunk) => {
41
+ if (truncated)
42
+ return;
43
+ data += chunk;
44
+ if (Buffer.byteLength(data) > MAX_STDIN_BYTES) {
45
+ truncated = true;
46
+ data = '';
47
+ }
48
+ });
49
+ process.stdin.on('end', () => resolve(data));
50
+ setTimeout(() => resolve(data), 10000);
51
+ });
52
+ }
53
+ // --- Indexation ---
54
+ async function ensureIndex(projectRoot) {
55
+ const store = new IndexStore(projectRoot);
56
+ const existing = store.load();
57
+ if (existing)
58
+ return existing;
59
+ const { index } = await indexProject(projectRoot);
60
+ return index;
61
+ }
62
+ // --- Mode hook (guard/check) ---
63
+ async function hookGuard(projectRoot, filePath) {
64
+ const index = await ensureIndex(projectRoot);
65
+ const result = runGuard(index, filePath);
66
+ const formatted = formatGuardResult(result);
67
+ const output = {
68
+ hookSpecificOutput: {
69
+ hookEventName: 'PreToolUse',
70
+ permissionDecision: result.risk === 'critical' ? 'deny' : 'allow',
71
+ ...(result.risk === 'critical'
72
+ ? { permissionDecisionReason: `CodeGuard: risque CRITIQUE. ${result.warnings.map((w) => w.message).join(' ')}` }
73
+ : {}),
74
+ additionalContext: formatted,
75
+ },
76
+ };
77
+ process.stdout.write(JSON.stringify(output));
78
+ }
79
+ async function hookCheck(projectRoot, filePath) {
80
+ const index = await ensureIndex(projectRoot);
81
+ const result = await runCheck(index, filePath);
82
+ const formatted = formatCheckResult(result);
83
+ const store = new IndexStore(projectRoot);
84
+ store.save(index);
85
+ const output = {
86
+ hookSpecificOutput: {
87
+ hookEventName: 'PostToolUse',
88
+ additionalContext: formatted,
89
+ },
90
+ };
91
+ process.stdout.write(JSON.stringify(output));
92
+ }
93
+ async function runHookMode(command) {
94
+ const argProjectRoot = process.argv[3];
95
+ const stdinData = await readStdin();
96
+ let filePath = '';
97
+ let hookCwd = '';
98
+ if (stdinData.trim()) {
99
+ try {
100
+ const parsed = JSON.parse(stdinData);
101
+ const hookInput = validateHookInput(parsed);
102
+ if (hookInput) {
103
+ filePath = hookInput.filePath;
104
+ hookCwd = hookInput.cwd;
105
+ if (filePath)
106
+ filePath = resolve(filePath);
107
+ }
108
+ }
109
+ catch {
110
+ if (stdinData.trim().length > 0) {
111
+ logger.warn('Stdin non-JSON recu par le hook', { preview: stdinData.slice(0, 200) });
112
+ }
113
+ }
114
+ }
115
+ const projectRoot = resolve(argProjectRoot ?? (hookCwd || process.cwd()));
116
+ initLogger(projectRoot, 'warn');
117
+ // Valider que le filePath du hook reste dans le projet
118
+ if (filePath) {
119
+ const normalizedFile = filePath.replace(/\\/g, '/').toLowerCase();
120
+ const normalizedRoot = projectRoot.replace(/\\/g, '/').toLowerCase();
121
+ if (!normalizedFile.startsWith(normalizedRoot)) {
122
+ filePath = ''; // Ignorer les chemins hors projet
123
+ logger.warn('Chemin hors du projet ignore par le hook', { filePath });
124
+ }
125
+ }
126
+ if (!filePath) {
127
+ const eventName = command === 'guard' ? 'PreToolUse' : 'PostToolUse';
128
+ const output = {
129
+ hookSpecificOutput: {
130
+ hookEventName: eventName,
131
+ ...(command === 'guard' ? { permissionDecision: 'allow' } : {}),
132
+ additionalContext: 'CodeGuard: pas de fichier a verifier.',
133
+ },
134
+ };
135
+ process.stdout.write(JSON.stringify(output));
136
+ return;
137
+ }
138
+ try {
139
+ if (command === 'guard') {
140
+ await hookGuard(projectRoot, filePath);
141
+ }
142
+ else {
143
+ await hookCheck(projectRoot, filePath);
144
+ }
145
+ }
146
+ catch (error) {
147
+ logger.error('Erreur hook', { command, error: String(error) });
148
+ const eventName = command === 'guard' ? 'PreToolUse' : 'PostToolUse';
149
+ const output = {
150
+ hookSpecificOutput: {
151
+ hookEventName: eventName,
152
+ ...(command === 'guard' ? { permissionDecision: 'allow' } : {}),
153
+ additionalContext: `CodeGuard: erreur interne (${error instanceof Error ? error.message : String(error)}).`,
154
+ },
155
+ };
156
+ process.stdout.write(JSON.stringify(output));
157
+ }
158
+ }
159
+ /** Resout un chemin et verifie qu'il reste dans le projet */
160
+ function safeResolvePath(input, projectRoot) {
161
+ const resolved = resolve(input);
162
+ const normalizedResolved = resolved.replace(/\\/g, '/').toLowerCase();
163
+ const normalizedRoot = projectRoot.replace(/\\/g, '/').toLowerCase();
164
+ if (!normalizedResolved.startsWith(normalizedRoot)) {
165
+ throw new Error(`Chemin hors du projet interdit : ${input}`);
166
+ }
167
+ return resolved;
168
+ }
169
+ // --- Mode CLI (init/status/impact/health/regression) ---
170
+ async function runCliMode(command) {
171
+ // Pour impact/regression, le fichier est argv[3] et project root argv[4]
172
+ // Pour init/status/health, project root est argv[3]
173
+ const needsFile = command === 'impact' || command === 'regression';
174
+ const optionalFile = command === 'graph';
175
+ const fileArg = (needsFile || optionalFile) ? process.argv[3] : undefined;
176
+ const rootArg = (needsFile || optionalFile) ? process.argv[4] : process.argv[3];
177
+ if (needsFile && !fileArg) {
178
+ console.error(`Usage: codeguard-cli ${command} <fichier> [project-root]`);
179
+ process.exit(1);
180
+ }
181
+ const projectRoot = resolve(rootArg ?? process.cwd());
182
+ initLogger(projectRoot, 'warn');
183
+ switch (command) {
184
+ case 'init': {
185
+ console.log(`Indexation de ${projectRoot}...`);
186
+ const { index } = await indexProject(projectRoot);
187
+ const graph = DependencyGraph.fromIndex(index);
188
+ console.log(`Indexation terminee.`);
189
+ console.log(` Fichiers : ${index.fileCount}`);
190
+ console.log(` Noeuds : ${graph.getNodeCount()}`);
191
+ console.log(` Aretes : ${graph.getEdgeCount()}`);
192
+ console.log(` Index : ${resolve(projectRoot, '.codeguard/index.json')}`);
193
+ break;
194
+ }
195
+ case 'status': {
196
+ const store = new IndexStore(projectRoot);
197
+ const index = store.load();
198
+ if (!index) {
199
+ console.log('Aucun index. Lancez "codeguard-cli init" pour indexer le projet.');
200
+ process.exit(1);
201
+ }
202
+ const age = Date.now() - index.indexedAt;
203
+ const ageMin = Math.round(age / 60000);
204
+ console.log(`CodeGuard — Status`);
205
+ console.log(` Projet : ${index.projectRoot}`);
206
+ console.log(` Fichiers: ${index.fileCount}`);
207
+ console.log(` Index : ${new Date(index.indexedAt).toLocaleString('fr-FR')}`);
208
+ console.log(` Age : ${ageMin < 60 ? `${ageMin} min` : `${Math.round(ageMin / 60)}h`}`);
209
+ break;
210
+ }
211
+ case 'impact': {
212
+ const index = await ensureIndex(projectRoot);
213
+ const filePath = safeResolvePath(fileArg, projectRoot);
214
+ const result = runImpactAnalysis(index, filePath);
215
+ console.log(formatImpactResult(result));
216
+ break;
217
+ }
218
+ case 'health': {
219
+ const index = await ensureIndex(projectRoot);
220
+ const result = runHealth(index);
221
+ console.log(formatHealthResult(result));
222
+ break;
223
+ }
224
+ case 'regression': {
225
+ const index = await ensureIndex(projectRoot);
226
+ const filePath = safeResolvePath(fileArg, projectRoot);
227
+ const result = runRegressionMap(index, filePath);
228
+ console.log(formatRegressionResult(result));
229
+ break;
230
+ }
231
+ case 'graph': {
232
+ const index = await ensureIndex(projectRoot);
233
+ const focusFile = fileArg ? safeResolvePath(fileArg, projectRoot) : undefined;
234
+ const result = generateGraph(index, focusFile);
235
+ console.log(formatGraphResult(result));
236
+ break;
237
+ }
238
+ case 'schema': {
239
+ const index = await ensureIndex(projectRoot);
240
+ const result = runSchemaCheck(index);
241
+ console.log(formatSchemaResult(result));
242
+ break;
243
+ }
244
+ case 'routes': {
245
+ const index = await ensureIndex(projectRoot);
246
+ const result = runRouteGuard(index);
247
+ console.log(formatRouteGuardResult(result));
248
+ break;
249
+ }
250
+ case 'changelog': {
251
+ const store = new IndexStore(projectRoot);
252
+ const index = store.load();
253
+ if (!index) {
254
+ console.log('Aucun index. Lancez "codeguard-cli init" d\'abord.');
255
+ process.exit(1);
256
+ }
257
+ const snapshot = store.loadSnapshot();
258
+ const result = runChangelog(index, snapshot);
259
+ console.log(formatChangelogResult(result));
260
+ break;
261
+ }
262
+ }
263
+ }
264
+ // --- Main ---
265
+ async function main() {
266
+ const command = process.argv[2];
267
+ if (!command || !ALL_COMMANDS.includes(command)) {
268
+ console.log(`CodeGuard CLI v0.1.0\n`);
269
+ console.log(`Usage: codeguard-cli <commande> [options]\n`);
270
+ console.log(`Commandes :`);
271
+ console.log(` init [project-root] Indexer le projet`);
272
+ console.log(` status [project-root] Etat de l'index`);
273
+ console.log(` impact <fichier> [project-root] Analyse d'impact`);
274
+ console.log(` health [project-root] Score de sante`);
275
+ console.log(` regression <fichier> [project-root] Pages a retester`);
276
+ console.log(` graph [fichier] [project-root] Diagramme Mermaid (complet ou focus)`);
277
+ console.log(` schema [project-root] Coherence Prisma ↔ DTOs ↔ types`);
278
+ console.log(` routes [project-root] Coherence routes frontend ↔ backend`);
279
+ console.log(` changelog [project-root] Diff depuis le dernier reindex`);
280
+ console.log(` guard [project-root] Hook pre-modification (stdin JSON)`);
281
+ console.log(` check [project-root] Hook post-modification (stdin JSON)`);
282
+ process.exit(command ? 1 : 0);
283
+ }
284
+ if (COMMANDS_HOOK.includes(command)) {
285
+ await runHookMode(command);
286
+ }
287
+ else {
288
+ await runCliMode(command);
289
+ }
290
+ }
291
+ main().catch((error) => {
292
+ console.error(`Erreur fatale: ${error instanceof Error ? error.message : String(error)}`);
293
+ process.exit(1);
294
+ });
295
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC3E,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAG9D,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AACzC,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;AACpH,MAAM,YAAY,GAAG,CAAC,GAAG,aAAa,EAAE,GAAG,YAAY,CAAC,CAAC;AAEzD,wBAAwB;AAExB,MAAM,eAAe,GAAG,SAAS,CAAC,CAAC,OAAO;AAE1C,KAAK,UAAU,SAAS;IACtB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QACnC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YACjC,IAAI,SAAS;gBAAE,OAAO;YACtB,IAAI,IAAI,KAAK,CAAC;YACd,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,eAAe,EAAE,CAAC;gBAC9C,SAAS,GAAG,IAAI,CAAC;gBACjB,IAAI,GAAG,EAAE,CAAC;YACZ,CAAC;QACH,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAC7C,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,qBAAqB;AAErB,KAAK,UAAU,WAAW,CAAC,WAAmB;IAC5C,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC;IAClD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,kCAAkC;AAElC,KAAK,UAAU,SAAS,CAAC,WAAmB,EAAE,QAAgB;IAC5D,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACzC,MAAM,SAAS,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAE5C,MAAM,MAAM,GAAG;QACb,kBAAkB,EAAE;YAClB,aAAa,EAAE,YAAY;YAC3B,kBAAkB,EAAE,MAAM,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;YACjE,GAAG,CAAC,MAAM,CAAC,IAAI,KAAK,UAAU;gBAC5B,CAAC,CAAC,EAAE,wBAAwB,EAAE,+BAA+B,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE;gBAChH,CAAC,CAAC,EAAE,CAAC;YACP,iBAAiB,EAAE,SAAS;SAC7B;KACF,CAAC;IACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,WAAmB,EAAE,QAAgB;IAC5D,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAE5C,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;IAC1C,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAElB,MAAM,MAAM,GAAG;QACb,kBAAkB,EAAE;YAClB,aAAa,EAAE,aAAa;YAC5B,iBAAiB,EAAE,SAAS;SAC7B;KACF,CAAC;IACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,OAAe;IACxC,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAEvC,MAAM,SAAS,GAAG,MAAM,SAAS,EAAE,CAAC;IACpC,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,IAAI,OAAO,GAAG,EAAE,CAAC;IAEjB,IAAI,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YAC9C,MAAM,SAAS,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;YAC5C,IAAI,SAAS,EAAE,CAAC;gBACd,QAAQ,GAAG,SAAS,CAAC,QAAQ,CAAC;gBAC9B,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC;gBACxB,IAAI,QAAQ;oBAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAChC,MAAM,CAAC,IAAI,CAAC,iCAAiC,EAAE,EAAE,OAAO,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;YACvF,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,OAAO,CAAC,cAAc,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IAC1E,UAAU,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAEhC,uDAAuD;IACvD,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;QAClE,MAAM,cAAc,GAAG,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;QACrE,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;YAC/C,QAAQ,GAAG,EAAE,CAAC,CAAC,kCAAkC;YACjD,MAAM,CAAC,IAAI,CAAC,0CAA0C,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IAED,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,SAAS,GAAG,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,CAAC;QACrE,MAAM,MAAM,GAAG;YACb,kBAAkB,EAAE;gBAClB,aAAa,EAAE,SAAS;gBACxB,GAAG,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,OAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxE,iBAAiB,EAAE,uCAAuC;aAC3D;SACF,CAAC;QACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;QAC7C,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;YACxB,MAAM,SAAS,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,MAAM,SAAS,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC/D,MAAM,SAAS,GAAG,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,CAAC;QACrE,MAAM,MAAM,GAAG;YACb,kBAAkB,EAAE;gBAClB,aAAa,EAAE,SAAS;gBACxB,GAAG,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,OAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACxE,iBAAiB,EAAE,8BAA8B,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI;aAC5G;SACF,CAAC;QACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED,6DAA6D;AAC7D,SAAS,eAAe,CAAC,KAAa,EAAE,WAAmB;IACzD,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAChC,MAAM,kBAAkB,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IACtE,MAAM,cAAc,GAAG,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IACrE,IAAI,CAAC,kBAAkB,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,oCAAoC,KAAK,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,0DAA0D;AAE1D,KAAK,UAAU,UAAU,CAAC,OAAe;IACvC,yEAAyE;IACzE,oDAAoD;IACpD,MAAM,SAAS,GAAG,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,YAAY,CAAC;IACnE,MAAM,YAAY,GAAG,OAAO,KAAK,OAAO,CAAC;IACzC,MAAM,OAAO,GAAG,CAAC,SAAS,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1E,MAAM,OAAO,GAAG,CAAC,SAAS,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAEhF,IAAI,SAAS,IAAI,CAAC,OAAO,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,wBAAwB,OAAO,2BAA2B,CAAC,CAAC;QAC1E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACtD,UAAU,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAEhC,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,iBAAiB,WAAW,KAAK,CAAC,CAAC;YAC/C,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC;YAClD,MAAM,KAAK,GAAG,eAAe,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAC/C,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;YACpC,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;YAC/C,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YACpD,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YACpD,OAAO,CAAC,GAAG,CAAC,gBAAgB,OAAO,CAAC,WAAW,EAAE,uBAAuB,CAAC,EAAE,CAAC,CAAC;YAC7E,MAAM;QACR,CAAC;QAED,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;YAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;YAC3B,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;gBAChF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC;YACzC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;YAChD,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC;YAC9C,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAChF,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;YAC5F,MAAM;QACR,CAAC;QAED,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,CAAC;YAC7C,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAQ,EAAE,WAAW,CAAC,CAAC;YACxD,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YAClD,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC;YACxC,MAAM;QACR,CAAC;QAED,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,CAAC;YAC7C,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;YAChC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC;YACxC,MAAM;QACR,CAAC;QAED,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,CAAC;YAC7C,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAQ,EAAE,WAAW,CAAC,CAAC;YACxD,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YACjD,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;YAC5C,MAAM;QACR,CAAC;QAED,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,CAAC;YAC7C,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC9E,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;YAC/C,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;YACvC,MAAM;QACR,CAAC;QAED,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,CAAC;YAC7C,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;YACrC,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC;YACxC,MAAM;QACR,CAAC;QAED,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,CAAC;YAC7C,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;YACpC,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;YAC5C,MAAM;QACR,CAAC;QAED,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;YAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;YAC3B,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;gBAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,MAAM,QAAQ,GAAG,KAAK,CAAC,YAAY,EAAE,CAAC;YACtC,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YAC7C,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC,CAAC;YAC3C,MAAM;QACR,CAAC;IACH,CAAC;AACH,CAAC;AAED,eAAe;AAEf,KAAK,UAAU,IAAI;IACjB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAEhC,IAAI,CAAC,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAChD,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;QACnE,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;QACjE,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;QACnE,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,0EAA0E,CAAC,CAAC;QACxF,OAAO,CAAC,GAAG,CAAC,mEAAmE,CAAC,CAAC;QACjF,OAAO,CAAC,GAAG,CAAC,uEAAuE,CAAC,CAAC;QACrF,OAAO,CAAC,GAAG,CAAC,kEAAkE,CAAC,CAAC;QAChF,OAAO,CAAC,GAAG,CAAC,sEAAsE,CAAC,CAAC;QACpF,OAAO,CAAC,GAAG,CAAC,uEAAuE,CAAC,CAAC;QACrF,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC;IAED,IAAI,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;SAAM,CAAC;QACN,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,kBAAkB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC1F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Logique d'indexation partagee entre le serveur MCP et le CLI.
3
+ * Un seul endroit pour ajouter un nouveau parser.
4
+ */
5
+ import { IndexStore } from '../storage/index-store.js';
6
+ import type { ProjectIndex } from '../storage/index-store.js';
7
+ export interface IndexStats {
8
+ total: number;
9
+ parsed: number;
10
+ skipped: number;
11
+ removed: number;
12
+ }
13
+ /** Indexe un projet (complet ou incremental) */
14
+ export declare function indexProject(projectRoot: string, options?: {
15
+ incremental?: boolean;
16
+ store?: IndexStore;
17
+ }): Promise<{
18
+ index: ProjectIndex;
19
+ stats: IndexStats;
20
+ }>;
21
+ //# sourceMappingURL=indexer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.d.ts","sourceRoot":"","sources":["../../src/core/indexer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAK9D,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,gDAAgD;AAChD,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,UAAU,CAAA;CAAO,GAC1D,OAAO,CAAC;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,CAAC,CAwFrD"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Logique d'indexation partagee entre le serveur MCP et le CLI.
3
+ * Un seul endroit pour ajouter un nouveau parser.
4
+ */
5
+ import { statSync } from 'node:fs';
6
+ import { TypeScriptParser } from '../parsers/typescript-parser.js';
7
+ import { parsePrismaSchema, prismaSchemaToFileNode } from '../parsers/prisma-parser.js';
8
+ import { scanProject } from '../utils/scanner.js';
9
+ import { IndexStore } from '../storage/index-store.js';
10
+ import { logger } from '../utils/logger.js';
11
+ const tsParser = new TypeScriptParser();
12
+ /** Indexe un projet (complet ou incremental) */
13
+ export async function indexProject(projectRoot, options = {}) {
14
+ const store = options.store ?? new IndexStore(projectRoot);
15
+ const incremental = options.incremental ?? false;
16
+ // Sauvegarder le snapshot avant de re-indexer
17
+ if (store.exists())
18
+ store.saveSnapshot();
19
+ const scan = scanProject(projectRoot);
20
+ logger.info('Scan termine', {
21
+ files: scan.files.length,
22
+ dirs: scan.scannedDirs,
23
+ ignored: scan.ignoredDirs,
24
+ duration: scan.duration,
25
+ });
26
+ const tsFiles = scan.files.filter((f) => tsParser.canParse(f));
27
+ const existing = incremental ? store.load() : null;
28
+ let parsed = 0;
29
+ let skipped = 0;
30
+ let removed = 0;
31
+ const index = {
32
+ projectRoot,
33
+ indexedAt: Date.now(),
34
+ fileCount: 0,
35
+ files: existing?.files ?? {},
36
+ };
37
+ // Determiner les fichiers a re-parser
38
+ const filesToParse = [];
39
+ for (const filePath of tsFiles) {
40
+ if (incremental && existing?.files[filePath]) {
41
+ try {
42
+ const mtime = statSync(filePath).mtimeMs;
43
+ if (mtime <= existing.files[filePath].parsedAt) {
44
+ skipped++;
45
+ continue;
46
+ }
47
+ }
48
+ catch {
49
+ // Fichier inaccessible — le re-parser
50
+ }
51
+ }
52
+ filesToParse.push(filePath);
53
+ }
54
+ // Parser les fichiers TS
55
+ const nodes = await tsParser.parseFiles(filesToParse);
56
+ parsed = nodes.length;
57
+ for (const node of nodes) {
58
+ index.files[node.filePath] = node;
59
+ }
60
+ // Parser les fichiers Prisma
61
+ const prismaFiles = scan.files.filter((f) => f.endsWith('.prisma'));
62
+ for (const prismaFile of prismaFiles) {
63
+ if (incremental && existing?.files[prismaFile]) {
64
+ try {
65
+ const mtime = statSync(prismaFile).mtimeMs;
66
+ if (mtime <= existing.files[prismaFile].parsedAt)
67
+ continue;
68
+ }
69
+ catch { /* re-parser */ }
70
+ }
71
+ try {
72
+ const schema = parsePrismaSchema(prismaFile);
73
+ const node = prismaSchemaToFileNode(schema);
74
+ index.files[node.filePath] = node;
75
+ parsed++;
76
+ }
77
+ catch (error) {
78
+ logger.warn('Prisma parsing echoue', { file: prismaFile, error: String(error) });
79
+ }
80
+ }
81
+ // Supprimer les fichiers qui n'existent plus
82
+ if (incremental && existing) {
83
+ const currentFiles = new Set([...tsFiles, ...prismaFiles]);
84
+ for (const filePath of Object.keys(index.files)) {
85
+ if (!currentFiles.has(filePath)) {
86
+ delete index.files[filePath];
87
+ removed++;
88
+ }
89
+ }
90
+ }
91
+ index.fileCount = Object.keys(index.files).length;
92
+ store.save(index);
93
+ logger.info('Indexation complete', { fileCount: index.fileCount, parsed, skipped, removed });
94
+ return { index, stats: { total: tsFiles.length, parsed, skipped, removed } };
95
+ }
96
+ //# sourceMappingURL=indexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"indexer.js","sourceRoot":"","sources":["../../src/core/indexer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Graphe de dependances oriente.
3
+ * Chaque fichier est un noeud, chaque import est une arete.
4
+ * Permet de naviguer dans les deux sens :
5
+ * - dependsOn : "ce fichier depend de..."
6
+ * - dependedBy : "ce fichier est utilise par..."
7
+ */
8
+ import type { ProjectIndex } from '../storage/index-store.js';
9
+ export interface DependencyEdge {
10
+ from: string;
11
+ to: string;
12
+ imports: string[];
13
+ }
14
+ export declare class DependencyGraph {
15
+ /** Fichier → fichiers dont il depend */
16
+ private dependsOn;
17
+ /** Fichier → fichiers qui l'utilisent */
18
+ private dependedBy;
19
+ /** Aretes indexees par cle "from|||to" pour lookup O(1) */
20
+ private edgeMap;
21
+ /** Construit le graphe a partir de l'index du projet */
22
+ static fromIndex(index: ProjectIndex): DependencyGraph;
23
+ private addEdge;
24
+ /** Fichiers dont `filePath` depend directement */
25
+ getDependencies(filePath: string): string[];
26
+ /** Fichiers qui importent `filePath` directement */
27
+ getDependents(filePath: string): string[];
28
+ /** Tous les fichiers qui importent `filePath`, directement ou en cascade (BFS) */
29
+ getTransitiveDependents(filePath: string): string[];
30
+ /** Toutes les aretes du graphe */
31
+ getEdges(): DependencyEdge[];
32
+ /** Nombre de noeuds uniques */
33
+ getNodeCount(): number;
34
+ /** Nombre d'aretes */
35
+ getEdgeCount(): number;
36
+ }
37
+ //# sourceMappingURL=dependency-graph.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependency-graph.d.ts","sourceRoot":"","sources":["../../src/graph/dependency-graph.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAG9D,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,qBAAa,eAAe;IAC1B,wCAAwC;IACxC,OAAO,CAAC,SAAS,CAAkC;IACnD,yCAAyC;IACzC,OAAO,CAAC,UAAU,CAAkC;IACpD,2DAA2D;IAC3D,OAAO,CAAC,OAAO,CAAqC;IAEpD,wDAAwD;IACxD,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,YAAY,GAAG,eAAe;IAgBtD,OAAO,CAAC,OAAO;IAmBf,kDAAkD;IAClD,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAI3C,oDAAoD;IACpD,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAIzC,kFAAkF;IAClF,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE;IAoBnD,kCAAkC;IAClC,QAAQ,IAAI,cAAc,EAAE;IAI5B,+BAA+B;IAC/B,YAAY,IAAI,MAAM;IAStB,sBAAsB;IACtB,YAAY,IAAI,MAAM;CAGvB"}