@mandujs/cli 0.12.2 → 0.13.1
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.ko.md +234 -234
- package/README.md +354 -354
- package/package.json +2 -2
- package/src/commands/contract.ts +173 -173
- package/src/commands/dev.ts +8 -68
- package/src/commands/doctor.ts +27 -27
- package/src/commands/guard-arch.ts +303 -303
- package/src/commands/guard-check.ts +3 -3
- package/src/commands/monitor.ts +300 -300
- package/src/commands/openapi.ts +107 -107
- package/src/commands/registry.ts +367 -357
- package/src/commands/routes.ts +228 -228
- package/src/commands/start.ts +184 -0
- package/src/errors/codes.ts +35 -35
- package/src/errors/index.ts +2 -2
- package/src/errors/messages.ts +143 -143
- package/src/hooks/index.ts +17 -17
- package/src/hooks/preaction.ts +256 -256
- package/src/main.ts +37 -34
- package/src/terminal/banner.ts +166 -166
- package/src/terminal/help.ts +306 -306
- package/src/terminal/index.ts +71 -71
- package/src/terminal/output.ts +295 -295
- package/src/terminal/palette.ts +30 -30
- package/src/terminal/progress.ts +327 -327
- package/src/terminal/stream-writer.ts +214 -214
- package/src/terminal/table.ts +354 -354
- package/src/terminal/theme.ts +142 -142
- package/src/util/bun.ts +6 -6
- package/src/util/fs.ts +23 -23
- package/src/util/handlers.ts +96 -0
- package/src/util/manifest.ts +52 -52
- package/src/util/output.ts +22 -22
- package/src/util/port.ts +71 -71
- package/templates/default/AGENTS.md +96 -96
- package/templates/default/app/api/health/route.ts +13 -13
- package/templates/default/app/globals.css +49 -49
- package/templates/default/app/layout.tsx +27 -27
- package/templates/default/app/page.tsx +38 -38
- package/templates/default/package.json +1 -0
- package/templates/default/src/client/shared/lib/utils.ts +16 -16
- package/templates/default/src/client/shared/ui/button.tsx +57 -57
- package/templates/default/src/client/shared/ui/card.tsx +78 -78
- package/templates/default/src/client/shared/ui/index.ts +21 -21
- package/templates/default/src/client/shared/ui/input.tsx +24 -24
- package/templates/default/tests/example.test.ts +58 -58
- package/templates/default/tests/helpers.ts +52 -52
- package/templates/default/tests/setup.ts +9 -9
- package/templates/default/tsconfig.json +12 -14
- package/templates/default/apps/server/main.ts +0 -67
- package/templates/default/apps/web/entry.tsx +0 -35
package/src/commands/registry.ts
CHANGED
|
@@ -1,357 +1,367 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DNA-010: Command Registry Pattern
|
|
3
|
-
*
|
|
4
|
-
* 선언적 명령어 등록 시스템
|
|
5
|
-
* - 각 명령어를 독립적으로 정의
|
|
6
|
-
* - 레이지 로딩으로 시작 시간 최적화
|
|
7
|
-
* - 서브커맨드 자동 라우팅
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import type { CLI_ERROR_CODES } from "../errors";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* 명령어 실행 컨텍스트
|
|
14
|
-
*/
|
|
15
|
-
export interface CommandContext {
|
|
16
|
-
args: string[];
|
|
17
|
-
options: Record<string, string>;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* 명령어 등록 정의
|
|
22
|
-
*/
|
|
23
|
-
export interface CommandRegistration {
|
|
24
|
-
/** 명령어 ID (예: "dev", "build", "guard") */
|
|
25
|
-
id: string;
|
|
26
|
-
/** 명령어 설명 */
|
|
27
|
-
description: string;
|
|
28
|
-
/** 서브커맨드 목록 (예: guard의 "arch", "legacy") */
|
|
29
|
-
subcommands?: string[];
|
|
30
|
-
/** 기본 서브커맨드 (서브커맨드 없이 호출 시) */
|
|
31
|
-
defaultSubcommand?: string;
|
|
32
|
-
/** 명령어 실행 */
|
|
33
|
-
run: (ctx: CommandContext) => Promise<boolean>;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* 명령어 레지스트리
|
|
38
|
-
*/
|
|
39
|
-
export const commandRegistry = new Map<string, CommandRegistration>();
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* 명령어 등록
|
|
43
|
-
*/
|
|
44
|
-
export function registerCommand(registration: CommandRegistration): void {
|
|
45
|
-
commandRegistry.set(registration.id, registration);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* 명령어 조회
|
|
50
|
-
*/
|
|
51
|
-
export function getCommand(id: string): CommandRegistration | undefined {
|
|
52
|
-
return commandRegistry.get(id);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* 모든 명령어 ID 목록
|
|
57
|
-
*/
|
|
58
|
-
export function getAllCommands(): string[] {
|
|
59
|
-
return Array.from(commandRegistry.keys());
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// ============================================================================
|
|
63
|
-
// 명령어 등록 (레이지 로딩)
|
|
64
|
-
// ============================================================================
|
|
65
|
-
|
|
66
|
-
registerCommand({
|
|
67
|
-
id: "init",
|
|
68
|
-
description: "새 프로젝트 생성 (Tailwind + shadcn/ui 기본 포함)",
|
|
69
|
-
async run(ctx) {
|
|
70
|
-
const { init } = await import("./init");
|
|
71
|
-
return init({
|
|
72
|
-
name: ctx.options.name || ctx.options._positional,
|
|
73
|
-
css: ctx.options.css as any,
|
|
74
|
-
ui: ctx.options.ui as any,
|
|
75
|
-
theme: ctx.options.theme === "true",
|
|
76
|
-
minimal: ctx.options.minimal === "true",
|
|
77
|
-
});
|
|
78
|
-
},
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
registerCommand({
|
|
82
|
-
id: "dev",
|
|
83
|
-
description: "개발 서버 실행 (FS Routes + Guard 기본)",
|
|
84
|
-
async run() {
|
|
85
|
-
const { dev } = await import("./dev");
|
|
86
|
-
await dev();
|
|
87
|
-
return true;
|
|
88
|
-
},
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
registerCommand({
|
|
92
|
-
id: "build",
|
|
93
|
-
description: "클라이언트 번들 빌드 (Hydration)",
|
|
94
|
-
async run(ctx) {
|
|
95
|
-
const { build } = await import("./build");
|
|
96
|
-
return build({ watch: ctx.options.watch === "true" });
|
|
97
|
-
},
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
registerCommand({
|
|
101
|
-
id: "
|
|
102
|
-
description: "
|
|
103
|
-
async run() {
|
|
104
|
-
const {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
case "
|
|
261
|
-
return
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
return
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
registerCommand({
|
|
342
|
-
id: "
|
|
343
|
-
description: "
|
|
344
|
-
async run(ctx) {
|
|
345
|
-
const {
|
|
346
|
-
return
|
|
347
|
-
},
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* DNA-010: Command Registry Pattern
|
|
3
|
+
*
|
|
4
|
+
* 선언적 명령어 등록 시스템
|
|
5
|
+
* - 각 명령어를 독립적으로 정의
|
|
6
|
+
* - 레이지 로딩으로 시작 시간 최적화
|
|
7
|
+
* - 서브커맨드 자동 라우팅
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { CLI_ERROR_CODES } from "../errors";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 명령어 실행 컨텍스트
|
|
14
|
+
*/
|
|
15
|
+
export interface CommandContext {
|
|
16
|
+
args: string[];
|
|
17
|
+
options: Record<string, string>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* 명령어 등록 정의
|
|
22
|
+
*/
|
|
23
|
+
export interface CommandRegistration {
|
|
24
|
+
/** 명령어 ID (예: "dev", "build", "guard") */
|
|
25
|
+
id: string;
|
|
26
|
+
/** 명령어 설명 */
|
|
27
|
+
description: string;
|
|
28
|
+
/** 서브커맨드 목록 (예: guard의 "arch", "legacy") */
|
|
29
|
+
subcommands?: string[];
|
|
30
|
+
/** 기본 서브커맨드 (서브커맨드 없이 호출 시) */
|
|
31
|
+
defaultSubcommand?: string;
|
|
32
|
+
/** 명령어 실행 */
|
|
33
|
+
run: (ctx: CommandContext) => Promise<boolean>;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 명령어 레지스트리
|
|
38
|
+
*/
|
|
39
|
+
export const commandRegistry = new Map<string, CommandRegistration>();
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 명령어 등록
|
|
43
|
+
*/
|
|
44
|
+
export function registerCommand(registration: CommandRegistration): void {
|
|
45
|
+
commandRegistry.set(registration.id, registration);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 명령어 조회
|
|
50
|
+
*/
|
|
51
|
+
export function getCommand(id: string): CommandRegistration | undefined {
|
|
52
|
+
return commandRegistry.get(id);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* 모든 명령어 ID 목록
|
|
57
|
+
*/
|
|
58
|
+
export function getAllCommands(): string[] {
|
|
59
|
+
return Array.from(commandRegistry.keys());
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ============================================================================
|
|
63
|
+
// 명령어 등록 (레이지 로딩)
|
|
64
|
+
// ============================================================================
|
|
65
|
+
|
|
66
|
+
registerCommand({
|
|
67
|
+
id: "init",
|
|
68
|
+
description: "새 프로젝트 생성 (Tailwind + shadcn/ui 기본 포함)",
|
|
69
|
+
async run(ctx) {
|
|
70
|
+
const { init } = await import("./init");
|
|
71
|
+
return init({
|
|
72
|
+
name: ctx.options.name || ctx.options._positional,
|
|
73
|
+
css: ctx.options.css as any,
|
|
74
|
+
ui: ctx.options.ui as any,
|
|
75
|
+
theme: ctx.options.theme === "true",
|
|
76
|
+
minimal: ctx.options.minimal === "true",
|
|
77
|
+
});
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
registerCommand({
|
|
82
|
+
id: "dev",
|
|
83
|
+
description: "개발 서버 실행 (FS Routes + Guard 기본)",
|
|
84
|
+
async run() {
|
|
85
|
+
const { dev } = await import("./dev");
|
|
86
|
+
await dev();
|
|
87
|
+
return true;
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
registerCommand({
|
|
92
|
+
id: "build",
|
|
93
|
+
description: "클라이언트 번들 빌드 (Hydration)",
|
|
94
|
+
async run(ctx) {
|
|
95
|
+
const { build } = await import("./build");
|
|
96
|
+
return build({ watch: ctx.options.watch === "true" });
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
registerCommand({
|
|
101
|
+
id: "start",
|
|
102
|
+
description: "프로덕션 서버 실행 (build 후)",
|
|
103
|
+
async run() {
|
|
104
|
+
const { start } = await import("./start");
|
|
105
|
+
await start();
|
|
106
|
+
return true;
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
registerCommand({
|
|
111
|
+
id: "check",
|
|
112
|
+
description: "FS Routes + Guard 통합 검사",
|
|
113
|
+
async run() {
|
|
114
|
+
const { check } = await import("./check");
|
|
115
|
+
return check();
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
registerCommand({
|
|
120
|
+
id: "guard",
|
|
121
|
+
description: "아키텍처 위반 검사",
|
|
122
|
+
subcommands: ["arch", "legacy", "spec"],
|
|
123
|
+
defaultSubcommand: "arch",
|
|
124
|
+
async run(ctx) {
|
|
125
|
+
const subCommand = ctx.args[1];
|
|
126
|
+
const hasSubCommand = subCommand && !subCommand.startsWith("--");
|
|
127
|
+
|
|
128
|
+
const guardOptions = {
|
|
129
|
+
watch: ctx.options.watch === "true",
|
|
130
|
+
output: ctx.options.output,
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
switch (subCommand) {
|
|
134
|
+
case "arch": {
|
|
135
|
+
const { guardArch } = await import("./guard-arch");
|
|
136
|
+
return guardArch(guardOptions);
|
|
137
|
+
}
|
|
138
|
+
case "legacy":
|
|
139
|
+
case "spec": {
|
|
140
|
+
const { guardCheck } = await import("./guard-check");
|
|
141
|
+
return guardCheck();
|
|
142
|
+
}
|
|
143
|
+
default:
|
|
144
|
+
if (hasSubCommand) {
|
|
145
|
+
// 알 수 없는 서브커맨드는 main.ts에서 처리
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
// 기본값: architecture guard
|
|
149
|
+
const { guardArch } = await import("./guard-arch");
|
|
150
|
+
return guardArch(guardOptions);
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
registerCommand({
|
|
156
|
+
id: "routes",
|
|
157
|
+
description: "FS Routes 관리",
|
|
158
|
+
subcommands: ["generate", "list", "watch"],
|
|
159
|
+
defaultSubcommand: "list",
|
|
160
|
+
async run(ctx) {
|
|
161
|
+
const subCommand = ctx.args[1];
|
|
162
|
+
const { routesGenerate, routesList, routesWatch } = await import("./routes");
|
|
163
|
+
|
|
164
|
+
const routesOptions = {
|
|
165
|
+
output: ctx.options.output,
|
|
166
|
+
verbose: ctx.options.verbose === "true",
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
switch (subCommand) {
|
|
170
|
+
case "generate":
|
|
171
|
+
return routesGenerate(routesOptions);
|
|
172
|
+
case "list":
|
|
173
|
+
return routesList({ verbose: routesOptions.verbose });
|
|
174
|
+
case "watch":
|
|
175
|
+
return routesWatch(routesOptions);
|
|
176
|
+
default:
|
|
177
|
+
if (subCommand && !subCommand.startsWith("--")) {
|
|
178
|
+
return false; // 알 수 없는 서브커맨드
|
|
179
|
+
}
|
|
180
|
+
return routesList({ verbose: routesOptions.verbose });
|
|
181
|
+
}
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
registerCommand({
|
|
186
|
+
id: "contract",
|
|
187
|
+
description: "Contract-First API 개발",
|
|
188
|
+
subcommands: ["create", "validate", "build", "diff"],
|
|
189
|
+
async run(ctx) {
|
|
190
|
+
const subCommand = ctx.args[1];
|
|
191
|
+
const {
|
|
192
|
+
contractCreate,
|
|
193
|
+
contractValidate,
|
|
194
|
+
contractBuild,
|
|
195
|
+
contractDiff,
|
|
196
|
+
} = await import("./contract");
|
|
197
|
+
|
|
198
|
+
switch (subCommand) {
|
|
199
|
+
case "create": {
|
|
200
|
+
const routeId = ctx.args[2] || ctx.options._positional;
|
|
201
|
+
if (!routeId) return false;
|
|
202
|
+
return contractCreate({ routeId });
|
|
203
|
+
}
|
|
204
|
+
case "validate":
|
|
205
|
+
return contractValidate({ verbose: ctx.options.verbose === "true" });
|
|
206
|
+
case "build":
|
|
207
|
+
return contractBuild({ output: ctx.options.output });
|
|
208
|
+
case "diff":
|
|
209
|
+
return contractDiff({
|
|
210
|
+
from: ctx.options.from,
|
|
211
|
+
to: ctx.options.to,
|
|
212
|
+
output: ctx.options.output,
|
|
213
|
+
json: ctx.options.json === "true",
|
|
214
|
+
});
|
|
215
|
+
default:
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
registerCommand({
|
|
222
|
+
id: "openapi",
|
|
223
|
+
description: "OpenAPI 스펙 생성",
|
|
224
|
+
subcommands: ["generate", "serve"],
|
|
225
|
+
async run(ctx) {
|
|
226
|
+
const subCommand = ctx.args[1];
|
|
227
|
+
const { openAPIGenerate, openAPIServe } = await import("./openapi");
|
|
228
|
+
|
|
229
|
+
switch (subCommand) {
|
|
230
|
+
case "generate":
|
|
231
|
+
return openAPIGenerate({
|
|
232
|
+
output: ctx.options.output,
|
|
233
|
+
title: ctx.options.title,
|
|
234
|
+
version: ctx.options.version,
|
|
235
|
+
});
|
|
236
|
+
case "serve":
|
|
237
|
+
return openAPIServe();
|
|
238
|
+
default:
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
registerCommand({
|
|
245
|
+
id: "change",
|
|
246
|
+
description: "변경 트랜잭션 관리",
|
|
247
|
+
subcommands: ["begin", "commit", "rollback", "status", "list", "prune"],
|
|
248
|
+
async run(ctx) {
|
|
249
|
+
const subCommand = ctx.args[1];
|
|
250
|
+
const {
|
|
251
|
+
changeBegin,
|
|
252
|
+
changeCommit,
|
|
253
|
+
changeRollback,
|
|
254
|
+
changeStatus,
|
|
255
|
+
changeList,
|
|
256
|
+
changePrune,
|
|
257
|
+
} = await import("./change");
|
|
258
|
+
|
|
259
|
+
switch (subCommand) {
|
|
260
|
+
case "begin":
|
|
261
|
+
return changeBegin({ message: ctx.options.message });
|
|
262
|
+
case "commit":
|
|
263
|
+
return changeCommit();
|
|
264
|
+
case "rollback":
|
|
265
|
+
return changeRollback({ id: ctx.options.id });
|
|
266
|
+
case "status":
|
|
267
|
+
return changeStatus();
|
|
268
|
+
case "list":
|
|
269
|
+
return changeList();
|
|
270
|
+
case "prune":
|
|
271
|
+
return changePrune({
|
|
272
|
+
keep: ctx.options.keep ? Number(ctx.options.keep) : undefined,
|
|
273
|
+
});
|
|
274
|
+
default:
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
registerCommand({
|
|
281
|
+
id: "brain",
|
|
282
|
+
description: "Brain (sLLM) 관리",
|
|
283
|
+
subcommands: ["setup", "status"],
|
|
284
|
+
async run(ctx) {
|
|
285
|
+
const subCommand = ctx.args[1];
|
|
286
|
+
const { brainSetup, brainStatus } = await import("./brain");
|
|
287
|
+
|
|
288
|
+
switch (subCommand) {
|
|
289
|
+
case "setup":
|
|
290
|
+
return brainSetup({
|
|
291
|
+
model: ctx.options.model,
|
|
292
|
+
url: ctx.options.url,
|
|
293
|
+
skipCheck: ctx.options["skip-check"] === "true",
|
|
294
|
+
});
|
|
295
|
+
case "status":
|
|
296
|
+
return brainStatus({ verbose: ctx.options.verbose === "true" });
|
|
297
|
+
default:
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
registerCommand({
|
|
304
|
+
id: "doctor",
|
|
305
|
+
description: "Guard 실패 분석 + 패치 제안",
|
|
306
|
+
async run(ctx) {
|
|
307
|
+
const { doctor } = await import("./doctor");
|
|
308
|
+
return doctor({
|
|
309
|
+
useLLM: ctx.options["no-llm"] !== "true",
|
|
310
|
+
output: ctx.options.output,
|
|
311
|
+
});
|
|
312
|
+
},
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
registerCommand({
|
|
316
|
+
id: "watch",
|
|
317
|
+
description: "실시간 파일 감시",
|
|
318
|
+
async run(ctx) {
|
|
319
|
+
const { watch } = await import("./watch");
|
|
320
|
+
return watch({
|
|
321
|
+
status: ctx.options.status === "true",
|
|
322
|
+
debounce: ctx.options.debounce ? Number(ctx.options.debounce) : undefined,
|
|
323
|
+
});
|
|
324
|
+
},
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
registerCommand({
|
|
328
|
+
id: "monitor",
|
|
329
|
+
description: "MCP Activity Monitor",
|
|
330
|
+
async run(ctx) {
|
|
331
|
+
const { monitor } = await import("./monitor");
|
|
332
|
+
return monitor({
|
|
333
|
+
summary: ctx.options.summary === "true",
|
|
334
|
+
since: ctx.options.since,
|
|
335
|
+
follow: ctx.options.follow === "false" ? false : true,
|
|
336
|
+
file: ctx.options.file,
|
|
337
|
+
});
|
|
338
|
+
},
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
registerCommand({
|
|
342
|
+
id: "lock",
|
|
343
|
+
description: "Lockfile 관리",
|
|
344
|
+
async run(ctx) {
|
|
345
|
+
const { runLockCommand } = await import("./lock");
|
|
346
|
+
return runLockCommand(ctx.args.slice(1));
|
|
347
|
+
},
|
|
348
|
+
});
|
|
349
|
+
|
|
350
|
+
// 레거시 명령어
|
|
351
|
+
registerCommand({
|
|
352
|
+
id: "spec-upsert",
|
|
353
|
+
description: "Spec 파일 검증 및 lock 갱신 (레거시)",
|
|
354
|
+
async run(ctx) {
|
|
355
|
+
const { specUpsert } = await import("./spec-upsert");
|
|
356
|
+
return specUpsert({ file: ctx.options.file });
|
|
357
|
+
},
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
registerCommand({
|
|
361
|
+
id: "generate",
|
|
362
|
+
description: "Spec에서 코드 생성 (레거시)",
|
|
363
|
+
async run() {
|
|
364
|
+
const { generateApply } = await import("./generate-apply");
|
|
365
|
+
return generateApply();
|
|
366
|
+
},
|
|
367
|
+
});
|