@axboot-mcp/mcp-server 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/CLAUDE.md +119 -0
  2. package/MCP_TOOL_PLAN.md +710 -0
  3. package/MCP_USAGE.md +914 -0
  4. package/README.md +168 -0
  5. package/REPOSITORY_CONVENTIONS.md +250 -0
  6. package/SEARCH_PARAMS_MCP_TOOL_COMPLETE_PLAN.md +646 -0
  7. package/SEARCH_PARAMS_PLAN.md +2570 -0
  8. package/STORE_PATTERNS.md +1178 -0
  9. package/debug-dto.js +72 -0
  10. package/generate-banner-store.js +62 -0
  11. package/generation-plan.json +2176 -0
  12. package/generation-results.json +1817 -0
  13. package/package.json +45 -0
  14. package/scripts/batch-generate-all.js +159 -0
  15. package/scripts/batch-generate-mcp.js +329 -0
  16. package/scripts/batch-generate-stores-v2.js +272 -0
  17. package/scripts/batch-generate-stores.js +179 -0
  18. package/scripts/batch-plan.json +3810 -0
  19. package/scripts/batch-process.py +90 -0
  20. package/scripts/batch-regenerate.js +356 -0
  21. package/scripts/direct-generate.js +227 -0
  22. package/scripts/execute-batches.js +1911 -0
  23. package/scripts/generate-all-stores.js +144 -0
  24. package/scripts/generate-stores-mcp.js +161 -0
  25. package/scripts/generate-stores-v2.js +450 -0
  26. package/scripts/generate-stores-v3.js +412 -0
  27. package/scripts/generate-stores-v4.js +521 -0
  28. package/scripts/generate-stores.js +382 -0
  29. package/scripts/repos-to-process.json +1899 -0
  30. package/src/config/nh-layout-patterns.ts +166 -0
  31. package/src/docs/HOOK_GENERATION_PLAN.md +2226 -0
  32. package/src/docs/NH_STORE_PATTERNS.md +297 -0
  33. package/src/docs/README.md +216 -0
  34. package/src/docs/index.ts +28 -0
  35. package/src/docs/loader.ts +568 -0
  36. package/src/docs/patterns.json +419 -0
  37. package/src/docs/practical-examples.md +732 -0
  38. package/src/docs/quick-start.md +257 -0
  39. package/src/docs/requirements-analysis-guide.md +364 -0
  40. package/src/docs/rules.json +321 -0
  41. package/src/docs/store-pattern-analysis.md +664 -0
  42. package/src/docs/store-patterns-rules.md +1168 -0
  43. package/src/docs/store-patterns-usage-guide.md +1835 -0
  44. package/src/docs/troubleshooting.md +544 -0
  45. package/src/docs/type-selection-guide.md +572 -0
  46. package/src/docs//354/202/254/354/232/251/353/262/225/AntD-/354/273/264/355/217/254/353/204/214/355/212/270-/354/202/254/354/232/251/353/262/225.md +1515 -0
  47. package/src/docs//354/202/254/354/232/251/353/262/225/DataGrid-/354/202/254/354/232/251/353/262/225.md +866 -0
  48. package/src/docs//354/202/254/354/232/251/353/262/225/FormItem-/354/202/254/354/232/251/353/262/225.md +903 -0
  49. package/src/docs//354/202/254/354/232/251/353/262/225/FormModal-/354/202/254/354/232/251/353/262/225.md +1155 -0
  50. package/src/docs//354/202/254/354/232/251/353/262/225/MCP-/353/260/224/354/235/264/353/270/214/354/275/224/353/224/251-/352/260/200/354/235/264/353/223/234.md +1133 -0
  51. package/src/docs//354/202/254/354/232/251/353/262/225/MSW-Mock-/353/215/260/354/235/264/355/204/260-/354/202/254/354/232/251/353/262/225.md +579 -0
  52. package/src/docs//354/202/254/354/232/251/353/262/225/Search-/354/273/264/355/217/254/353/204/214/355/212/270-/354/202/254/354/232/251/353/262/225.md +738 -0
  53. package/src/docs//354/202/254/354/232/251/353/262/225/Store-/355/214/250/355/204/264-/354/202/254/354/232/251/353/262/225.md +1135 -0
  54. package/src/docs//354/202/254/354/232/251/353/262/225//355/231/224/353/251/264/352/265/254/354/204/261-/355/203/200/354/236/205/353/263/204-/352/260/234/353/260/234/354/210/234/354/204/234.md +1805 -0
  55. package/src/docs//354/202/254/354/232/251/353/262/225//355/231/224/353/251/264/355/203/200/354/236/205/353/263/204-/352/260/234/353/260/234-/355/224/204/353/241/254/355/224/204/355/212/270-/352/260/200/354/235/264/353/223/234.md +946 -0
  56. package/src/docs//354/202/254/354/232/251/353/262/225//355/231/225/354/236/245/355/231/224/353/251/264/355/203/200/354/236/205/353/263/204-/354/203/201/354/204/270-/355/224/204/353/241/254/355/224/204/355/212/270/352/260/200/354/235/264/353/223/234.md +2422 -0
  57. package/src/features/store-features.ts +232 -0
  58. package/src/handlers/analyze-requirements.ts +403 -0
  59. package/src/handlers/analyze.ts +1373 -0
  60. package/src/handlers/generate-from-requirements.ts +250 -0
  61. package/src/handlers/generate-hook.ts +950 -0
  62. package/src/handlers/generate-interactive.ts +840 -0
  63. package/src/handlers/generate-listdatagrid.ts +521 -0
  64. package/src/handlers/generate-multi-stores.ts +577 -0
  65. package/src/handlers/generate-requirements-from-layout.ts +160 -0
  66. package/src/handlers/generate-search-params.ts +717 -0
  67. package/src/handlers/generate.ts +911 -0
  68. package/src/handlers/list-templates.ts +104 -0
  69. package/src/handlers/scan-metadata.ts +485 -0
  70. package/src/handlers/suggest-layout.ts +326 -0
  71. package/src/index.ts +959 -0
  72. package/src/prompts/search-params.md +793 -0
  73. package/src/templates/index.ts +107 -0
  74. package/src/templates/unified.ts +462 -0
  75. package/store-generation-error-patterns.md +225 -0
  76. package/test/useAgentStore.ts +136 -0
  77. package/test-server.js +78 -0
  78. package/tsconfig.json +20 -0
