@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.
Files changed (51) hide show
  1. package/README.ko.md +234 -234
  2. package/README.md +354 -354
  3. package/package.json +2 -2
  4. package/src/commands/contract.ts +173 -173
  5. package/src/commands/dev.ts +8 -68
  6. package/src/commands/doctor.ts +27 -27
  7. package/src/commands/guard-arch.ts +303 -303
  8. package/src/commands/guard-check.ts +3 -3
  9. package/src/commands/monitor.ts +300 -300
  10. package/src/commands/openapi.ts +107 -107
  11. package/src/commands/registry.ts +367 -357
  12. package/src/commands/routes.ts +228 -228
  13. package/src/commands/start.ts +184 -0
  14. package/src/errors/codes.ts +35 -35
  15. package/src/errors/index.ts +2 -2
  16. package/src/errors/messages.ts +143 -143
  17. package/src/hooks/index.ts +17 -17
  18. package/src/hooks/preaction.ts +256 -256
  19. package/src/main.ts +37 -34
  20. package/src/terminal/banner.ts +166 -166
  21. package/src/terminal/help.ts +306 -306
  22. package/src/terminal/index.ts +71 -71
  23. package/src/terminal/output.ts +295 -295
  24. package/src/terminal/palette.ts +30 -30
  25. package/src/terminal/progress.ts +327 -327
  26. package/src/terminal/stream-writer.ts +214 -214
  27. package/src/terminal/table.ts +354 -354
  28. package/src/terminal/theme.ts +142 -142
  29. package/src/util/bun.ts +6 -6
  30. package/src/util/fs.ts +23 -23
  31. package/src/util/handlers.ts +96 -0
  32. package/src/util/manifest.ts +52 -52
  33. package/src/util/output.ts +22 -22
  34. package/src/util/port.ts +71 -71
  35. package/templates/default/AGENTS.md +96 -96
  36. package/templates/default/app/api/health/route.ts +13 -13
  37. package/templates/default/app/globals.css +49 -49
  38. package/templates/default/app/layout.tsx +27 -27
  39. package/templates/default/app/page.tsx +38 -38
  40. package/templates/default/package.json +1 -0
  41. package/templates/default/src/client/shared/lib/utils.ts +16 -16
  42. package/templates/default/src/client/shared/ui/button.tsx +57 -57
  43. package/templates/default/src/client/shared/ui/card.tsx +78 -78
  44. package/templates/default/src/client/shared/ui/index.ts +21 -21
  45. package/templates/default/src/client/shared/ui/input.tsx +24 -24
  46. package/templates/default/tests/example.test.ts +58 -58
  47. package/templates/default/tests/helpers.ts +52 -52
  48. package/templates/default/tests/setup.ts +9 -9
  49. package/templates/default/tsconfig.json +12 -14
  50. package/templates/default/apps/server/main.ts +0 -67
  51. package/templates/default/apps/web/entry.tsx +0 -35
