memento-mcp-server 1.16.1 → 1.16.2-a

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 (163) hide show
  1. package/dist/client/index.d.ts.map +1 -1
  2. package/dist/client/index.js +4 -3
  3. package/dist/client/index.js.map +1 -1
  4. package/dist/domains/anchor/services/anchor/anchor-interfaces.d.ts +2 -4
  5. package/dist/domains/anchor/services/anchor/anchor-interfaces.d.ts.map +1 -1
  6. package/dist/domains/anchor/services/anchor/anchor-interfaces.js.map +1 -1
  7. package/dist/domains/anchor/services/anchor/anchor-manager.d.ts +2 -2
  8. package/dist/domains/anchor/services/anchor/anchor-manager.d.ts.map +1 -1
  9. package/dist/domains/anchor/services/anchor/anchor-manager.js.map +1 -1
  10. package/dist/domains/anchor/services/anchor/anchor-search-service.d.ts +11 -34
  11. package/dist/domains/anchor/services/anchor/anchor-search-service.d.ts.map +1 -1
  12. package/dist/domains/anchor/services/anchor/anchor-search-service.js +66 -549
  13. package/dist/domains/anchor/services/anchor/anchor-search-service.js.map +1 -1
  14. package/dist/domains/anchor/services/anchor/database-types.d.ts +28 -0
  15. package/dist/domains/anchor/services/anchor/database-types.d.ts.map +1 -0
  16. package/dist/domains/anchor/services/anchor/database-types.js +6 -0
  17. package/dist/domains/anchor/services/anchor/database-types.js.map +1 -0
  18. package/dist/domains/anchor/services/anchor/embedding-types.d.ts +20 -0
  19. package/dist/domains/anchor/services/anchor/embedding-types.d.ts.map +1 -0
  20. package/dist/domains/anchor/services/anchor/embedding-types.js +6 -0
  21. package/dist/domains/anchor/services/anchor/embedding-types.js.map +1 -0
  22. package/dist/domains/anchor/services/anchor/fallback-search-service.d.ts +36 -0
  23. package/dist/domains/anchor/services/anchor/fallback-search-service.d.ts.map +1 -0
  24. package/dist/domains/anchor/services/anchor/fallback-search-service.js +85 -0
  25. package/dist/domains/anchor/services/anchor/fallback-search-service.js.map +1 -0
  26. package/dist/domains/anchor/services/anchor/fallback-strategy.d.ts +25 -0
  27. package/dist/domains/anchor/services/anchor/fallback-strategy.d.ts.map +1 -0
  28. package/dist/domains/anchor/services/anchor/fallback-strategy.js +35 -0
  29. package/dist/domains/anchor/services/anchor/fallback-strategy.js.map +1 -0
  30. package/dist/domains/anchor/services/anchor/local-search-service.d.ts +72 -0
  31. package/dist/domains/anchor/services/anchor/local-search-service.d.ts.map +1 -0
  32. package/dist/domains/anchor/services/anchor/local-search-service.js +129 -0
  33. package/dist/domains/anchor/services/anchor/local-search-service.js.map +1 -0
  34. package/dist/domains/anchor/services/anchor/n-hop-search-service.d.ts +90 -0
  35. package/dist/domains/anchor/services/anchor/n-hop-search-service.d.ts.map +1 -0
  36. package/dist/domains/anchor/services/anchor/n-hop-search-service.js +385 -0
  37. package/dist/domains/anchor/services/anchor/n-hop-search-service.js.map +1 -0
  38. package/dist/domains/anchor/services/anchor/n-hop-search-strategy.d.ts +24 -0
  39. package/dist/domains/anchor/services/anchor/n-hop-search-strategy.d.ts.map +1 -0
  40. package/dist/domains/anchor/services/anchor/n-hop-search-strategy.js +39 -0
  41. package/dist/domains/anchor/services/anchor/n-hop-search-strategy.js.map +1 -0
  42. package/dist/domains/anchor/services/anchor/query-filter-service.d.ts +52 -0
  43. package/dist/domains/anchor/services/anchor/query-filter-service.d.ts.map +1 -0
  44. package/dist/domains/anchor/services/anchor/query-filter-service.js +136 -0
  45. package/dist/domains/anchor/services/anchor/query-filter-service.js.map +1 -0
  46. package/dist/domains/anchor/services/anchor/query-filter-strategy.d.ts +24 -0
  47. package/dist/domains/anchor/services/anchor/query-filter-strategy.d.ts.map +1 -0
  48. package/dist/domains/anchor/services/anchor/query-filter-strategy.js +34 -0
  49. package/dist/domains/anchor/services/anchor/query-filter-strategy.js.map +1 -0
  50. package/dist/domains/anchor/services/anchor/search-strategy-interfaces.d.ts +52 -0
  51. package/dist/domains/anchor/services/anchor/search-strategy-interfaces.d.ts.map +1 -0
  52. package/dist/domains/anchor/services/anchor/search-strategy-interfaces.js +6 -0
  53. package/dist/domains/anchor/services/anchor/search-strategy-interfaces.js.map +1 -0
  54. package/dist/domains/anchor/services/anchor/vector-search-engine-types.d.ts +18 -0
  55. package/dist/domains/anchor/services/anchor/vector-search-engine-types.d.ts.map +1 -0
  56. package/dist/domains/anchor/services/anchor/vector-search-engine-types.js +11 -0
  57. package/dist/domains/anchor/services/anchor/vector-search-engine-types.js.map +1 -0
  58. package/dist/domains/memory/repositories/core-memory-database.interface.d.ts +47 -0
  59. package/dist/domains/memory/repositories/core-memory-database.interface.d.ts.map +1 -0
  60. package/dist/domains/memory/repositories/core-memory-database.interface.js +7 -0
  61. package/dist/domains/memory/repositories/core-memory-database.interface.js.map +1 -0
  62. package/dist/domains/memory/repositories/core-memory-repository.d.ts +7 -77
  63. package/dist/domains/memory/repositories/core-memory-repository.d.ts.map +1 -1
  64. package/dist/domains/memory/repositories/core-memory-repository.interface.d.ts +92 -0
  65. package/dist/domains/memory/repositories/core-memory-repository.interface.d.ts.map +1 -0
  66. package/dist/domains/memory/repositories/core-memory-repository.interface.js +6 -0
  67. package/dist/domains/memory/repositories/core-memory-repository.interface.js.map +1 -0
  68. package/dist/domains/memory/repositories/core-memory-repository.js +7 -259
  69. package/dist/domains/memory/repositories/core-memory-repository.js.map +1 -1
  70. package/dist/domains/memory/services/core-memory-cache-service.d.ts +55 -0
  71. package/dist/domains/memory/services/core-memory-cache-service.d.ts.map +1 -1
  72. package/dist/domains/memory/services/core-memory-cache-service.js +110 -8
  73. package/dist/domains/memory/services/core-memory-cache-service.js.map +1 -1
  74. package/dist/domains/memory/services/core-memory-service.d.ts +2 -2
  75. package/dist/domains/memory/services/core-memory-service.d.ts.map +1 -1
  76. package/dist/domains/memory/services/core-memory-service.js +43 -24
  77. package/dist/domains/memory/services/core-memory-service.js.map +1 -1
  78. package/dist/domains/memory/tools/recall-tool.d.ts.map +1 -1
  79. package/dist/domains/memory/tools/recall-tool.js +2 -2
  80. package/dist/domains/memory/tools/recall-tool.js.map +1 -1
  81. package/dist/domains/memory/tools/remember-tool.d.ts.map +1 -1
  82. package/dist/domains/memory/tools/remember-tool.js +2 -2
  83. package/dist/domains/memory/tools/remember-tool.js.map +1 -1
  84. package/dist/domains/monitoring/services/performance-monitor.d.ts +8 -0
  85. package/dist/domains/monitoring/services/performance-monitor.d.ts.map +1 -1
  86. package/dist/domains/monitoring/services/performance-monitor.js +16 -0
  87. package/dist/domains/monitoring/services/performance-monitor.js.map +1 -1
  88. package/dist/infrastructure/async-optimizer.d.ts.map +1 -1
  89. package/dist/infrastructure/async-optimizer.js +8 -7
  90. package/dist/infrastructure/async-optimizer.js.map +1 -1
  91. package/dist/infrastructure/database/adapters/sqlite-core-memory-adapter.d.ts +31 -0
  92. package/dist/infrastructure/database/adapters/sqlite-core-memory-adapter.d.ts.map +1 -0
  93. package/dist/infrastructure/database/adapters/sqlite-core-memory-adapter.js +112 -0
  94. package/dist/infrastructure/database/adapters/sqlite-core-memory-adapter.js.map +1 -0
  95. package/dist/infrastructure/database/database/init.d.ts.map +1 -1
  96. package/dist/infrastructure/database/database/init.js +23 -2
  97. package/dist/infrastructure/database/database/init.js.map +1 -1
  98. package/dist/infrastructure/database/database/migration/migrations/010-add-core-memory-version.d.ts +64 -0
  99. package/dist/infrastructure/database/database/migration/migrations/010-add-core-memory-version.d.ts.map +1 -0
  100. package/dist/infrastructure/database/database/migration/migrations/010-add-core-memory-version.js +174 -0
  101. package/dist/infrastructure/database/database/migration/migrations/010-add-core-memory-version.js.map +1 -0
  102. package/dist/infrastructure/database/database/migration/migrations/010-add-core-memory-version.sql +25 -0
  103. package/dist/infrastructure/database/database-lock-monitor.d.ts +105 -0
  104. package/dist/infrastructure/database/database-lock-monitor.d.ts.map +1 -0
  105. package/dist/infrastructure/database/database-lock-monitor.js +265 -0
  106. package/dist/infrastructure/database/database-lock-monitor.js.map +1 -0
  107. package/dist/infrastructure/database/factories/core-memory-repository.factory.d.ts +17 -0
  108. package/dist/infrastructure/database/factories/core-memory-repository.factory.d.ts.map +1 -0
  109. package/dist/infrastructure/database/factories/core-memory-repository.factory.js +43 -0
  110. package/dist/infrastructure/database/factories/core-memory-repository.factory.js.map +1 -0
  111. package/dist/infrastructure/database/repositories/core-memory-repository-sqlite.impl.d.ts +63 -0
  112. package/dist/infrastructure/database/repositories/core-memory-repository-sqlite.impl.d.ts.map +1 -0
  113. package/dist/infrastructure/database/repositories/core-memory-repository-sqlite.impl.js +281 -0
  114. package/dist/infrastructure/database/repositories/core-memory-repository-sqlite.impl.js.map +1 -0
  115. package/dist/infrastructure/database/wal-checkpoint-scheduler.d.ts +166 -0
  116. package/dist/infrastructure/database/wal-checkpoint-scheduler.d.ts.map +1 -0
  117. package/dist/infrastructure/database/wal-checkpoint-scheduler.js +285 -0
  118. package/dist/infrastructure/database/wal-checkpoint-scheduler.js.map +1 -0
  119. package/dist/npm-client/memento-client.d.ts.map +1 -1
  120. package/dist/npm-client/memento-client.js +5 -4
  121. package/dist/npm-client/memento-client.js.map +1 -1
  122. package/dist/npm-client/memory-manager.d.ts.map +1 -1
  123. package/dist/npm-client/memory-manager.js +4 -3
  124. package/dist/npm-client/memory-manager.js.map +1 -1
  125. package/dist/scripts/check-migration-status.d.ts.map +1 -1
  126. package/dist/scripts/check-migration-status.js +1 -0
  127. package/dist/scripts/check-migration-status.js.map +1 -1
  128. package/dist/server/bootstrap.d.ts +4 -0
  129. package/dist/server/bootstrap.d.ts.map +1 -1
  130. package/dist/server/bootstrap.js +27 -2
  131. package/dist/server/bootstrap.js.map +1 -1
  132. package/dist/server/http-server.d.ts.map +1 -1
  133. package/dist/server/http-server.js +59 -31
  134. package/dist/server/http-server.js.map +1 -1
  135. package/dist/server/index.js +32 -16
  136. package/dist/server/index.js.map +1 -1
  137. package/dist/server/simple-mcp-server.d.ts.map +1 -1
  138. package/dist/server/simple-mcp-server.js +15 -14
  139. package/dist/server/simple-mcp-server.js.map +1 -1
  140. package/dist/shared/config/environment.d.ts.map +1 -1
  141. package/dist/shared/config/environment.js +13 -1
  142. package/dist/shared/config/environment.js.map +1 -1
  143. package/dist/shared/config/index.d.ts.map +1 -1
  144. package/dist/shared/config/index.js +13 -1
  145. package/dist/shared/config/index.js.map +1 -1
  146. package/dist/shared/types/index.d.ts +10 -0
  147. package/dist/shared/types/index.d.ts.map +1 -1
  148. package/dist/tools/base-tool.d.ts.map +1 -1
  149. package/dist/tools/base-tool.js +5 -4
  150. package/dist/tools/base-tool.js.map +1 -1
  151. package/dist/tools/migrate-embeddings-tool.d.ts.map +1 -1
  152. package/dist/tools/migrate-embeddings-tool.js +2 -1
  153. package/dist/tools/migrate-embeddings-tool.js.map +1 -1
  154. package/dist/tools/tool-registry.d.ts.map +1 -1
  155. package/dist/tools/tool-registry.js +4 -3
  156. package/dist/tools/tool-registry.js.map +1 -1
  157. package/dist/workers/consolidation-score-worker.d.ts.map +1 -1
  158. package/dist/workers/consolidation-score-worker.js +5 -4
  159. package/dist/workers/consolidation-score-worker.js.map +1 -1
  160. package/package.json +1 -1
  161. package/scripts/check-file-sizes.ts +405 -0
  162. package/scripts/count-any-types.ts +375 -0
  163. package/scripts/count-console-logs.ts +451 -0