@@ -0,0 +1,382 @@
1
+ /**
2
+ * StoreNew.ts 파일 생성 스크립트
3
+ * 리포지토리 파일을 분석하여 StoreNew.ts 파일 생성
4
+ */
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+ const { parse } = require('@typescript-eslint/typescript-estree');
9
+
10
+ // 경로 설정
11
+ const REPO_DIR = '/Users/kyle/Desktop/nh-fe-bo/src/services/@interface/repository';
12
+ const STORE_DIR = '/Users/kyle/Desktop/nh-fe-bo/src/pages/resources/NH';
13
+ const TEMPLATE_DIR = path.join(__dirname, '../src/templates');
14
+
15
+ // 템플릿 가져오기
16
+ const templates = {
17
+ type1: fs.readFileSync(path.join(TEMPLATE_DIR, 'type1.ts'), 'utf-8'),
18
+ type2: fs.readFileSync(path.join(TEMPLATE_DIR, 'type2.ts'), 'utf-8'),
19
+ type3: fs.readFileSync(path.join(TEMPLATE_DIR, 'type3.ts'), 'utf-8'),
20
+ type6: fs.readFileSync(path.join(TEMPLATE_DIR, 'type6.ts'), 'utf-8'),
21
+ type7: fs.readFileSync(path.join(TEMPLATE_DIR, 'type7.ts'), 'utf-8'),
22
+ type8: fs.readFileSync(path.join(TEMPLATE_DIR, 'type8.ts'), 'utf-8'),
23
+ type9: fs.readFileSync(path.join(TEMPLATE_DIR, 'type9.ts'), 'utf-8'),
24
+ type10: fs.readFileSync(path.join(TEMPLATE_DIR, 'type10.ts'), 'utf-8'),
25
+ type11: fs.readFileSync(path.join(TEMPLATE_DIR, 'type11.ts'), 'utf-8'),
26
+ };
27
+
28
+ /**
29
+ * 리포지토리 파일에서 정보 추출
30
+ */
31
+ function analyzeRepository(filePath) {
32
+ const content = fs.readFileSync(filePath, 'utf-8');
33
+
34
+ // 클래스 이름 추출
35
+ const classNameMatch = content.match(/export class (\w+)Repository/);
36
+ const className = classNameMatch ? classNameMatch[1] : '';
37
+
38
+ // Service 이름 추출 (ClassName에서 Repository 제거 + Service)
39
+ const serviceName = className.replace('Repository', '') + 'Service';
40
+
41
+ // 인터페이스 추출
42
+ const interfaceMatch = content.match(/extends (\w+)Interface/);
43
+ const interfaceName = interfaceMatch ? interfaceMatch[1] : '';
44
+
45
+ // 메서드 추출
46
+ const methodPattern = /async (\w+)\(([^)]*)\): Promise<([^>]+)>/g;
47
+ const methods = [];
48
+ let match;
49
+
50
+ while ((match = methodPattern.exec(content)) !== null) {
51
+ methods.push({
52
+ name: match[1],
53
+ params: match[2],
54
+ returnType: match[3],
55
+ });
56
+ }
57
+
58
+ // Request/Response 타입 추출
59
+ const importMatch = content.match(/import \{([^}]+)\} from "\.\.\/interface"/);
60
+ const imports = importMatch ? importMatch[1].split(',').map(s => s.trim()) : [];
61
+
62
+ const requestTypes = imports.filter(i => i.includes('Request'));
63
+ const responseTypes = imports.filter(i => i.includes('Response'));
64
+
65
+ return {
66
+ className,
67
+ serviceName,
68
+ interfaceName,
69
+ methods,
70
+ requestTypes,
71
+ responseTypes,
72
+ imports: importMatch ? importMatch[0] : '',
73
+ };
74
+ }
75
+
76
+ /**
77
+ * 스토어 타입 결정
78
+ */
79
+ function determineStoreType(repoInfo) {
80
+ const methods = repoInfo.methods.map(m => m.name.toLowerCase());
81
+
82
+ // DELETE 메서드가 있는지 확인
83
+ const hasDelete = methods.some(m => m.includes('delete') || m.includes('remove'));
84
+
85
+ // SAVE 메서드가 있는지 확인
86
+ const hasSave = methods.some(m => m.includes('save') || m.includes('insert') || m.includes('update') || m.includes('create'));
87
+
88
+ // LIST 메서드가 있는지 확인
89
+ const hasList = methods.some(m => m.includes('list') || m.includes('find') || m.includes('get'));
90
+
91
+ // EXCEL 메서드가 있는지 확인
92
+ const hasExcel = methods.some(m => m.includes('excel') || m.includes('download'));
93
+
94
+ // DETAIL 메서드가 있는지 확인
95
+ const hasDetail = methods.some(m => m.includes('detail') || (m.includes('get') && !m.includes('list')));
96
+
97
+ // 메서드 개수에 따른 분류
98
+ const methodCount = methods.length;
99
+
100
+ // 타입 결정 로직
101
+ if (hasDelete && hasSave && hasList) {
102
+ return 2; // Master-Detail + Modal + Delete
103
+ } else if (hasSave && hasList) {
104
+ return 1; // Basic List + Detail
105
+ } else if (hasList) {
106
+ return 6; // Simple List
107
+ } else if (hasSave) {
108
+ return 5; // Simple (Save only)
109
+ }
110
+
111
+ return 6; // Default: Simple List
112
+ }
113
+
114
+ /**
115
+ * 템플릿 변수 생성
116
+ */
117
+ function createTemplateVariables(repoInfo, storeType, existingStore) {
118
+ const className = repoInfo.className;
119
+ const baseName = className.replace('Repository', '');
120
+
121
+ // 기존 Store에서 패턴 추출
122
+ const existingPattern = existingStore ? analyzeExistingStore(existingStore) : null;
123
+
124
+ // LIST 메서드 찾기
125
+ const listMethod = repoInfo.methods.find(m =>
126
+ m.name.toLowerCase().includes('list') &&
127
+ !m.name.toLowerCase().includes('excel')
128
+ ) || repoInfo.methods[0];
129
+
130
+ // DELETE 메서드 찾기
131
+ const deleteMethod = repoInfo.methods.find(m =>
132
+ m.name.toLowerCase().includes('delete') ||
133
+ m.name.toLowerCase().includes('remove')
134
+ );
135
+
136
+ // SAVE 메서드 찾기
137
+ const saveMethod = repoInfo.methods.find(m =>
138
+ m.name.toLowerCase().includes('save') ||
139
+ m.name.toLowerCase().includes('insert') ||
140
+ m.name.toLowerCase().includes('update') ||
141
+ m.name.toLowerCase().includes('create')
142
+ );
143
+
144
+ // DETAIL 메서드 찾기
145
+ const detailMethod = repoInfo.methods.find(m =>
146
+ m.name.toLowerCase().includes('detail') ||
147
+ (m.name.toLowerCase().includes('get') && !m.name.toLowerCase().includes('list'))
148
+ );
149
+
150
+ // Request 타입 찾기
151
+ const listRequestType = listMethod ?
152
+ (listMethod.returnType.includes('Response') ?
153
+ listMethod.returnType.replace('Response', 'Request') :
154
+ `Post${baseName}${listMethod.name.charAt(0).toUpperCase() + listMethod.name.slice(1)}Request`) :
155
+ `${baseName}Request`;
156
+
157
+ // Response 타입 찾기
158
+ const listResponseType = listMethod ?
159
+ listMethod.returnType :
160
+ `${baseName}Response`;
161
+
162
+ // DTO 타입 추정
163
+ const dtoItem = listResponseType.replace('Response', 'Res') || `${baseName}Res`;
164
+
165
+ // 기존 Store의 초기값 패턴 추출
166
+ const defaultRequestValues = existingPattern?.defaultRequestValues || {
167
+ pageNumber: 1,
168
+ pageSize: 100,
169
+ };
170
+
171
+ // Store 이름 생성 (camelCase)
172
+ const storeName = `use${baseName}Store`;
173
+ const storeInterface = `${baseName}Store`;
174
+ const storeNamePascal = baseName;
175
+
176
+ return {
177
+ STORE_NAME: storeName,
178
+ STORE_NAME_PASCAL: storeNamePascal,
179
+ STORE_INTERFACE: storeInterface,
180
+ SERVICE_NAME: repoInfo.serviceName,
181
+ LIST_METHOD_NAME: listMethod?.name || 'getList',
182
+ DELETE_METHOD_NAME: deleteMethod?.name,
183
+ SAVE_METHOD_NAME: saveMethod?.name,
184
+ DETAIL_METHOD_NAME: detailMethod?.name,
185
+ DELETE_API_CALL: deleteMethod ? `await ${repoInfo.serviceName}.${deleteMethod.name}(id);` : '',
186
+ SAVE_API_CALL: saveMethod ? `await ${repoInfo.serviceName}.${saveMethod.name}(apiParam);` : '',
187
+ LIST_REQUEST: listRequestType,
188
+ LIST_RESPONSE: listResponseType,
189
+ DTO_ITEM: dtoItem,
190
+ DTO_ITEM_LOWER: dtoItem.charAt(0).toLowerCase() + dtoItem.slice(1),
191
+ HAS_PAGE: true,
192
+ HAS_SAVE: !!saveMethod,
193
+ HAS_DELETE: !!deleteMethod,
194
+ HAS_DETAIL: !!detailMethod,
195
+ HAS_LIST: true,
196
+ IMPORTS: repoInfo.imports,
197
+ };
198
+ }
199
+
200
+ /**
201
+ * 기존 Store 분석
202
+ */
203
+ function analyzeExistingStore(content) {
204
+ // listRequestValue의 초기값 추출
205
+ const createStateMatch = content.match(/const createState: States = \{([^}]+)\}/s);
206
+ if (createStateMatch) {
207
+ const listRequestValueMatch = createStateMatch[1].match(/listRequestValue: \{([^}]+)\}/s);
208
+ if (listRequestValueMatch) {
209
+ // 기본값 파싱
210
+ const values = listRequestValueMatch[1].split(',').map(v => v.trim());
211
+ const defaultRequestValues = {};
212
+ values.forEach(v => {
213
+ const [key, ...valueParts] = v.split(':');
214
+ const value = valueParts.join(':').trim().replace(/,/g, '');
215
+ if (key && value) {
216
+ defaultRequestValues[key.trim()] = value;
217
+ }
218
+ });
219
+ return { defaultRequestValues };
220
+ }
221
+ }
222
+ return null;
223
+ }
224
+
225
+ /**
226
+ * 템플릿 렌더링
227
+ */
228
+ function renderTemplate(template, variables) {
229
+ let result = template;
230
+
231
+ // Handlebars 스타일 치환
232
+ Object.keys(variables).forEach(key => {
233
+ const regex = new RegExp(`\\{\\{${key}\\}\\}`, 'g');
234
+ const regexIf = new RegExp(`\\{\\{#${key}\\}\\}([\\s\\S]*?)\\{\\{/${key}\\}\\}`, 'g');
235
+ const regexIfNot = new RegExp(`\\{\\{\\^${key}\\}\\}([\\s\\S]*?)\\{\\{/${key}\\}\\}`, 'g');
236
+
237
+ if (variables[key]) {
238
+ // 조건부 치환 처리
239
+ result = result.replace(regexIf, (match, content) => content);
240
+ result = result.replace(regexIfNot, '');
241
+ result = result.replace(regex, variables[key]);
242
+ } else {
243
+ result = result.replace(regexIf, '');
244
+ result = result.replace(regexIfNot, (match, content) => content);
245
+ result = result.replace(regex, '');
246
+ }
247
+ });
248
+
249
+ return result;
250
+ }
251
+
252
+ /**
253
+ * 기존 Store 파일 찾기
254
+ */
255
+ function findExistingStore(baseName) {
256
+ // 가능한 Store 파일 경로들
257
+ const possiblePaths = [
258
+ path.join(STORE_DIR, `${kebabCase(baseName)}.use${baseName}Store.ts`),
259
+ path.join(STORE_DIR, `${kebabCase(baseName)}/use${baseName}Store.ts`),
260
+ ];
261
+
262
+ for (const p of possiblePaths) {
263
+ if (fs.existsSync(p)) {
264
+ return fs.readFileSync(p, 'utf-8');
265
+ }
266
+ }
267
+
268
+ return null;
269
+ }
270
+
271
+ /**
272
+ * camelCase를 kebab-case로 변환
273
+ */
274
+ function kebabCase(str) {
275
+ return str
276
+ .replace(/([a-z])([A-Z])/g, '$1-$2')
277
+ .replace(/[\s_]+/g, '-')
278
+ .toLowerCase();
279
+ }
280
+
281
+ /**
282
+ * Store 파일 경로 결정
283
+ */
284
+ function determineStorePath(baseName) {
285
+ // 기존 파일 구조 확인
286
+ const possibleDirs = [
287
+ path.join(STORE_DIR, `${kebabCase(baseName)}`),
288
+ STORE_DIR,
289
+ ];
290
+
291
+ for (const dir of possibleDirs) {
292
+ if (fs.existsSync(dir)) {
293
+ return path.join(dir, `use${baseName}StoreNew.ts`);
294
+ }
295
+ }
296
+
297
+ // 기본 경로
298
+ return path.join(STORE_DIR, `use${baseName}StoreNew.ts`);
299
+ }
300
+
301
+ /**
302
+ * 메인 실행 함수
303
+ */
304
+ function main() {
305
+ console.log('=== StoreNew.ts 파일 생성 시작 ===\n');
306
+
307
+ // 리포지토리 파일 목록 가져오기
308
+ const repoFiles = fs.readdirSync(REPO_DIR)
309
+ .filter(file => file.endsWith('Repository.ts') && file !== 'APIRepository.ts');
310
+
311
+ console.log(`리포지토리 파일 ${repoFiles.length}개 발견\n`);
312
+
313
+ let successCount = 0;
314
+ let skipCount = 0;
315
+ let errorCount = 0;
316
+
317
+ repoFiles.forEach((file, index) => {
318
+ try {
319
+ const repoPath = path.join(REPO_DIR, file);
320
+ const repoInfo = analyzeRepository(repoPath);
321
+
322
+ if (!repoInfo.className) {
323
+ console.log(`[${index + 1}/${repoFiles.length}] SKIP: ${file} - 클래스를 찾을 수 없음`);
324
+ skipCount++;
325
+ return;
326
+ }
327
+
328
+ const baseName = repoInfo.className.replace('Repository', '');
329
+ const storeType = determineStoreType(repoInfo);
330
+
331
+ // 기존 Store 파일 찾기
332
+ const existingStore = findExistingStore(baseName);
333
+
334
+ // 템플릿 변수 생성
335
+ const variables = createTemplateVariables(repoInfo, storeType, existingStore);
336
+
337
+ // 템플릿 선택
338
+ const templateKey = `type${storeType}`;
339
+ const template = templates[templateKey];
340
+
341
+ if (!template) {
342
+ console.log(`[${index + 1}/${repoFiles.length}] SKIP: ${file} - 템플릿을 찾을 수 없음 (Type ${storeType})`);
343
+ skipCount++;
344
+ return;
345
+ }
346
+
347
+ // 템플릿 렌더링
348
+ const rendered = renderTemplate(template, variables);
349
+
350
+ // 출력 경로 결정
351
+ const outputPath = determineStorePath(baseName);
352
+
353
+ // 디렉토리 생성
354
+ const outputDir = path.dirname(outputPath);
355
+ if (!fs.existsSync(outputDir)) {
356
+ fs.mkdirSync(outputDir, { recursive: true });
357
+ }
358
+
359
+ // 파일 쓰기
360
+ fs.writeFileSync(outputPath, rendered);
361
+
362
+ console.log(`[${index + 1}/${repoFiles.length}] SUCCESS: ${baseName}StoreNew.ts 생성 (Type ${storeType})`);
363
+ successCount++;
364
+
365
+ } catch (error) {
366
+ console.error(`[${index + 1}/${repoFiles.length}] ERROR: ${file} - ${error.message}`);
367
+ errorCount++;
368
+ }
369
+ });
370
+
371
+ console.log(`\n=== 생성 완료 ===`);
372
+ console.log(`성공: ${successCount}`);
373
+ console.log(`건너뜀: ${skipCount}`);
374
+ console.log(`오류: ${errorCount}`);
375
+ }
376
+
377
+ // 실행
378
+ if (require.main === module) {
379
+ main();
380
+ }
381
+
382
+ module.exports = { analyzeRepository, determineStoreType, createTemplateVariables, renderTemplate };