@mandujs/cli 0.12.2 → 0.13.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.
- 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/terminal/banner.ts
CHANGED
|
@@ -1,166 +1,166 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DNA-017: Hero Banner with cfonts + gradient
|
|
3
|
-
*
|
|
4
|
-
* Sexy ASCII art banner for CLI startup
|
|
5
|
-
* Inspired by Claude Code, Vite, Astro CLI screens
|
|
6
|
-
*
|
|
7
|
-
* @see https://github.com/dominikwilkowski/cfonts
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { theme, isRich, stripAnsi } from "./theme.js";
|
|
11
|
-
import { MANDU_PALETTE } from "./palette.js";
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Check if banner should be displayed
|
|
15
|
-
*/
|
|
16
|
-
export function shouldShowBanner(argv: string[]): boolean {
|
|
17
|
-
// Environment-based skip
|
|
18
|
-
if (process.env.MANDU_NO_BANNER) return false;
|
|
19
|
-
if (process.env.CI) return false;
|
|
20
|
-
if (process.env.CLAUDE_CODE) return false;
|
|
21
|
-
if (process.env.CODEX_AGENT) return false;
|
|
22
|
-
if (process.env.MANDU_AGENT) return false;
|
|
23
|
-
|
|
24
|
-
// TTY check
|
|
25
|
-
if (!process.stdout.isTTY) return false;
|
|
26
|
-
|
|
27
|
-
// Flag-based skip
|
|
28
|
-
const hasJsonFlag = argv.includes("--json");
|
|
29
|
-
const hasQuietFlag = argv.includes("--quiet") || argv.includes("-q");
|
|
30
|
-
const hasHelpFlag = argv.includes("--help") || argv.includes("-h");
|
|
31
|
-
|
|
32
|
-
if (hasJsonFlag || hasQuietFlag || hasHelpFlag) return false;
|
|
33
|
-
|
|
34
|
-
return true;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Fallback ASCII art banner (no dependencies)
|
|
39
|
-
*/
|
|
40
|
-
const MANDU_ASCII_SMALL = `
|
|
41
|
-
╔╦╗╔═╗╔╗╔╔╦╗╦ ╦
|
|
42
|
-
║║║╠═╣║║║ ║║║ ║
|
|
43
|
-
╩ ╩╩ ╩╝╚╝═╩╝╚═╝
|
|
44
|
-
`;
|
|
45
|
-
|
|
46
|
-
const MANDU_ASCII_LARGE = `
|
|
47
|
-
███╗ ███╗ █████╗ ███╗ ██╗██████╗ ██╗ ██╗
|
|
48
|
-
████╗ ████║██╔══██╗████╗ ██║██╔══██╗██║ ██║
|
|
49
|
-
██╔████╔██║███████║██╔██╗ ██║██║ ██║██║ ██║
|
|
50
|
-
██║╚██╔╝██║██╔══██║██║╚██╗██║██║ ██║██║ ██║
|
|
51
|
-
██║ ╚═╝ ██║██║ ██║██║ ╚████║██████╔╝╚██████╔╝
|
|
52
|
-
╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═════╝ ╚═════╝
|
|
53
|
-
`;
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Apply gradient effect to text (simple version)
|
|
57
|
-
*/
|
|
58
|
-
function applyGradient(text: string): string {
|
|
59
|
-
if (!isRich()) return text;
|
|
60
|
-
|
|
61
|
-
const lines = text.split("\n");
|
|
62
|
-
const colorFns = [
|
|
63
|
-
theme.accentDim,
|
|
64
|
-
theme.accent,
|
|
65
|
-
theme.accentBright,
|
|
66
|
-
theme.accent,
|
|
67
|
-
theme.accentDim,
|
|
68
|
-
];
|
|
69
|
-
|
|
70
|
-
return lines
|
|
71
|
-
.map((line, i) => {
|
|
72
|
-
const colorIndex = Math.min(i, colorFns.length - 1);
|
|
73
|
-
const colorFn = colorFns[colorIndex];
|
|
74
|
-
return colorFn(line);
|
|
75
|
-
})
|
|
76
|
-
.join("\n");
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Render hero banner with cfonts (if available) or fallback
|
|
81
|
-
*/
|
|
82
|
-
export async function renderHeroBanner(version: string): Promise<void> {
|
|
83
|
-
const cols = process.stdout.columns ?? 80;
|
|
84
|
-
|
|
85
|
-
// Very narrow terminal: minimal output
|
|
86
|
-
if (cols < 40) {
|
|
87
|
-
console.log(`\n 🥟 Mandu v${version}\n`);
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Try cfonts first
|
|
92
|
-
try {
|
|
93
|
-
const cfonts = await import("cfonts");
|
|
94
|
-
|
|
95
|
-
cfonts.say("MANDU", {
|
|
96
|
-
font: "block",
|
|
97
|
-
gradient: [MANDU_PALETTE.accent, MANDU_PALETTE.accentBright],
|
|
98
|
-
transitionGradient: true,
|
|
99
|
-
align: "center",
|
|
100
|
-
space: true,
|
|
101
|
-
maxLength: Math.min(cols - 4, 80),
|
|
102
|
-
});
|
|
103
|
-
} catch {
|
|
104
|
-
// cfonts not available, use fallback
|
|
105
|
-
const ascii = cols >= 60 ? MANDU_ASCII_LARGE : MANDU_ASCII_SMALL;
|
|
106
|
-
console.log(applyGradient(ascii));
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Tagline
|
|
110
|
-
const tagline = `🥟 Agent-Native Web Framework v${version}`;
|
|
111
|
-
const taglineWidth = stripAnsi(tagline).length;
|
|
112
|
-
const padding = Math.max(0, Math.floor((cols - taglineWidth) / 2));
|
|
113
|
-
|
|
114
|
-
console.log(" ".repeat(padding) + theme.muted(tagline));
|
|
115
|
-
console.log();
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Render minimal banner (for narrow terminals or quick commands)
|
|
120
|
-
*/
|
|
121
|
-
export function renderMiniBanner(version: string): void {
|
|
122
|
-
if (!isRich()) {
|
|
123
|
-
console.log(`\nMandu v${version}\n`);
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
console.log();
|
|
128
|
-
console.log(` ${theme.heading("🥟 Mandu")} ${theme.muted(`v${version}`)}`);
|
|
129
|
-
console.log(` ${theme.muted("Agent-Native Web Framework")}`);
|
|
130
|
-
console.log();
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Render box banner (alternative style)
|
|
135
|
-
*/
|
|
136
|
-
export function renderBoxBanner(version: string): void {
|
|
137
|
-
if (!isRich()) {
|
|
138
|
-
console.log(`\nMandu v${version}\n`);
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const width = 30;
|
|
143
|
-
const top = theme.accent(" ╭" + "─".repeat(width) + "╮");
|
|
144
|
-
const mid1 =
|
|
145
|
-
theme.accent(" │") +
|
|
146
|
-
" " +
|
|
147
|
-
theme.heading("🥟 Mandu") +
|
|
148
|
-
" " +
|
|
149
|
-
theme.muted(`v${version}`) +
|
|
150
|
-
" ".repeat(width - 18 - version.length) +
|
|
151
|
-
theme.accent("│");
|
|
152
|
-
const mid2 =
|
|
153
|
-
theme.accent(" │") +
|
|
154
|
-
" " +
|
|
155
|
-
theme.muted("Agent-Native Framework") +
|
|
156
|
-
" ".repeat(width - 24) +
|
|
157
|
-
theme.accent("│");
|
|
158
|
-
const bottom = theme.accent(" ╰" + "─".repeat(width) + "╯");
|
|
159
|
-
|
|
160
|
-
console.log();
|
|
161
|
-
console.log(top);
|
|
162
|
-
console.log(mid1);
|
|
163
|
-
console.log(mid2);
|
|
164
|
-
console.log(bottom);
|
|
165
|
-
console.log();
|
|
166
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* DNA-017: Hero Banner with cfonts + gradient
|
|
3
|
+
*
|
|
4
|
+
* Sexy ASCII art banner for CLI startup
|
|
5
|
+
* Inspired by Claude Code, Vite, Astro CLI screens
|
|
6
|
+
*
|
|
7
|
+
* @see https://github.com/dominikwilkowski/cfonts
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { theme, isRich, stripAnsi } from "./theme.js";
|
|
11
|
+
import { MANDU_PALETTE } from "./palette.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Check if banner should be displayed
|
|
15
|
+
*/
|
|
16
|
+
export function shouldShowBanner(argv: string[]): boolean {
|
|
17
|
+
// Environment-based skip
|
|
18
|
+
if (process.env.MANDU_NO_BANNER) return false;
|
|
19
|
+
if (process.env.CI) return false;
|
|
20
|
+
if (process.env.CLAUDE_CODE) return false;
|
|
21
|
+
if (process.env.CODEX_AGENT) return false;
|
|
22
|
+
if (process.env.MANDU_AGENT) return false;
|
|
23
|
+
|
|
24
|
+
// TTY check
|
|
25
|
+
if (!process.stdout.isTTY) return false;
|
|
26
|
+
|
|
27
|
+
// Flag-based skip
|
|
28
|
+
const hasJsonFlag = argv.includes("--json");
|
|
29
|
+
const hasQuietFlag = argv.includes("--quiet") || argv.includes("-q");
|
|
30
|
+
const hasHelpFlag = argv.includes("--help") || argv.includes("-h");
|
|
31
|
+
|
|
32
|
+
if (hasJsonFlag || hasQuietFlag || hasHelpFlag) return false;
|
|
33
|
+
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Fallback ASCII art banner (no dependencies)
|
|
39
|
+
*/
|
|
40
|
+
const MANDU_ASCII_SMALL = `
|
|
41
|
+
╔╦╗╔═╗╔╗╔╔╦╗╦ ╦
|
|
42
|
+
║║║╠═╣║║║ ║║║ ║
|
|
43
|
+
╩ ╩╩ ╩╝╚╝═╩╝╚═╝
|
|
44
|
+
`;
|
|
45
|
+
|
|
46
|
+
const MANDU_ASCII_LARGE = `
|
|
47
|
+
███╗ ███╗ █████╗ ███╗ ██╗██████╗ ██╗ ██╗
|
|
48
|
+
████╗ ████║██╔══██╗████╗ ██║██╔══██╗██║ ██║
|
|
49
|
+
██╔████╔██║███████║██╔██╗ ██║██║ ██║██║ ██║
|
|
50
|
+
██║╚██╔╝██║██╔══██║██║╚██╗██║██║ ██║██║ ██║
|
|
51
|
+
██║ ╚═╝ ██║██║ ██║██║ ╚████║██████╔╝╚██████╔╝
|
|
52
|
+
╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═════╝ ╚═════╝
|
|
53
|
+
`;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Apply gradient effect to text (simple version)
|
|
57
|
+
*/
|
|
58
|
+
function applyGradient(text: string): string {
|
|
59
|
+
if (!isRich()) return text;
|
|
60
|
+
|
|
61
|
+
const lines = text.split("\n");
|
|
62
|
+
const colorFns = [
|
|
63
|
+
theme.accentDim,
|
|
64
|
+
theme.accent,
|
|
65
|
+
theme.accentBright,
|
|
66
|
+
theme.accent,
|
|
67
|
+
theme.accentDim,
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
return lines
|
|
71
|
+
.map((line, i) => {
|
|
72
|
+
const colorIndex = Math.min(i, colorFns.length - 1);
|
|
73
|
+
const colorFn = colorFns[colorIndex];
|
|
74
|
+
return colorFn(line);
|
|
75
|
+
})
|
|
76
|
+
.join("\n");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Render hero banner with cfonts (if available) or fallback
|
|
81
|
+
*/
|
|
82
|
+
export async function renderHeroBanner(version: string): Promise<void> {
|
|
83
|
+
const cols = process.stdout.columns ?? 80;
|
|
84
|
+
|
|
85
|
+
// Very narrow terminal: minimal output
|
|
86
|
+
if (cols < 40) {
|
|
87
|
+
console.log(`\n 🥟 Mandu v${version}\n`);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Try cfonts first
|
|
92
|
+
try {
|
|
93
|
+
const cfonts = await import("cfonts");
|
|
94
|
+
|
|
95
|
+
cfonts.say("MANDU", {
|
|
96
|
+
font: "block",
|
|
97
|
+
gradient: [MANDU_PALETTE.accent, MANDU_PALETTE.accentBright],
|
|
98
|
+
transitionGradient: true,
|
|
99
|
+
align: "center",
|
|
100
|
+
space: true,
|
|
101
|
+
maxLength: Math.min(cols - 4, 80),
|
|
102
|
+
});
|
|
103
|
+
} catch {
|
|
104
|
+
// cfonts not available, use fallback
|
|
105
|
+
const ascii = cols >= 60 ? MANDU_ASCII_LARGE : MANDU_ASCII_SMALL;
|
|
106
|
+
console.log(applyGradient(ascii));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Tagline
|
|
110
|
+
const tagline = `🥟 Agent-Native Web Framework v${version}`;
|
|
111
|
+
const taglineWidth = stripAnsi(tagline).length;
|
|
112
|
+
const padding = Math.max(0, Math.floor((cols - taglineWidth) / 2));
|
|
113
|
+
|
|
114
|
+
console.log(" ".repeat(padding) + theme.muted(tagline));
|
|
115
|
+
console.log();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Render minimal banner (for narrow terminals or quick commands)
|
|
120
|
+
*/
|
|
121
|
+
export function renderMiniBanner(version: string): void {
|
|
122
|
+
if (!isRich()) {
|
|
123
|
+
console.log(`\nMandu v${version}\n`);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
console.log();
|
|
128
|
+
console.log(` ${theme.heading("🥟 Mandu")} ${theme.muted(`v${version}`)}`);
|
|
129
|
+
console.log(` ${theme.muted("Agent-Native Web Framework")}`);
|
|
130
|
+
console.log();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Render box banner (alternative style)
|
|
135
|
+
*/
|
|
136
|
+
export function renderBoxBanner(version: string): void {
|
|
137
|
+
if (!isRich()) {
|
|
138
|
+
console.log(`\nMandu v${version}\n`);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const width = 30;
|
|
143
|
+
const top = theme.accent(" ╭" + "─".repeat(width) + "╮");
|
|
144
|
+
const mid1 =
|
|
145
|
+
theme.accent(" │") +
|
|
146
|
+
" " +
|
|
147
|
+
theme.heading("🥟 Mandu") +
|
|
148
|
+
" " +
|
|
149
|
+
theme.muted(`v${version}`) +
|
|
150
|
+
" ".repeat(width - 18 - version.length) +
|
|
151
|
+
theme.accent("│");
|
|
152
|
+
const mid2 =
|
|
153
|
+
theme.accent(" │") +
|
|
154
|
+
" " +
|
|
155
|
+
theme.muted("Agent-Native Framework") +
|
|
156
|
+
" ".repeat(width - 24) +
|
|
157
|
+
theme.accent("│");
|
|
158
|
+
const bottom = theme.accent(" ╰" + "─".repeat(width) + "╯");
|
|
159
|
+
|
|
160
|
+
console.log();
|
|
161
|
+
console.log(top);
|
|
162
|
+
console.log(mid1);
|
|
163
|
+
console.log(mid2);
|
|
164
|
+
console.log(bottom);
|
|
165
|
+
console.log();
|
|
166
|
+
}
|