@@ -1,35 +1,35 @@
1
- /**
2
- * CLI error codes
3
- */
4
- export const CLI_ERROR_CODES = {
5
- // Init errors (E001-E009)
6
- INIT_DIR_EXISTS: "CLI_E001",
7
- INIT_BUN_NOT_FOUND: "CLI_E002",
8
- INIT_TEMPLATE_NOT_FOUND: "CLI_E003",
9
-
10
- // Dev errors (E010-E019)
11
- DEV_PORT_IN_USE: "CLI_E010",
12
- DEV_MANIFEST_NOT_FOUND: "CLI_E011",
13
- DEV_NO_ROUTES: "CLI_E012",
14
-
15
- // Guard errors (E020-E029)
16
- GUARD_CONFIG_INVALID: "CLI_E020",
17
- GUARD_PRESET_NOT_FOUND: "CLI_E021",
18
- GUARD_VIOLATION_FOUND: "CLI_E022",
19
-
20
- // Build errors (E030-E039)
21
- BUILD_ENTRY_NOT_FOUND: "CLI_E030",
22
- BUILD_BUNDLE_FAILED: "CLI_E031",
23
- BUILD_OUTDIR_NOT_WRITABLE: "CLI_E032",
24
-
25
- // Config errors (E040-E049)
26
- CONFIG_PARSE_FAILED: "CLI_E040",
27
- CONFIG_VALIDATION_FAILED: "CLI_E041",
28
-
29
- // CLI usage errors (E100+)
30
- UNKNOWN_COMMAND: "CLI_E100",
31
- UNKNOWN_SUBCOMMAND: "CLI_E101",
32
- MISSING_ARGUMENT: "CLI_E102",
33
- } as const;
34
-
35
- export type CLIErrorCode = typeof CLI_ERROR_CODES[keyof typeof CLI_ERROR_CODES];
1
+ /**
2
+ * CLI error codes
3
+ */
4
+ export const CLI_ERROR_CODES = {
5
+ // Init errors (E001-E009)
6
+ INIT_DIR_EXISTS: "CLI_E001",
7
+ INIT_BUN_NOT_FOUND: "CLI_E002",
8
+ INIT_TEMPLATE_NOT_FOUND: "CLI_E003",
9
+
10
+ // Dev errors (E010-E019)
11
+ DEV_PORT_IN_USE: "CLI_E010",
12
+ DEV_MANIFEST_NOT_FOUND: "CLI_E011",
13
+ DEV_NO_ROUTES: "CLI_E012",
14
+
15
+ // Guard errors (E020-E029)
16
+ GUARD_CONFIG_INVALID: "CLI_E020",
17
+ GUARD_PRESET_NOT_FOUND: "CLI_E021",
18
+ GUARD_VIOLATION_FOUND: "CLI_E022",
19
+
20
+ // Build errors (E030-E039)
21
+ BUILD_ENTRY_NOT_FOUND: "CLI_E030",
22
+ BUILD_BUNDLE_FAILED: "CLI_E031",
23
+ BUILD_OUTDIR_NOT_WRITABLE: "CLI_E032",
24
+
25
+ // Config errors (E040-E049)
26
+ CONFIG_PARSE_FAILED: "CLI_E040",
27
+ CONFIG_VALIDATION_FAILED: "CLI_E041",
28
+
29
+ // CLI usage errors (E100+)
30
+ UNKNOWN_COMMAND: "CLI_E100",
31
+ UNKNOWN_SUBCOMMAND: "CLI_E101",
32
+ MISSING_ARGUMENT: "CLI_E102",
33
+ } as const;
34
+
35
+ export type CLIErrorCode = typeof CLI_ERROR_CODES[keyof typeof CLI_ERROR_CODES];
@@ -1,2 +1,2 @@
1
- export { CLI_ERROR_CODES, type CLIErrorCode } from "./codes";
2
- export { CLIError, formatCLIError, handleCLIError, printCLIError } from "./messages";
1
+ export { CLI_ERROR_CODES, type CLIErrorCode } from "./codes";
2
+ export { CLIError, formatCLIError, handleCLIError, printCLIError } from "./messages";
@@ -1,143 +1,143 @@
1
- import { CLI_ERROR_CODES, type CLIErrorCode } from "./codes";
2
-
3
- interface ErrorInfo {
4
- message: string;
5
- suggestion?: string;
6
- docLink?: string;
7
- }
8
-
9
- export const ERROR_MESSAGES: Record<CLIErrorCode, ErrorInfo> = {
10
- [CLI_ERROR_CODES.INIT_DIR_EXISTS]: {
11
- message: "Directory already exists: {path}",
12
- suggestion: "Choose a different project name or remove the existing directory.",
13
- },
14
- [CLI_ERROR_CODES.INIT_BUN_NOT_FOUND]: {
15
- message: "Bun runtime not found.",
16
- suggestion: "Install Bun and ensure it is available in your PATH.",
17
- },
18
- [CLI_ERROR_CODES.INIT_TEMPLATE_NOT_FOUND]: {
19
- message: "Template not found: {template}",
20
- suggestion: "Use a valid template name (default).",
21
- },
22
- [CLI_ERROR_CODES.DEV_PORT_IN_USE]: {
23
- message: "Port {port} is already in use.",
24
- suggestion: "Set PORT or mandu.config server.port to pick a different port, or stop the process using this port.",
25
- },
26
- [CLI_ERROR_CODES.DEV_MANIFEST_NOT_FOUND]: {
27
- message: "Routes manifest not found.",
28
- suggestion: "Run `mandu routes generate` or create app/ routes before dev.",
29
- },
30
- [CLI_ERROR_CODES.DEV_NO_ROUTES]: {
31
- message: "No routes were found in app/.",
32
- suggestion: "Create app/page.tsx or app/api/*/route.ts to get started.",
33
- },
34
- [CLI_ERROR_CODES.GUARD_CONFIG_INVALID]: {
35
- message: "Invalid guard configuration.",
36
- suggestion: "Check your mandu.config and guard settings.",
37
- },
38
- [CLI_ERROR_CODES.GUARD_PRESET_NOT_FOUND]: {
39
- message: "Unknown architecture preset: {preset}",
40
- suggestion: "Available presets: mandu, fsd, clean, hexagonal, atomic.",
41
- },
42
- [CLI_ERROR_CODES.GUARD_VIOLATION_FOUND]: {
43
- message: "{count} architecture violation(s) found.",
44
- suggestion: "Fix violations above or set MANDU_OUTPUT=agent for AI-friendly output.",
45
- },
46
- [CLI_ERROR_CODES.BUILD_ENTRY_NOT_FOUND]: {
47
- message: "Build entry not found: {entry}",
48
- suggestion: "Check your routes manifest or build inputs.",
49
- },
50
- [CLI_ERROR_CODES.BUILD_BUNDLE_FAILED]: {
51
- message: "Bundle build failed for '{target}'.",
52
- suggestion: "Review build errors above for missing deps or syntax errors.",
53
- },
54
- [CLI_ERROR_CODES.BUILD_OUTDIR_NOT_WRITABLE]: {
55
- message: "Output directory is not writable: {path}",
56
- suggestion: "Ensure the directory exists and you have write permissions.",
57
- },
58
- [CLI_ERROR_CODES.CONFIG_PARSE_FAILED]: {
59
- message: "Failed to parse mandu.config.",
60
- suggestion: "Fix syntax errors in the config file.",
61
- },
62
- [CLI_ERROR_CODES.CONFIG_VALIDATION_FAILED]: {
63
- message: "Configuration validation failed.",
64
- suggestion: "Review validation errors above and fix your config.",
65
- },
66
- [CLI_ERROR_CODES.UNKNOWN_COMMAND]: {
67
- message: "Unknown command: {command}",
68
- suggestion: "Run with --help to see available commands.",
69
- },
70
- [CLI_ERROR_CODES.UNKNOWN_SUBCOMMAND]: {
71
- message: "Unknown subcommand '{subcommand}' for {command}.",
72
- suggestion: "Run the command with --help to see available subcommands.",
73
- },
74
- [CLI_ERROR_CODES.MISSING_ARGUMENT]: {
75
- message: "Missing required argument: {argument}",
76
- suggestion: "Provide the required argument and try again.",
77
- },
78
- };
79
-
80
- function interpolate(text: string, context?: Record<string, string | number>): string {
81
- if (!context) return text;
82
- let result = text;
83
- for (const [key, value] of Object.entries(context)) {
84
- result = result.replace(new RegExp(`\\{${key}\\}`, "g"), String(value));
85
- }
86
- return result;
87
- }
88
-
89
- export function formatCLIError(
90
- code: CLIErrorCode,
91
- context?: Record<string, string | number>
92
- ): string {
93
- const info = ERROR_MESSAGES[code];
94
- const message = interpolate(info?.message ?? "Unknown error", context);
95
- const suggestion = info?.suggestion ? interpolate(info.suggestion, context) : undefined;
96
-
97
- const lines = ["", `❌ Error [${code}]`, ` ${message}`];
98
- if (suggestion) {
99
- lines.push("", `πŸ’‘ ${suggestion}`);
100
- }
101
- if (info?.docLink) {
102
- lines.push(`πŸ“– ${info.docLink}`);
103
- }
104
- lines.push("");
105
- return lines.join("\n");
106
- }
107
-
108
- export class CLIError extends Error {
109
- readonly code: CLIErrorCode;
110
- readonly context?: Record<string, string | number>;
111
-
112
- constructor(code: CLIErrorCode, context?: Record<string, string | number>) {
113
- super(formatCLIError(code, context));
114
- this.code = code;
115
- this.context = context;
116
- this.name = "CLIError";
117
- }
118
- }
119
-
120
- export function printCLIError(
121
- code: CLIErrorCode,
122
- context?: Record<string, string | number>
123
- ): void {
124
- console.error(formatCLIError(code, context));
125
- }
126
-
127
- export function handleCLIError(error: unknown): never {
128
- if (error instanceof CLIError) {
129
- console.error(error.message);
130
- process.exit(1);
131
- }
132
-
133
- if (error instanceof Error) {
134
- console.error(`\n❌ Unexpected error: ${error.message}\n`);
135
- if (process.env.DEBUG) {
136
- console.error(error.stack);
137
- }
138
- process.exit(1);
139
- }
140
-
141
- console.error("\n❌ Unknown error occurred\n");
142
- process.exit(1);
143
- }
1
+ import { CLI_ERROR_CODES, type CLIErrorCode } from "./codes";
2
+
3
+ interface ErrorInfo {
4
+ message: string;
5
+ suggestion?: string;
6
+ docLink?: string;
7
+ }
8
+
9
+ export const ERROR_MESSAGES: Record<CLIErrorCode, ErrorInfo> = {
10
+ [CLI_ERROR_CODES.INIT_DIR_EXISTS]: {
11
+ message: "Directory already exists: {path}",
12
+ suggestion: "Choose a different project name or remove the existing directory.",
13
+ },
14
+ [CLI_ERROR_CODES.INIT_BUN_NOT_FOUND]: {
15
+ message: "Bun runtime not found.",
16
+ suggestion: "Install Bun and ensure it is available in your PATH.",
17
+ },
18
+ [CLI_ERROR_CODES.INIT_TEMPLATE_NOT_FOUND]: {
19
+ message: "Template not found: {template}",
20
+ suggestion: "Use a valid template name (default).",
21
+ },
22
+ [CLI_ERROR_CODES.DEV_PORT_IN_USE]: {
23
+ message: "Port {port} is already in use.",
24
+ suggestion: "Set PORT or mandu.config server.port to pick a different port, or stop the process using this port.",
25
+ },
26
+ [CLI_ERROR_CODES.DEV_MANIFEST_NOT_FOUND]: {
27
+ message: "Routes manifest not found.",
28
+ suggestion: "Run `mandu routes generate` or create app/ routes before dev.",
29
+ },
30
+ [CLI_ERROR_CODES.DEV_NO_ROUTES]: {
31
+ message: "No routes were found in app/.",
32
+ suggestion: "Create app/page.tsx or app/api/*/route.ts to get started.",
33
+ },
34
+ [CLI_ERROR_CODES.GUARD_CONFIG_INVALID]: {
35
+ message: "Invalid guard configuration.",
36
+ suggestion: "Check your mandu.config and guard settings.",
37
+ },
38
+ [CLI_ERROR_CODES.GUARD_PRESET_NOT_FOUND]: {
39
+ message: "Unknown architecture preset: {preset}",
40
+ suggestion: "Available presets: mandu, fsd, clean, hexagonal, atomic.",
41
+ },
42
+ [CLI_ERROR_CODES.GUARD_VIOLATION_FOUND]: {
43
+ message: "{count} architecture violation(s) found.",
44
+ suggestion: "Fix violations above or set MANDU_OUTPUT=agent for AI-friendly output.",
45
+ },
46
+ [CLI_ERROR_CODES.BUILD_ENTRY_NOT_FOUND]: {
47
+ message: "Build entry not found: {entry}",
48
+ suggestion: "Check your routes manifest or build inputs.",
49
+ },
50
+ [CLI_ERROR_CODES.BUILD_BUNDLE_FAILED]: {
51
+ message: "Bundle build failed for '{target}'.",
52
+ suggestion: "Review build errors above for missing deps or syntax errors.",
53
+ },
54
+ [CLI_ERROR_CODES.BUILD_OUTDIR_NOT_WRITABLE]: {
55
+ message: "Output directory is not writable: {path}",
56
+ suggestion: "Ensure the directory exists and you have write permissions.",
57
+ },
58
+ [CLI_ERROR_CODES.CONFIG_PARSE_FAILED]: {
59
+ message: "Failed to parse mandu.config.",
60
+ suggestion: "Fix syntax errors in the config file.",
61
+ },
62
+ [CLI_ERROR_CODES.CONFIG_VALIDATION_FAILED]: {
63
+ message: "Configuration validation failed.",
64
+ suggestion: "Review validation errors above and fix your config.",
65
+ },
66
+ [CLI_ERROR_CODES.UNKNOWN_COMMAND]: {
67
+ message: "Unknown command: {command}",
68
+ suggestion: "Run with --help to see available commands.",
69
+ },
70
+ [CLI_ERROR_CODES.UNKNOWN_SUBCOMMAND]: {
71
+ message: "Unknown subcommand '{subcommand}' for {command}.",
72
+ suggestion: "Run the command with --help to see available subcommands.",
73
+ },
74
+ [CLI_ERROR_CODES.MISSING_ARGUMENT]: {
75
+ message: "Missing required argument: {argument}",
76
+ suggestion: "Provide the required argument and try again.",
77
+ },
78
+ };
79
+
80
+ function interpolate(text: string, context?: Record<string, string | number>): string {
81
+ if (!context) return text;
82
+ let result = text;
83
+ for (const [key, value] of Object.entries(context)) {
84
+ result = result.replace(new RegExp(`\\{${key}\\}`, "g"), String(value));
85
+ }
86
+ return result;
87
+ }
88
+
89
+ export function formatCLIError(
90
+ code: CLIErrorCode,
91
+ context?: Record<string, string | number>
92
+ ): string {
93
+ const info = ERROR_MESSAGES[code];
94
+ const message = interpolate(info?.message ?? "Unknown error", context);
95
+ const suggestion = info?.suggestion ? interpolate(info.suggestion, context) : undefined;
96
+
97
+ const lines = ["", `❌ Error [${code}]`, ` ${message}`];
98
+ if (suggestion) {
99
+ lines.push("", `πŸ’‘ ${suggestion}`);
100
+ }
101
+ if (info?.docLink) {
102
+ lines.push(`πŸ“– ${info.docLink}`);
103
+ }
104
+ lines.push("");
105
+ return lines.join("\n");
106
+ }
107
+
108
+ export class CLIError extends Error {
109
+ readonly code: CLIErrorCode;
110
+ readonly context?: Record<string, string | number>;
111
+
112
+ constructor(code: CLIErrorCode, context?: Record<string, string | number>) {
113
+ super(formatCLIError(code, context));
114
+ this.code = code;
115
+ this.context = context;
116
+ this.name = "CLIError";
117
+ }
118
+ }
119
+
120
+ export function printCLIError(
121
+ code: CLIErrorCode,
122
+ context?: Record<string, string | number>
123
+ ): void {
124
+ console.error(formatCLIError(code, context));
125
+ }
126
+
127
+ export function handleCLIError(error: unknown): never {
128
+ if (error instanceof CLIError) {
129
+ console.error(error.message);
130
+ process.exit(1);
131
+ }
132
+
133
+ if (error instanceof Error) {
134
+ console.error(`\n❌ Unexpected error: ${error.message}\n`);
135
+ if (process.env.DEBUG) {
136
+ console.error(error.stack);
137
+ }
138
+ process.exit(1);
139
+ }
140
+
141
+ console.error("\n❌ Unknown error occurred\n");
142
+ process.exit(1);
143
+ }
@@ -1,17 +1,17 @@
1
- /**
2
- * DNA-016: CLI Hooks
3
- *
4
- * λͺ…λ Ήμ–΄ 라이프사이클 ν›…
5
- */
6
-
7
- export {
8
- preActionRegistry,
9
- runPreAction,
10
- registerPreActionHook,
11
- registerDefaultHooks,
12
- setVerbose,
13
- isVerbose,
14
- setProcessTitle,
15
- type PreActionContext,
16
- type PreActionHook,
17
- } from "./preaction.js";
1
+ /**
2
+ * DNA-016: CLI Hooks
3
+ *
4
+ * λͺ…λ Ήμ–΄ 라이프사이클 ν›…
5
+ */
6
+
7
+ export {
8
+ preActionRegistry,
9
+ runPreAction,
10
+ registerPreActionHook,
11
+ registerDefaultHooks,
12
+ setVerbose,
13
+ isVerbose,
14
+ setProcessTitle,
15
+ type PreActionContext,
16
+ type PreActionHook,
17
+ } from "./preaction.js";