@@ -0,0 +1,451 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * console.log 개수 측정 스크립트
4
+ *
5
+ * PRD 0017: 코드 품질 개선 - 로깅 일원화
6
+ *
7
+ * 사용법:
8
+ * tsx scripts/count-console-logs.ts
9
+ * tsx scripts/count-console-logs.ts --ci
10
+ * tsx scripts/count-console-logs.ts --core-only
11
+ * tsx scripts/count-console-logs.ts --directory src/
12
+ *
13
+ * 목표:
14
+ * - 핵심 모듈 console.log 0개
15
+ * - 전체 console.log 단계적 감소
16
+ * - CI/CD 통합 가능
17
+ */
18
+
19
+ import { readFileSync } from 'fs';
20
+ import { readdir } from 'fs/promises';
21
+ import { join, relative } from 'path';
22
+
23
+ /**
24
+ * CLI 옵션
25
+ */
26
+ interface CliOptions {
27
+ ci?: boolean;
28
+ coreOnly?: boolean;
29
+ directory?: string;
30
+ exclude?: string[];
31
+ target?: number;
32
+ allowSoftFail?: boolean;
33
+ }
34
+
35
+ /**
36
+ * console.* 발견 위치
37
+ */
38
+ interface ConsoleLogLocation {
39
+ file: string;
40
+ line: number;
41
+ column: number;
42
+ method: string; // log, error, warn, info, debug
43
+ context: string;
44
+ }
45
+
46
+ /**
47
+ * 측정 결과
48
+ */
49
+ interface CountResult {
50
+ total: number;
51
+ coreTotal: number;
52
+ locations: ConsoleLogLocation[];
53
+ byFile: Map<string, number>;
54
+ byMethod: Map<string, number>;
55
+ }
56
+
57
+ /**
58
+ * 명령줄 인자 파싱
59
+ */
60
+ function parseArgs(): CliOptions {
61
+ const args = process.argv.slice(2);
62
+ const options: CliOptions = {
63
+ exclude: ['**/node_modules/**', '**/dist/**', '**/*.d.ts']
64
+ };
65
+
66
+ for (let i = 0; i < args.length; i++) {
67
+ const arg = args[i];
68
+ if (arg === '--ci') {
69
+ options.ci = true;
70
+ } else if (arg === '--core-only') {
71
+ options.coreOnly = true;
72
+ } else if (arg === '--directory' && args[i + 1]) {
73
+ options.directory = args[i + 1];
74
+ i++;
75
+ } else if (arg === '--exclude' && args[i + 1]) {
76
+ if (!options.exclude) {
77
+ options.exclude = [];
78
+ }
79
+ options.exclude.push(args[i + 1]);
80
+ i++;
81
+ } else if (arg === '--target' && args[i + 1]) {
82
+ options.target = parseInt(args[i + 1], 10);
83
+ i++;
84
+ } else if (arg === '--allow-soft-fail') {
85
+ options.allowSoftFail = true;
86
+ } else if (arg === '--help' || arg === '-h') {
87
+ printHelp();
88
+ process.exit(0);
89
+ }
90
+ }
91
+
92
+ return options;
93
+ }
94
+
95
+ /**
96
+ * 도움말 출력
97
+ */
98
+ function printHelp(): void {
99
+ console.log(`
100
+ console.log 개수 측정 스크립트
101
+
102
+ 사용법:
103
+ tsx scripts/count-console-logs.ts [options]
104
+
105
+ 옵션:
106
+ --ci CI 모드 (실패 시 exit code 1 반환)
107
+ --core-only 핵심 모듈만 검사 (src/server/, src/services/)
108
+ --directory <path> 검사할 디렉토리 (기본값: src/)
109
+ --exclude <pattern> 제외할 파일 패턴 (여러 번 사용 가능)
110
+ --target <number> 목표 개수 (기본값: 핵심 모듈 0개, 전체 200개)
111
+ --allow-soft-fail CI 모드에서 경고만 출력하고 통과
112
+ --help, -h 도움말 출력
113
+
114
+ 예제:
115
+ tsx scripts/count-console-logs.ts
116
+ tsx scripts/count-console-logs.ts --ci
117
+ tsx scripts/count-console-logs.ts --core-only
118
+ tsx scripts/count-console-logs.ts --directory src/ --exclude "**/*.spec.ts"
119
+ `);
120
+ }
121
+
122
+ /**
123
+ * 핵심 모듈인지 확인
124
+ */
125
+ function isCoreModule(filePath: string): boolean {
126
+ return filePath.includes('src/server/') || filePath.includes('src/services/');
127
+ }
128
+
129
+ /**
130
+ * 테스트 파일인지 확인
131
+ */
132
+ function isTestFile(filePath: string): boolean {
133
+ return filePath.endsWith('.spec.ts') ||
134
+ filePath.includes('test-') ||
135
+ filePath.includes('/test/') ||
136
+ filePath.includes('/__tests__/');
137
+ }
138
+
139
+ /**
140
+ * CLI 스크립트인지 확인
141
+ */
142
+ function isCliScript(filePath: string): boolean {
143
+ return filePath.includes('scripts/');
144
+ }
145
+
146
+ /**
147
+ * 패턴 매칭
148
+ */
149
+ function matchesPattern(path: string, pattern: string): boolean {
150
+ if (pattern.includes('**/node_modules/**')) {
151
+ return path.includes('node_modules');
152
+ }
153
+ if (pattern.includes('**/dist/**')) {
154
+ return path.includes('dist');
155
+ }
156
+ if (pattern.includes('**/*.spec.ts')) {
157
+ return path.endsWith('.spec.ts');
158
+ }
159
+ if (pattern.includes('**/*.d.ts')) {
160
+ return path.endsWith('.d.ts');
161
+ }
162
+ return false;
163
+ }
164
+
165
+ /**
166
+ * 파일이 제외 패턴에 해당하는지 확인
167
+ */
168
+ function shouldExclude(filePath: string, exclude: string[]): boolean {
169
+ for (const pattern of exclude) {
170
+ if (matchesPattern(filePath, pattern)) {
171
+ return true;
172
+ }
173
+ }
174
+ return false;
175
+ }
176
+
177
+ /**
178
+ * 파일 검색 (재귀적)
179
+ */
180
+ async function findFiles(directory: string, exclude: string[]): Promise<string[]> {
181
+ const files: string[] = [];
182
+ const absoluteDir = join(process.cwd(), directory);
183
+
184
+ async function walkDir(dir: string): Promise<void> {
185
+ try {
186
+ const { readdir } = await import('fs/promises');
187
+ const entries = await readdir(dir, { withFileTypes: true });
188
+
189
+ for (const entry of entries) {
190
+ const fullPath = join(dir, entry.name);
191
+
192
+ if (shouldExclude(fullPath, exclude)) {
193
+ continue;
194
+ }
195
+
196
+ if (entry.isDirectory()) {
197
+ await walkDir(fullPath);
198
+ } else if (entry.isFile() && entry.name.endsWith('.ts')) {
199
+ files.push(fullPath);
200
+ }
201
+ }
202
+ } catch (error) {
203
+ // 디렉토리 읽기 실패 시 무시
204
+ }
205
+ }
206
+
207
+ await walkDir(absoluteDir);
208
+ return files;
209
+ }
210
+
211
+ /**
212
+ * 파일에서 console.* 찾기
213
+ */
214
+ function findConsoleLogs(filePath: string): ConsoleLogLocation[] {
215
+ const locations: ConsoleLogLocation[] = [];
216
+
217
+ try {
218
+ const content = readFileSync(filePath, 'utf-8');
219
+ const lines = content.split('\n');
220
+
221
+ // console.log, console.error, console.warn, console.info, console.debug 패턴
222
+ const consolePattern = /console\.(log|error|warn|info|debug)\s*\(/g;
223
+
224
+ for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
225
+ const line = lines[lineIndex];
226
+
227
+ // 주석 제외
228
+ if (line.trim().startsWith('//')) {
229
+ continue;
230
+ }
231
+
232
+ // 문자열 내부 제외 (간단한 휴리스틱)
233
+ const inString = (line.match(/['"]/g) || []).length % 2 === 1;
234
+ if (inString) {
235
+ continue;
236
+ }
237
+
238
+ // console.* 패턴 검색
239
+ let match;
240
+ while ((match = consolePattern.exec(line)) !== null) {
241
+ locations.push({
242
+ file: filePath,
243
+ line: lineIndex + 1,
244
+ column: match.index + 1,
245
+ method: match[1],
246
+ context: line.trim()
247
+ });
248
+ }
249
+ }
250
+ } catch (error) {
251
+ // 파일 읽기 실패 시 무시
252
+ }
253
+
254
+ return locations;
255
+ }
256
+
257
+ /**
258
+ * console.log 개수 측정
259
+ */
260
+ function countConsoleLogs(files: string[], coreOnly: boolean): CountResult {
261
+ const locations: ConsoleLogLocation[] = [];
262
+ const byFile = new Map<string, number>();
263
+ const byMethod = new Map<string, number>();
264
+
265
+ for (const file of files) {
266
+ // 테스트 파일과 CLI 스크립트는 제외
267
+ if (isTestFile(file) || isCliScript(file)) {
268
+ continue;
269
+ }
270
+
271
+ // 핵심 모듈만 검사하는 경우
272
+ if (coreOnly && !isCoreModule(file)) {
273
+ continue;
274
+ }
275
+
276
+ const fileLocations = findConsoleLogs(file);
277
+ locations.push(...fileLocations);
278
+
279
+ if (fileLocations.length > 0) {
280
+ byFile.set(file, fileLocations.length);
281
+
282
+ for (const loc of fileLocations) {
283
+ const count = byMethod.get(loc.method) || 0;
284
+ byMethod.set(loc.method, count + 1);
285
+ }
286
+ }
287
+ }
288
+
289
+ // 핵심 모듈 개수 계산
290
+ const coreLocations = locations.filter(loc => isCoreModule(loc.file));
291
+
292
+ return {
293
+ total: locations.length,
294
+ coreTotal: coreLocations.length,
295
+ locations,
296
+ byFile,
297
+ byMethod
298
+ };
299
+ }
300
+
301
+ /**
302
+ * 결과 출력
303
+ */
304
+ function printResults(
305
+ result: CountResult,
306
+ target: number,
307
+ coreTarget: number,
308
+ projectRoot: string,
309
+ coreOnly: boolean
310
+ ): void {
311
+ console.log('\n📊 console.log 개수 측정 결과\n');
312
+
313
+ if (coreOnly) {
314
+ console.log(`핵심 모듈 console.* 개수: ${result.coreTotal}개`);
315
+ console.log(`목표 개수: ${coreTarget}개 이하`);
316
+
317
+ if (result.coreTotal > coreTarget) {
318
+ console.log(`⚠️ 목표 대비: ${result.coreTotal - coreTarget}개 초과\n`);
319
+ } else {
320
+ console.log(`✅ 목표 달성\n`);
321
+ }
322
+ } else {
323
+ console.log(`전체 console.* 개수: ${result.total}개`);
324
+ console.log(`핵심 모듈 console.* 개수: ${result.coreTotal}개`);
325
+ console.log(`목표 개수: 전체 ${target}개 이하, 핵심 모듈 ${coreTarget}개 이하\n`);
326
+
327
+ if (result.coreTotal > coreTarget) {
328
+ console.log(`⚠️ 핵심 모듈 목표 대비: ${result.coreTotal - coreTarget}개 초과`);
329
+ }
330
+ if (result.total > target) {
331
+ console.log(`⚠️ 전체 목표 대비: ${result.total - target}개 초과`);
332
+ }
333
+ console.log('');
334
+ }
335
+
336
+ // 메서드별 통계
337
+ if (result.byMethod.size > 0) {
338
+ console.log('📈 메서드별 통계:');
339
+ const sortedMethods = Array.from(result.byMethod.entries())
340
+ .sort((a, b) => b[1] - a[1]);
341
+
342
+ for (const [method, count] of sortedMethods) {
343
+ console.log(` console.${method}: ${count}개`);
344
+ }
345
+ console.log('');
346
+ }
347
+
348
+ // 파일별 통계 (상위 10개)
349
+ if (result.byFile.size > 0) {
350
+ console.log('📁 파일별 console.* 개수 (상위 10개):');
351
+ const sortedFiles = Array.from(result.byFile.entries())
352
+ .sort((a, b) => b[1] - a[1])
353
+ .slice(0, 10);
354
+
355
+ for (const [file, count] of sortedFiles) {
356
+ const relativePath = relative(projectRoot, file);
357
+ const isCore = isCoreModule(file);
358
+ const marker = isCore ? '🔴' : ' ';
359
+ console.log(` ${marker} ${relativePath}: ${count}개`);
360
+ }
361
+ console.log('');
362
+ }
363
+
364
+ // 핵심 모듈 파일 목록
365
+ if (!coreOnly && result.coreTotal > 0) {
366
+ const coreFiles = Array.from(result.byFile.entries())
367
+ .filter(([file]) => isCoreModule(file))
368
+ .sort((a, b) => b[1] - a[1]);
369
+
370
+ if (coreFiles.length > 0) {
371
+ console.log('🔴 핵심 모듈 파일 목록:');
372
+ for (const [file, count] of coreFiles) {
373
+ const relativePath = relative(projectRoot, file);
374
+ console.log(` ${relativePath}: ${count}개`);
375
+ }
376
+ console.log('');
377
+ }
378
+ }
379
+ }
380
+
381
+ /**
382
+ * 메인 함수
383
+ */
384
+ async function main(): Promise<void> {
385
+ const options = parseArgs();
386
+ const projectRoot = process.cwd();
387
+ const directory = options.directory || 'src/';
388
+ const exclude = options.exclude || ['**/node_modules/**', '**/dist/**', '**/*.d.ts'];
389
+ const coreTarget = 0; // 핵심 모듈은 항상 0개 목표
390
+ const target = options.target || (options.coreOnly ? 0 : 200);
391
+
392
+ try {
393
+ // 파일 검색
394
+ const searchDir = options.coreOnly ? 'src/' : directory;
395
+ console.log(`🔍 파일 검색 중... (디렉토리: ${searchDir}${options.coreOnly ? ', 핵심 모듈만' : ''})`);
396
+ const files = await findFiles(searchDir, exclude);
397
+
398
+ if (files.length === 0) {
399
+ console.log('⚠️ 검사할 파일이 없습니다.');
400
+ process.exit(0);
401
+ }
402
+
403
+ console.log(` 발견된 파일: ${files.length}개\n`);
404
+
405
+ // console.log 개수 측정
406
+ console.log('🔎 console.* 검색 중...');
407
+ const result = countConsoleLogs(files, options.coreOnly || false);
408
+
409
+ // 결과 출력
410
+ printResults(result, target, coreTarget, projectRoot, options.coreOnly || false);
411
+
412
+ // CI 모드: exit code 처리
413
+ if (options.ci) {
414
+ const failed = options.coreOnly
415
+ ? result.coreTotal > coreTarget
416
+ : result.coreTotal > coreTarget || result.total > target;
417
+
418
+ if (failed) {
419
+ if (options.coreOnly) {
420
+ console.log(`❌ CI 실패: 핵심 모듈 console.*가 ${result.coreTotal}개로 목표(${coreTarget}개)를 초과했습니다.`);
421
+ } else {
422
+ console.log(`❌ CI 실패: 전체 ${result.total}개, 핵심 모듈 ${result.coreTotal}개로 목표를 초과했습니다.`);
423
+ }
424
+ process.exit(1);
425
+ } else {
426
+ console.log(`✅ CI 통과: 목표를 달성했습니다.`);
427
+ process.exit(0);
428
+ }
429
+ } else {
430
+ // 일반 모드: 정보만 출력
431
+ if (result.coreTotal > coreTarget || result.total > target) {
432
+ console.log('💡 팁: --ci 옵션을 사용하면 CI/CD 파이프라인에 통합할 수 있습니다.');
433
+ }
434
+ }
435
+ } catch (error) {
436
+ console.error('❌ 오류 발생:', error instanceof Error ? error.message : String(error));
437
+ if (error instanceof Error && error.stack) {
438
+ console.error(error.stack);
439
+ }
440
+ process.exit(1);
441
+ }
442
+ }
443
+
444
+ // 스크립트 직접 실행 시
445
+ if (import.meta.url === `file://${process.argv[1]}` || import.meta.url.endsWith(process.argv[1])) {
446
+ main().catch(error => {
447
+ console.error('❌ 치명적 오류:', error);
448
+ process.exit(1);
449
+ });
450
+ }
451
+