@mandujs/cli 0.9.21 β 0.9.23
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 +57 -4
- package/README.md +62 -15
- package/package.json +2 -2
- package/src/commands/check.ts +41 -5
- package/src/commands/contract.ts +135 -9
- package/src/commands/dev.ts +155 -95
- package/src/commands/guard-arch.ts +39 -9
- package/src/commands/guard-check.ts +3 -3
- package/src/commands/init.ts +264 -9
- package/src/commands/monitor.ts +301 -0
- package/src/main.ts +421 -361
- package/templates/default/app/globals.css +37 -0
- package/templates/default/app/layout.tsx +27 -0
- package/templates/default/app/page.tsx +27 -49
- package/templates/default/package.json +20 -11
- package/templates/default/postcss.config.js +6 -0
- package/templates/default/src/client/app/index.ts +1 -0
- package/templates/default/src/client/entities/index.ts +1 -0
- package/templates/default/src/client/features/index.ts +1 -0
- package/templates/default/src/client/pages/index.ts +1 -0
- package/templates/default/src/client/shared/index.ts +1 -0
- package/templates/default/src/client/shared/lib/utils.ts +16 -0
- package/templates/default/src/client/shared/ui/button.tsx +57 -0
- package/templates/default/src/client/shared/ui/card.tsx +78 -0
- package/templates/default/src/client/shared/ui/index.ts +21 -0
- package/templates/default/src/client/shared/ui/input.tsx +24 -0
- package/templates/default/src/client/widgets/index.ts +1 -0
- package/templates/default/src/server/api/index.ts +1 -0
- package/templates/default/src/server/application/index.ts +1 -0
- package/templates/default/src/server/core/index.ts +1 -0
- package/templates/default/src/server/domain/index.ts +1 -0
- package/templates/default/src/server/infra/index.ts +1 -0
- package/templates/default/src/shared/contracts/index.ts +1 -0
- package/templates/default/src/shared/env/index.ts +1 -0
- package/templates/default/src/shared/schema/index.ts +1 -0
- package/templates/default/src/shared/types/index.ts +1 -0
- package/templates/default/src/shared/utils/client/index.ts +1 -0
- package/templates/default/src/shared/utils/server/index.ts +1 -0
- package/templates/default/tailwind.config.ts +64 -0
- package/templates/default/tsconfig.json +14 -3
package/src/main.ts
CHANGED
|
@@ -1,72 +1,81 @@
|
|
|
1
|
-
#!/usr/bin/env bun
|
|
2
|
-
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
3
|
import { specUpsert } from "./commands/spec-upsert";
|
|
4
4
|
import { generateApply } from "./commands/generate-apply";
|
|
5
5
|
import { guardCheck } from "./commands/guard-check";
|
|
6
6
|
import { guardArch } from "./commands/guard-arch";
|
|
7
7
|
import { check } from "./commands/check";
|
|
8
8
|
import { dev } from "./commands/dev";
|
|
9
|
-
import { init } from "./commands/init";
|
|
10
|
-
import { build } from "./commands/build";
|
|
11
|
-
import { contractCreate, contractValidate } from "./commands/contract";
|
|
12
|
-
import { openAPIGenerate, openAPIServe } from "./commands/openapi";
|
|
13
|
-
import {
|
|
14
|
-
changeBegin,
|
|
15
|
-
changeCommit,
|
|
16
|
-
changeRollback,
|
|
17
|
-
changeStatus,
|
|
18
|
-
changeList,
|
|
19
|
-
changePrune,
|
|
20
|
-
} from "./commands/change";
|
|
21
|
-
import { doctor } from "./commands/doctor";
|
|
22
|
-
import { watch } from "./commands/watch";
|
|
23
|
-
import { brainSetup, brainStatus } from "./commands/brain";
|
|
24
|
-
import { routesGenerate, routesList, routesWatch } from "./commands/routes";
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
9
|
+
import { init } from "./commands/init";
|
|
10
|
+
import { build } from "./commands/build";
|
|
11
|
+
import { contractCreate, contractValidate, contractBuild, contractDiff } from "./commands/contract";
|
|
12
|
+
import { openAPIGenerate, openAPIServe } from "./commands/openapi";
|
|
13
|
+
import {
|
|
14
|
+
changeBegin,
|
|
15
|
+
changeCommit,
|
|
16
|
+
changeRollback,
|
|
17
|
+
changeStatus,
|
|
18
|
+
changeList,
|
|
19
|
+
changePrune,
|
|
20
|
+
} from "./commands/change";
|
|
21
|
+
import { doctor } from "./commands/doctor";
|
|
22
|
+
import { watch } from "./commands/watch";
|
|
23
|
+
import { brainSetup, brainStatus } from "./commands/brain";
|
|
24
|
+
import { routesGenerate, routesList, routesWatch } from "./commands/routes";
|
|
25
|
+
import { monitor } from "./commands/monitor";
|
|
26
|
+
|
|
27
|
+
const HELP_TEXT = `
|
|
28
|
+
π₯ Mandu CLI - Agent-Native Fullstack Framework
|
|
29
|
+
|
|
30
|
+
Usage: bunx mandu <command> [options]
|
|
31
|
+
|
|
31
32
|
Commands:
|
|
32
|
-
init μ νλ‘μ νΈ μμ±
|
|
33
|
+
init μ νλ‘μ νΈ μμ± (Tailwind + shadcn/ui κΈ°λ³Έ ν¬ν¨)
|
|
33
34
|
check FS Routes + Guard ν΅ν© κ²μ¬
|
|
34
35
|
routes generate FS Routes μ€μΊ λ° λ§€λνμ€νΈ μμ±
|
|
35
36
|
routes list νμ¬ λΌμ°νΈ λͺ©λ‘ μΆλ ₯
|
|
36
37
|
routes watch μ€μκ° λΌμ°νΈ κ°μ
|
|
37
38
|
dev κ°λ° μλ² μ€ν (FS Routes + Guard κΈ°λ³Έ)
|
|
38
39
|
dev --no-guard Guard κ°μ λΉνμ±ν
|
|
39
|
-
build ν΄λΌμ΄μΈνΈ λ²λ€ λΉλ (Hydration)
|
|
40
|
-
guard
|
|
41
|
-
guard arch μν€ν
μ² μλ° κ²μ¬ (FSD/Clean/Hexagonal)
|
|
42
|
-
guard
|
|
43
|
-
guard arch --
|
|
44
|
-
guard arch --
|
|
45
|
-
guard arch --
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
change
|
|
66
|
-
change
|
|
67
|
-
|
|
40
|
+
build ν΄λΌμ΄μΈνΈ λ²λ€ λΉλ (Hydration)
|
|
41
|
+
guard μν€ν
μ² μλ° κ²μ¬ (κΈ°λ³Έ)
|
|
42
|
+
guard arch μν€ν
μ² μλ° κ²μ¬ (FSD/Clean/Hexagonal)
|
|
43
|
+
guard legacy λ κ±°μ Spec Guard κ²μ¬
|
|
44
|
+
guard arch --watch μ€μκ° μν€ν
μ² κ°μ
|
|
45
|
+
guard arch --list-presets μ¬μ© κ°λ₯ν ν리μ
λͺ©λ‘
|
|
46
|
+
guard arch --output report.md 리ν¬νΈ νμΌ μμ±
|
|
47
|
+
guard arch --show-trend νΈλ λ λΆμ νμ
|
|
48
|
+
spec-upsert Spec νμΌ κ²μ¦ λ° lock κ°±μ (λ κ±°μ)
|
|
49
|
+
generate Specμμ μ½λ μμ± (λ κ±°μ)
|
|
50
|
+
|
|
51
|
+
doctor Guard μ€ν¨ λΆμ + ν¨μΉ μ μ (Brain)
|
|
52
|
+
watch μ€μκ° νμΌ κ°μ - κ²½κ³ λ§ (Brain)
|
|
53
|
+
monitor MCP Activity Monitor λ‘κ·Έ μ€νΈλ¦Ό
|
|
54
|
+
|
|
55
|
+
brain setup sLLM μ€μ (μ ν)
|
|
56
|
+
brain status Brain μν νμΈ
|
|
57
|
+
|
|
58
|
+
contract create <routeId> λΌμ°νΈμ λν Contract μμ±
|
|
59
|
+
contract validate Contract-Slot μΌκ΄μ± κ²μ¦
|
|
60
|
+
contract build Contract λ μ§μ€νΈλ¦¬ μμ±
|
|
61
|
+
contract diff Contract λ³κ²½μ¬ν λΉκ΅
|
|
62
|
+
|
|
63
|
+
openapi generate OpenAPI 3.0 μ€ν μμ±
|
|
64
|
+
openapi serve Swagger UI λ‘컬 μλ² μ€ν
|
|
65
|
+
|
|
66
|
+
change begin λ³κ²½ νΈλμμ
μμ (μ€λ
μ· μμ±)
|
|
67
|
+
change commit λ³κ²½ νμ
|
|
68
|
+
change rollback μ€λ
μ·μΌλ‘ 볡μ
|
|
69
|
+
change status νμ¬ νΈλμμ
μν
|
|
70
|
+
change list λ³κ²½ μ΄λ ₯ μ‘°ν
|
|
71
|
+
change prune μ€λλ μ€λ
μ· μ 리
|
|
72
|
+
|
|
68
73
|
Options:
|
|
69
74
|
--name <name> init μ νλ‘μ νΈ μ΄λ¦ (κΈ°λ³Έ: my-mandu-app)
|
|
75
|
+
--css <framework> init μ CSS νλ μμν¬: tailwind, panda, none (κΈ°λ³Έ: tailwind)
|
|
76
|
+
--ui <library> init μ UI λΌμ΄λΈλ¬λ¦¬: shadcn, ark, none (κΈ°λ³Έ: shadcn)
|
|
77
|
+
--theme init μ λ€ν¬λͺ¨λ ν
λ§ μμ€ν
μΆκ°
|
|
78
|
+
--minimal init μ CSS/UI μμ΄ μ΅μ ν
νλ¦Ώ μμ± (--css none --ui none)
|
|
70
79
|
--file <path> spec-upsert μ μ¬μ©ν spec νμΌ κ²½λ‘
|
|
71
80
|
--port <port> dev/openapi serve ν¬νΈ (κΈ°λ³Έ: 3000/8080)
|
|
72
81
|
--guard dev μ Architecture Guard μ€μκ° κ°μ νμ±ν (κΈ°λ³Έ: ON)
|
|
@@ -76,125 +85,144 @@ Options:
|
|
|
76
85
|
--legacy FS Routes λΉνμ±ν (λ κ±°μ λͺ¨λ)
|
|
77
86
|
--no-auto-correct guard μ μλ μμ λΉνμ±ν
|
|
78
87
|
--preset <name> guard/check ν리μ
(κΈ°λ³Έ: mandu) - fsd, clean, hexagonal, atomic μ ν κ°λ₯
|
|
79
|
-
--ci guard/check CI λͺ¨λ (
|
|
88
|
+
--ci guard/check CI λͺ¨λ (warningλ μ€ν¨ μ²λ¦¬)
|
|
80
89
|
--quiet guard/check μμ½λ§ μΆλ ₯
|
|
81
|
-
--report-format guard arch 리ν¬νΈ νμ: json, markdown, html
|
|
82
|
-
--save-stats guard arch ν΅κ³ μ μ₯ (νΈλ λ λΆμμ©)
|
|
83
|
-
--show-trend guard arch νΈλ λ λΆμ νμ
|
|
84
|
-
--minify build μ μ½λ μμΆ
|
|
85
|
-
--sourcemap build μ μμ€λ§΅ μμ±
|
|
86
|
-
--watch build/guard arch νμΌ κ°μ λͺ¨λ
|
|
87
|
-
--
|
|
88
|
-
--
|
|
89
|
-
--
|
|
90
|
-
--
|
|
90
|
+
--report-format guard arch 리ν¬νΈ νμ: json, markdown, html
|
|
91
|
+
--save-stats guard arch ν΅κ³ μ μ₯ (νΈλ λ λΆμμ©)
|
|
92
|
+
--show-trend guard arch νΈλ λ λΆμ νμ
|
|
93
|
+
--minify build μ μ½λ μμΆ
|
|
94
|
+
--sourcemap build μ μμ€λ§΅ μμ±
|
|
95
|
+
--watch build/guard arch νμΌ κ°μ λͺ¨λ
|
|
96
|
+
--summary monitor μμ½ μΆλ ₯ (JSON λ‘κ·Έμμλ§)
|
|
97
|
+
--since <duration> monitor μμ½ κΈ°κ° (μ: 5m, 30s, 1h)
|
|
98
|
+
--follow <bool> monitor follow λͺ¨λ (κΈ°λ³Έ: true)
|
|
99
|
+
--file <path> monitor λ‘κ·Έ νμΌ μ§μ μ§μ
|
|
100
|
+
--message <msg> change begin μ μ€λͺ
λ©μμ§
|
|
101
|
+
--id <id> change rollback μ νΉμ λ³κ²½ ID
|
|
102
|
+
--keep <n> change prune μ μ μ§ν μ€λ
μ· μ (κΈ°λ³Έ: 5)
|
|
103
|
+
--output <path> openapi/doctor μΆλ ₯ κ²½λ‘
|
|
104
|
+
--from <path> contract diff κΈ°μ€ λ μ§μ€νΈλ¦¬ κ²½λ‘
|
|
105
|
+
--to <path> contract diff λμ λ μ§μ€νΈλ¦¬ κ²½λ‘
|
|
106
|
+
--json contract diff κ²°κ³Ό JSON μΆλ ₯
|
|
91
107
|
--format <fmt> guard/check μΆλ ₯ νμ: console, json, agent (κΈ°λ³Έ: μλ)
|
|
92
108
|
--format <fmt> doctor μΆλ ₯ νμ: console, json, markdown (κΈ°λ³Έ: console)
|
|
93
|
-
--no-llm doctorμμ LLM μ¬μ© μ ν¨ (ν
νλ¦Ώ λͺ¨λ)
|
|
94
|
-
--model <name> brain setup μ λͺ¨λΈ μ΄λ¦ (κΈ°λ³Έ: llama3.2)
|
|
95
|
-
--url <url> brain setup μ Ollama URL
|
|
96
|
-
--verbose μμΈ μΆλ ₯
|
|
97
|
-
--help, -h λμλ§ νμ
|
|
98
|
-
|
|
109
|
+
--no-llm doctorμμ LLM μ¬μ© μ ν¨ (ν
νλ¦Ώ λͺ¨λ)
|
|
110
|
+
--model <name> brain setup μ λͺ¨λΈ μ΄λ¦ (κΈ°λ³Έ: llama3.2)
|
|
111
|
+
--url <url> brain setup μ Ollama URL
|
|
112
|
+
--verbose μμΈ μΆλ ₯
|
|
113
|
+
--help, -h λμλ§ νμ
|
|
114
|
+
|
|
99
115
|
Examples:
|
|
100
|
-
bunx mandu init --name my-app
|
|
116
|
+
bunx mandu init --name my-app # Tailwind + shadcn/ui κΈ°λ³Έ
|
|
117
|
+
bunx mandu init my-app --minimal # CSS/UI μμ΄ μ΅μ ν
νλ¦Ώ
|
|
118
|
+
bunx mandu init my-app --theme # λ€ν¬λͺ¨λ ν
λ§ ν¬ν¨
|
|
119
|
+
bunx mandu init my-app --ui none # UI λΌμ΄λΈλ¬λ¦¬ μμ΄
|
|
101
120
|
bunx mandu check
|
|
102
121
|
bunx mandu routes list
|
|
103
122
|
bunx mandu routes generate
|
|
104
123
|
bunx mandu dev --port 3000
|
|
105
124
|
bunx mandu dev --no-guard
|
|
106
125
|
bunx mandu build --minify
|
|
107
|
-
bunx mandu guard
|
|
108
|
-
bunx mandu guard arch --preset fsd
|
|
109
|
-
bunx mandu guard arch --watch
|
|
110
|
-
bunx mandu guard arch --ci --format json
|
|
111
|
-
bunx mandu
|
|
112
|
-
bunx mandu
|
|
113
|
-
bunx mandu
|
|
114
|
-
bunx mandu
|
|
115
|
-
bunx mandu
|
|
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
|
-
options
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
if (
|
|
169
|
-
console.warn(`β οΈ Invalid --${optionName}
|
|
170
|
-
return undefined;
|
|
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
|
-
|
|
126
|
+
bunx mandu guard
|
|
127
|
+
bunx mandu guard arch --preset fsd
|
|
128
|
+
bunx mandu guard arch --watch
|
|
129
|
+
bunx mandu guard arch --ci --format json
|
|
130
|
+
bunx mandu guard legacy
|
|
131
|
+
bunx mandu monitor
|
|
132
|
+
bunx mandu monitor --summary --since 5m
|
|
133
|
+
bunx mandu doctor
|
|
134
|
+
bunx mandu brain setup --model codellama
|
|
135
|
+
bunx mandu contract create users
|
|
136
|
+
bunx mandu contract build
|
|
137
|
+
bunx mandu contract diff
|
|
138
|
+
bunx mandu openapi generate --output docs/api.json
|
|
139
|
+
bunx mandu change begin --message "Add new route"
|
|
140
|
+
|
|
141
|
+
FS Routes Workflow (κΆμ₯):
|
|
142
|
+
1. init β 2. app/ ν΄λμ page.tsx μμ± β 3. dev β 4. build
|
|
143
|
+
|
|
144
|
+
Legacy Workflow:
|
|
145
|
+
1. init β 2. spec-upsert β 3. generate β 4. build β 5. guard β 6. dev
|
|
146
|
+
|
|
147
|
+
Contract-first Workflow:
|
|
148
|
+
1. contract create β 2. Edit contract β 3. generate β 4. Edit slot β 5. contract validate
|
|
149
|
+
|
|
150
|
+
Brain (sLLM) Workflow:
|
|
151
|
+
1. brain setup β 2. doctor (λΆμ) β 3. watch (κ°μ)
|
|
152
|
+
`;
|
|
153
|
+
|
|
154
|
+
function parseArgs(args: string[]): { command: string; options: Record<string, string> } {
|
|
155
|
+
const command = args[0] || "";
|
|
156
|
+
const options: Record<string, string> = {};
|
|
157
|
+
|
|
158
|
+
for (let i = 1; i < args.length; i++) {
|
|
159
|
+
const arg = args[i];
|
|
160
|
+
if (arg.startsWith("--")) {
|
|
161
|
+
const key = arg.slice(2);
|
|
162
|
+
const value = args[i + 1] && !args[i + 1].startsWith("--") ? args[++i] : "true";
|
|
163
|
+
options[key] = value;
|
|
164
|
+
} else if (arg === "-h") {
|
|
165
|
+
options["help"] = "true";
|
|
166
|
+
} else if (!options._positional) {
|
|
167
|
+
// First non-flag argument after command is positional (e.g., project name)
|
|
168
|
+
options._positional = arg;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return { command, options };
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* ν¬νΈ μ΅μ
μμ νκ² νμ±
|
|
177
|
+
* - μ«μκ° μλλ©΄ undefined λ°ν (κΈ°λ³Έκ° μ¬μ©)
|
|
178
|
+
* - μ ν¨ λ²μ: 1-65535
|
|
179
|
+
*/
|
|
180
|
+
function parsePort(value: string | undefined, optionName = "port"): number | undefined {
|
|
181
|
+
if (!value || value === "true") {
|
|
182
|
+
return undefined; // κΈ°λ³Έκ° μ¬μ©
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const port = Number(value);
|
|
186
|
+
|
|
187
|
+
if (Number.isNaN(port)) {
|
|
188
|
+
console.warn(`β οΈ Invalid --${optionName} value: "${value}" (using default)`);
|
|
189
|
+
return undefined;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
193
|
+
console.warn(`β οΈ Invalid --${optionName} range: ${port} (must be 1-65535, using default)`);
|
|
194
|
+
return undefined;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return port;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async function main(): Promise<void> {
|
|
201
|
+
const args = process.argv.slice(2);
|
|
202
|
+
const { command, options } = parseArgs(args);
|
|
203
|
+
|
|
204
|
+
if (options.help || command === "help" || !command) {
|
|
205
|
+
console.log(HELP_TEXT);
|
|
206
|
+
process.exit(0);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
let success = true;
|
|
210
|
+
|
|
211
|
+
switch (command) {
|
|
212
|
+
case "init":
|
|
213
|
+
success = await init({
|
|
214
|
+
name: options.name || options._positional,
|
|
215
|
+
css: options.css as any,
|
|
216
|
+
ui: options.ui as any,
|
|
217
|
+
theme: options.theme === "true",
|
|
218
|
+
minimal: options.minimal === "true",
|
|
219
|
+
});
|
|
220
|
+
break;
|
|
221
|
+
|
|
222
|
+
case "spec-upsert":
|
|
223
|
+
success = await specUpsert({ file: options.file });
|
|
224
|
+
break;
|
|
225
|
+
|
|
198
226
|
case "generate":
|
|
199
227
|
success = await generateApply();
|
|
200
228
|
break;
|
|
@@ -211,39 +239,50 @@ async function main(): Promise<void> {
|
|
|
211
239
|
|
|
212
240
|
case "guard": {
|
|
213
241
|
const subCommand = args[1];
|
|
242
|
+
const hasSubCommand = subCommand && !subCommand.startsWith("--");
|
|
243
|
+
const guardArchOptions = {
|
|
244
|
+
preset: options.preset as any,
|
|
245
|
+
watch: options.watch === "true",
|
|
246
|
+
ci: options.ci === "true",
|
|
247
|
+
format: options.format as any,
|
|
248
|
+
quiet: options.quiet === "true",
|
|
249
|
+
srcDir: options["src-dir"],
|
|
250
|
+
listPresets: options["list-presets"] === "true",
|
|
251
|
+
output: options.output,
|
|
252
|
+
reportFormat: (options["report-format"] as any) || "markdown",
|
|
253
|
+
saveStats: options["save-stats"] === "true",
|
|
254
|
+
showTrend: options["show-trend"] === "true",
|
|
255
|
+
};
|
|
214
256
|
switch (subCommand) {
|
|
215
257
|
case "arch":
|
|
216
|
-
success = await guardArch(
|
|
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
|
-
break;
|
|
246
|
-
|
|
258
|
+
success = await guardArch(guardArchOptions);
|
|
259
|
+
break;
|
|
260
|
+
case "legacy":
|
|
261
|
+
case "spec":
|
|
262
|
+
success = await guardCheck({
|
|
263
|
+
autoCorrect: options["no-auto-correct"] !== "true",
|
|
264
|
+
});
|
|
265
|
+
break;
|
|
266
|
+
default:
|
|
267
|
+
if (hasSubCommand) {
|
|
268
|
+
console.error(`β Unknown guard subcommand: ${subCommand}`);
|
|
269
|
+
console.log("\nUsage: bunx mandu guard <arch|legacy>");
|
|
270
|
+
process.exit(1);
|
|
271
|
+
}
|
|
272
|
+
// κΈ°λ³Έκ°: architecture guard
|
|
273
|
+
success = await guardArch(guardArchOptions);
|
|
274
|
+
}
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
case "build":
|
|
279
|
+
success = await build({
|
|
280
|
+
minify: options.minify === "true",
|
|
281
|
+
sourcemap: options.sourcemap === "true",
|
|
282
|
+
watch: options.watch === "true",
|
|
283
|
+
});
|
|
284
|
+
break;
|
|
285
|
+
|
|
247
286
|
case "dev":
|
|
248
287
|
await dev({
|
|
249
288
|
port: parsePort(options.port),
|
|
@@ -253,170 +292,191 @@ async function main(): Promise<void> {
|
|
|
253
292
|
legacy: options.legacy === "true",
|
|
254
293
|
});
|
|
255
294
|
break;
|
|
256
|
-
|
|
257
|
-
case "routes": {
|
|
258
|
-
const subCommand = args[1];
|
|
259
|
-
switch (subCommand) {
|
|
260
|
-
case "generate":
|
|
261
|
-
success = await routesGenerate({
|
|
262
|
-
output: options.output,
|
|
263
|
-
verbose: options.verbose === "true",
|
|
264
|
-
});
|
|
265
|
-
break;
|
|
266
|
-
case "list":
|
|
267
|
-
success = await routesList({
|
|
268
|
-
verbose: options.verbose === "true",
|
|
269
|
-
});
|
|
270
|
-
break;
|
|
271
|
-
case "watch":
|
|
272
|
-
success = await routesWatch({
|
|
273
|
-
output: options.output,
|
|
274
|
-
verbose: options.verbose === "true",
|
|
275
|
-
});
|
|
276
|
-
break;
|
|
277
|
-
default:
|
|
278
|
-
// κΈ°λ³Έκ°: list
|
|
279
|
-
if (!subCommand) {
|
|
280
|
-
success = await routesList({
|
|
281
|
-
verbose: options.verbose === "true",
|
|
282
|
-
});
|
|
283
|
-
} else {
|
|
284
|
-
console.error(`β Unknown routes subcommand: ${subCommand}`);
|
|
285
|
-
console.log("\nUsage: bunx mandu routes <generate|list|watch>");
|
|
286
|
-
process.exit(1);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
break;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
case "contract": {
|
|
293
|
-
const subCommand = args[1];
|
|
294
|
-
switch (subCommand) {
|
|
295
|
-
case "create": {
|
|
296
|
-
const routeId = args[2] || options._positional;
|
|
297
|
-
if (!routeId) {
|
|
298
|
-
console.error("β Route ID is required");
|
|
299
|
-
console.log("\nUsage: bunx mandu contract create <routeId>");
|
|
300
|
-
process.exit(1);
|
|
301
|
-
}
|
|
302
|
-
success = await contractCreate({ routeId });
|
|
303
|
-
break;
|
|
304
|
-
}
|
|
305
|
-
case "validate":
|
|
306
|
-
success = await contractValidate({ verbose: options.verbose === "true" });
|
|
307
|
-
break;
|
|
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
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
});
|
|
361
|
-
break;
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
});
|
|
295
|
+
|
|
296
|
+
case "routes": {
|
|
297
|
+
const subCommand = args[1];
|
|
298
|
+
switch (subCommand) {
|
|
299
|
+
case "generate":
|
|
300
|
+
success = await routesGenerate({
|
|
301
|
+
output: options.output,
|
|
302
|
+
verbose: options.verbose === "true",
|
|
303
|
+
});
|
|
304
|
+
break;
|
|
305
|
+
case "list":
|
|
306
|
+
success = await routesList({
|
|
307
|
+
verbose: options.verbose === "true",
|
|
308
|
+
});
|
|
309
|
+
break;
|
|
310
|
+
case "watch":
|
|
311
|
+
success = await routesWatch({
|
|
312
|
+
output: options.output,
|
|
313
|
+
verbose: options.verbose === "true",
|
|
314
|
+
});
|
|
315
|
+
break;
|
|
316
|
+
default:
|
|
317
|
+
// κΈ°λ³Έκ°: list
|
|
318
|
+
if (!subCommand) {
|
|
319
|
+
success = await routesList({
|
|
320
|
+
verbose: options.verbose === "true",
|
|
321
|
+
});
|
|
322
|
+
} else {
|
|
323
|
+
console.error(`β Unknown routes subcommand: ${subCommand}`);
|
|
324
|
+
console.log("\nUsage: bunx mandu routes <generate|list|watch>");
|
|
325
|
+
process.exit(1);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
break;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
case "contract": {
|
|
332
|
+
const subCommand = args[1];
|
|
333
|
+
switch (subCommand) {
|
|
334
|
+
case "create": {
|
|
335
|
+
const routeId = args[2] || options._positional;
|
|
336
|
+
if (!routeId) {
|
|
337
|
+
console.error("β Route ID is required");
|
|
338
|
+
console.log("\nUsage: bunx mandu contract create <routeId>");
|
|
339
|
+
process.exit(1);
|
|
340
|
+
}
|
|
341
|
+
success = await contractCreate({ routeId });
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
case "validate":
|
|
345
|
+
success = await contractValidate({ verbose: options.verbose === "true" });
|
|
346
|
+
break;
|
|
347
|
+
case "build":
|
|
348
|
+
success = await contractBuild({ output: options.output });
|
|
349
|
+
break;
|
|
350
|
+
case "diff":
|
|
351
|
+
success = await contractDiff({
|
|
352
|
+
from: options.from,
|
|
353
|
+
to: options.to,
|
|
354
|
+
output: options.output,
|
|
355
|
+
json: options.json === "true",
|
|
356
|
+
});
|
|
357
|
+
break;
|
|
358
|
+
default:
|
|
359
|
+
console.error(`β Unknown contract subcommand: ${subCommand}`);
|
|
360
|
+
console.log("\nUsage: bunx mandu contract <create|validate|build|diff>");
|
|
361
|
+
process.exit(1);
|
|
362
|
+
}
|
|
363
|
+
break;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
case "openapi": {
|
|
367
|
+
const subCommand = args[1];
|
|
368
|
+
switch (subCommand) {
|
|
369
|
+
case "generate":
|
|
370
|
+
success = await openAPIGenerate({
|
|
371
|
+
output: options.output,
|
|
372
|
+
title: options.title,
|
|
373
|
+
version: options.version,
|
|
374
|
+
});
|
|
375
|
+
break;
|
|
376
|
+
case "serve":
|
|
377
|
+
success = await openAPIServe({
|
|
378
|
+
port: parsePort(options.port),
|
|
379
|
+
});
|
|
380
|
+
break;
|
|
381
|
+
default:
|
|
382
|
+
console.error(`β Unknown openapi subcommand: ${subCommand}`);
|
|
383
|
+
console.log("\nUsage: bunx mandu openapi <generate|serve>");
|
|
384
|
+
process.exit(1);
|
|
385
|
+
}
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
case "change": {
|
|
390
|
+
const subCommand = args[1];
|
|
391
|
+
switch (subCommand) {
|
|
392
|
+
case "begin":
|
|
393
|
+
success = await changeBegin({ message: options.message });
|
|
394
|
+
break;
|
|
395
|
+
case "commit":
|
|
396
|
+
success = await changeCommit();
|
|
397
|
+
break;
|
|
398
|
+
case "rollback":
|
|
399
|
+
success = await changeRollback({ id: options.id });
|
|
400
|
+
break;
|
|
401
|
+
case "status":
|
|
402
|
+
success = await changeStatus();
|
|
403
|
+
break;
|
|
404
|
+
case "list":
|
|
405
|
+
success = await changeList();
|
|
406
|
+
break;
|
|
407
|
+
case "prune":
|
|
408
|
+
success = await changePrune({
|
|
409
|
+
keep: options.keep ? Number(options.keep) : undefined,
|
|
410
|
+
});
|
|
411
|
+
break;
|
|
412
|
+
default:
|
|
413
|
+
console.error(`β Unknown change subcommand: ${subCommand}`);
|
|
414
|
+
console.log(`\nUsage: bunx mandu change <begin|commit|rollback|status|list|prune>`);
|
|
415
|
+
process.exit(1);
|
|
416
|
+
}
|
|
417
|
+
break;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
case "doctor":
|
|
421
|
+
success = await doctor({
|
|
422
|
+
format: (options.format as "console" | "json" | "markdown") || "console",
|
|
423
|
+
useLLM: options["no-llm"] !== "true",
|
|
424
|
+
output: options.output,
|
|
425
|
+
});
|
|
426
|
+
break;
|
|
427
|
+
|
|
428
|
+
case "watch":
|
|
429
|
+
success = await watch({
|
|
430
|
+
status: options.status === "true",
|
|
431
|
+
debounce: options.debounce ? Number(options.debounce) : undefined,
|
|
432
|
+
});
|
|
433
|
+
break;
|
|
434
|
+
|
|
435
|
+
case "monitor":
|
|
436
|
+
success = await monitor({
|
|
437
|
+
format: options.format as any,
|
|
438
|
+
summary: options.summary === "true",
|
|
439
|
+
since: options.since,
|
|
440
|
+
follow: options.follow === "false" ? false : true,
|
|
441
|
+
file: options.file,
|
|
442
|
+
});
|
|
443
|
+
break;
|
|
444
|
+
|
|
445
|
+
case "brain": {
|
|
446
|
+
const subCommand = args[1];
|
|
447
|
+
switch (subCommand) {
|
|
448
|
+
case "setup":
|
|
449
|
+
success = await brainSetup({
|
|
450
|
+
model: options.model,
|
|
451
|
+
url: options.url,
|
|
452
|
+
skipCheck: options["skip-check"] === "true",
|
|
453
|
+
});
|
|
454
|
+
break;
|
|
455
|
+
case "status":
|
|
456
|
+
success = await brainStatus({
|
|
457
|
+
verbose: options.verbose === "true",
|
|
458
|
+
});
|
|
459
|
+
break;
|
|
460
|
+
default:
|
|
461
|
+
console.error(`β Unknown brain subcommand: ${subCommand}`);
|
|
462
|
+
console.log("\nUsage: bunx mandu brain <setup|status>");
|
|
463
|
+
process.exit(1);
|
|
464
|
+
}
|
|
465
|
+
break;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
default:
|
|
469
|
+
console.error(`β Unknown command: ${command}`);
|
|
470
|
+
console.log(HELP_TEXT);
|
|
471
|
+
process.exit(1);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
if (!success) {
|
|
475
|
+
process.exit(1);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
main().catch((error) => {
|
|
480
|
+
console.error("β μμμΉ λͺ»ν μ€λ₯:", error);
|
|
481
|
+
process.exit(1);
|
|
482
|
+
});
|