@mandujs/cli 0.15.1 → 0.15.3
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 +33 -33
- package/README.md +354 -354
- package/package.json +2 -2
- package/src/commands/check.ts +71 -7
- package/src/commands/contract.ts +173 -173
- package/src/commands/dev.ts +9 -42
- package/src/commands/guard-arch.ts +303 -303
- package/src/commands/init.ts +50 -5
- package/src/commands/monitor.ts +300 -300
- package/src/commands/openapi.ts +107 -107
- package/src/commands/registry.ts +1 -0
- package/src/commands/start.ts +9 -42
- 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 +9 -7
- 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 +49 -5
- package/src/util/lockfile.ts +66 -0
- 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/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 +1 -1
- package/templates/default/src/client/shared/ui/index.ts +21 -21
- package/templates/default/src/client/shared/ui/input.tsx +5 -1
- 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 +23 -23
- package/templates/realtime-chat/AGENTS.md +96 -0
- package/templates/realtime-chat/app/api/chat/messages/route.ts +63 -0
- package/templates/realtime-chat/app/api/chat/stream/route.ts +85 -0
- package/templates/realtime-chat/app/api/health/route.ts +13 -0
- package/templates/realtime-chat/app/globals.css +49 -0
- package/templates/realtime-chat/app/layout.tsx +27 -0
- package/templates/realtime-chat/app/page.tsx +16 -0
- package/templates/realtime-chat/package.json +34 -0
- package/templates/realtime-chat/src/client/app/index.ts +1 -0
- package/templates/realtime-chat/src/client/entities/index.ts +1 -0
- package/templates/realtime-chat/src/client/features/chat/chat-api.ts +209 -0
- package/templates/realtime-chat/src/client/features/chat/realtime-chat-starter.client.tsx +89 -0
- package/templates/realtime-chat/src/client/features/chat/use-realtime-chat.ts +65 -0
- package/templates/realtime-chat/src/client/features/index.ts +1 -0
- package/templates/realtime-chat/src/client/pages/index.ts +1 -0
- package/templates/realtime-chat/src/client/shared/index.ts +1 -0
- package/templates/realtime-chat/src/client/shared/lib/utils.ts +16 -0
- package/templates/realtime-chat/src/client/shared/ui/button.tsx +57 -0
- package/templates/realtime-chat/src/client/shared/ui/card.tsx +78 -0
- package/templates/realtime-chat/src/client/shared/ui/index.ts +21 -0
- package/templates/realtime-chat/src/client/shared/ui/input.tsx +28 -0
- package/templates/realtime-chat/src/client/widgets/index.ts +1 -0
- package/templates/realtime-chat/src/server/api/index.ts +1 -0
- package/templates/realtime-chat/src/server/application/ai-adapter.ts +24 -0
- package/templates/realtime-chat/src/server/application/chat-store.ts +158 -0
- package/templates/realtime-chat/src/server/application/index.ts +1 -0
- package/templates/realtime-chat/src/server/core/index.ts +1 -0
- package/templates/realtime-chat/src/server/domain/index.ts +1 -0
- package/templates/realtime-chat/src/server/infra/index.ts +1 -0
- package/templates/realtime-chat/src/shared/contracts/chat.ts +29 -0
- package/templates/realtime-chat/src/shared/contracts/index.ts +1 -0
- package/templates/realtime-chat/src/shared/env/index.ts +1 -0
- package/templates/realtime-chat/src/shared/schema/index.ts +1 -0
- package/templates/realtime-chat/src/shared/types/index.ts +1 -0
- package/templates/realtime-chat/src/shared/utils/client/index.ts +1 -0
- package/templates/realtime-chat/src/shared/utils/server/index.ts +1 -0
- package/templates/realtime-chat/tests/chat-api.sse.test.ts +188 -0
- package/templates/realtime-chat/tests/chat-starter.test.ts +200 -0
- package/templates/realtime-chat/tests/chat-store.concurrency.test.ts +39 -0
- package/templates/realtime-chat/tests/example.test.ts +58 -0
- package/templates/realtime-chat/tests/helpers.ts +52 -0
- package/templates/realtime-chat/tests/setup.ts +9 -0
- package/templates/realtime-chat/tsconfig.json +23 -0
package/src/commands/openapi.ts
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
* OpenAPI 스펙 생성 명령어
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { generateOpenAPIDocument, openAPIToJSON, validateAndReport } from "@mandujs/core";
|
|
7
|
-
import path from "path";
|
|
8
|
-
import fs from "fs/promises";
|
|
9
|
-
import { resolveManifest } from "../util/manifest";
|
|
6
|
+
import { generateOpenAPIDocument, openAPIToJSON, validateAndReport } from "@mandujs/core";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import fs from "fs/promises";
|
|
9
|
+
import { resolveManifest } from "../util/manifest";
|
|
10
10
|
|
|
11
11
|
interface OpenAPIGenerateOptions {
|
|
12
12
|
output?: string;
|
|
@@ -14,78 +14,78 @@ interface OpenAPIGenerateOptions {
|
|
|
14
14
|
version?: string;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
interface OpenAPIServeOptions {
|
|
18
|
-
port?: number;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function normalizePort(value: string | number | undefined, label: string): number | undefined {
|
|
22
|
-
if (value === undefined || value === null || value === "") {
|
|
23
|
-
return undefined;
|
|
24
|
-
}
|
|
25
|
-
const port = typeof value === "string" ? Number(value) : value;
|
|
26
|
-
if (!Number.isFinite(port) || !Number.isInteger(port)) {
|
|
27
|
-
console.warn(`⚠️ Invalid ${label} value: "${value}" (using default)`);
|
|
28
|
-
return undefined;
|
|
29
|
-
}
|
|
30
|
-
if (port < 1 || port > 65535) {
|
|
31
|
-
console.warn(`⚠️ Invalid ${label} range: ${port} (must be 1-65535, using default)`);
|
|
32
|
-
return undefined;
|
|
33
|
-
}
|
|
34
|
-
return port;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function isPortInUse(error: unknown): boolean {
|
|
38
|
-
if (!error || typeof error !== "object") return false;
|
|
39
|
-
const code = (error as { code?: string }).code;
|
|
40
|
-
const message = (error as { message?: string }).message ?? "";
|
|
41
|
-
return code === "EADDRINUSE" || message.includes("EADDRINUSE") || message.includes("address already in use");
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function serveWithAutoPort(
|
|
45
|
-
startPort: number,
|
|
46
|
-
fetch: (req: Request) => Response
|
|
47
|
-
): { server: ReturnType<typeof Bun.serve>; port: number; attempts: number } {
|
|
48
|
-
const maxAttempts = 10;
|
|
49
|
-
let lastError: unknown = null;
|
|
50
|
-
|
|
51
|
-
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
52
|
-
const candidate = startPort + attempt;
|
|
53
|
-
if (candidate < 1 || candidate > 65535) {
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
try {
|
|
57
|
-
const server = Bun.serve({ port: candidate, fetch });
|
|
58
|
-
return { server, port: server.port ?? candidate, attempts: attempt };
|
|
59
|
-
} catch (error) {
|
|
60
|
-
if (!isPortInUse(error)) {
|
|
61
|
-
throw error;
|
|
62
|
-
}
|
|
63
|
-
lastError = error;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
throw lastError ?? new Error(`No available port found starting at ${startPort}`);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Generate OpenAPI specification from contracts
|
|
72
|
-
*/
|
|
73
|
-
export async function openAPIGenerate(options: OpenAPIGenerateOptions = {}): Promise<boolean> {
|
|
74
|
-
const rootDir = process.cwd();
|
|
75
|
-
|
|
76
|
-
console.log(`\n📄 Generating OpenAPI specification...\n`);
|
|
77
|
-
|
|
78
|
-
// Load manifest (FS Routes 우선)
|
|
79
|
-
let manifest: Awaited<ReturnType<typeof resolveManifest>>["manifest"];
|
|
80
|
-
try {
|
|
81
|
-
const config = await validateAndReport(rootDir);
|
|
82
|
-
if (!config) return false;
|
|
83
|
-
const resolved = await resolveManifest(rootDir, { fsRoutes: config.fsRoutes });
|
|
84
|
-
manifest = resolved.manifest;
|
|
85
|
-
} catch (error) {
|
|
86
|
-
console.error("❌ Failed to load manifest:", error instanceof Error ? error.message : error);
|
|
87
|
-
return false;
|
|
88
|
-
}
|
|
17
|
+
interface OpenAPIServeOptions {
|
|
18
|
+
port?: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function normalizePort(value: string | number | undefined, label: string): number | undefined {
|
|
22
|
+
if (value === undefined || value === null || value === "") {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
const port = typeof value === "string" ? Number(value) : value;
|
|
26
|
+
if (!Number.isFinite(port) || !Number.isInteger(port)) {
|
|
27
|
+
console.warn(`⚠️ Invalid ${label} value: "${value}" (using default)`);
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
if (port < 1 || port > 65535) {
|
|
31
|
+
console.warn(`⚠️ Invalid ${label} range: ${port} (must be 1-65535, using default)`);
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
return port;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function isPortInUse(error: unknown): boolean {
|
|
38
|
+
if (!error || typeof error !== "object") return false;
|
|
39
|
+
const code = (error as { code?: string }).code;
|
|
40
|
+
const message = (error as { message?: string }).message ?? "";
|
|
41
|
+
return code === "EADDRINUSE" || message.includes("EADDRINUSE") || message.includes("address already in use");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function serveWithAutoPort(
|
|
45
|
+
startPort: number,
|
|
46
|
+
fetch: (req: Request) => Response
|
|
47
|
+
): { server: ReturnType<typeof Bun.serve>; port: number; attempts: number } {
|
|
48
|
+
const maxAttempts = 10;
|
|
49
|
+
let lastError: unknown = null;
|
|
50
|
+
|
|
51
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
52
|
+
const candidate = startPort + attempt;
|
|
53
|
+
if (candidate < 1 || candidate > 65535) {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const server = Bun.serve({ port: candidate, fetch });
|
|
58
|
+
return { server, port: server.port ?? candidate, attempts: attempt };
|
|
59
|
+
} catch (error) {
|
|
60
|
+
if (!isPortInUse(error)) {
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
lastError = error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
throw lastError ?? new Error(`No available port found starting at ${startPort}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Generate OpenAPI specification from contracts
|
|
72
|
+
*/
|
|
73
|
+
export async function openAPIGenerate(options: OpenAPIGenerateOptions = {}): Promise<boolean> {
|
|
74
|
+
const rootDir = process.cwd();
|
|
75
|
+
|
|
76
|
+
console.log(`\n📄 Generating OpenAPI specification...\n`);
|
|
77
|
+
|
|
78
|
+
// Load manifest (FS Routes 우선)
|
|
79
|
+
let manifest: Awaited<ReturnType<typeof resolveManifest>>["manifest"];
|
|
80
|
+
try {
|
|
81
|
+
const config = await validateAndReport(rootDir);
|
|
82
|
+
if (!config) return false;
|
|
83
|
+
const resolved = await resolveManifest(rootDir, { fsRoutes: config.fsRoutes });
|
|
84
|
+
manifest = resolved.manifest;
|
|
85
|
+
} catch (error) {
|
|
86
|
+
console.error("❌ Failed to load manifest:", error instanceof Error ? error.message : error);
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
89
|
|
|
90
90
|
// Count routes with contracts
|
|
91
91
|
const contractRoutes = manifest.routes.filter((r) => r.contractModule);
|
|
@@ -148,16 +148,16 @@ export async function openAPIGenerate(options: OpenAPIGenerateOptions = {}): Pro
|
|
|
148
148
|
/**
|
|
149
149
|
* Serve Swagger UI for OpenAPI documentation
|
|
150
150
|
*/
|
|
151
|
-
export async function openAPIServe(options: OpenAPIServeOptions = {}): Promise<boolean> {
|
|
152
|
-
const rootDir = process.cwd();
|
|
153
|
-
const config = await validateAndReport(rootDir);
|
|
154
|
-
if (!config) return false;
|
|
155
|
-
|
|
156
|
-
const optionPort = normalizePort(options.port, "openapi.port");
|
|
157
|
-
const envPort = normalizePort(process.env.PORT, "PORT");
|
|
158
|
-
const configPort = normalizePort(config.server?.port, "mandu.config server.port");
|
|
159
|
-
const desiredPort = optionPort ?? envPort ?? configPort ?? 8080;
|
|
160
|
-
const openAPIPath = path.join(rootDir, "openapi.json");
|
|
151
|
+
export async function openAPIServe(options: OpenAPIServeOptions = {}): Promise<boolean> {
|
|
152
|
+
const rootDir = process.cwd();
|
|
153
|
+
const config = await validateAndReport(rootDir);
|
|
154
|
+
if (!config) return false;
|
|
155
|
+
|
|
156
|
+
const optionPort = normalizePort(options.port, "openapi.port");
|
|
157
|
+
const envPort = normalizePort(process.env.PORT, "PORT");
|
|
158
|
+
const configPort = normalizePort(config.server?.port, "mandu.config server.port");
|
|
159
|
+
const desiredPort = optionPort ?? envPort ?? configPort ?? 8080;
|
|
160
|
+
const openAPIPath = path.join(rootDir, "openapi.json");
|
|
161
161
|
|
|
162
162
|
console.log(`\n🌐 Starting OpenAPI documentation server...\n`);
|
|
163
163
|
|
|
@@ -212,27 +212,27 @@ export async function openAPIServe(options: OpenAPIServeOptions = {}): Promise<b
|
|
|
212
212
|
</html>
|
|
213
213
|
`.trim();
|
|
214
214
|
|
|
215
|
-
// Start server (auto port fallback)
|
|
216
|
-
const { port, attempts } = serveWithAutoPort(desiredPort, (req) => {
|
|
217
|
-
const url = new URL(req.url);
|
|
218
|
-
|
|
219
|
-
if (url.pathname === "/openapi.json") {
|
|
220
|
-
return new Response(specContent, {
|
|
221
|
-
headers: { "Content-Type": "application/json" },
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
return new Response(swaggerHTML, {
|
|
226
|
-
headers: { "Content-Type": "text/html" },
|
|
227
|
-
});
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
if (attempts > 0) {
|
|
231
|
-
console.warn(`⚠️ Port ${desiredPort} is in use. Using ${port} instead.`);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
console.log(`✅ Swagger UI is running at http://localhost:${port}`);
|
|
235
|
-
console.log(` OpenAPI spec: http://localhost:${port}/openapi.json`);
|
|
215
|
+
// Start server (auto port fallback)
|
|
216
|
+
const { port, attempts } = serveWithAutoPort(desiredPort, (req) => {
|
|
217
|
+
const url = new URL(req.url);
|
|
218
|
+
|
|
219
|
+
if (url.pathname === "/openapi.json") {
|
|
220
|
+
return new Response(specContent, {
|
|
221
|
+
headers: { "Content-Type": "application/json" },
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return new Response(swaggerHTML, {
|
|
226
|
+
headers: { "Content-Type": "text/html" },
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
if (attempts > 0) {
|
|
231
|
+
console.warn(`⚠️ Port ${desiredPort} is in use. Using ${port} instead.`);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
console.log(`✅ Swagger UI is running at http://localhost:${port}`);
|
|
235
|
+
console.log(` OpenAPI spec: http://localhost:${port}/openapi.json`);
|
|
236
236
|
console.log(`\nPress Ctrl+C to stop.\n`);
|
|
237
237
|
|
|
238
238
|
// Keep server running
|
package/src/commands/registry.ts
CHANGED
|
@@ -70,6 +70,7 @@ registerCommand({
|
|
|
70
70
|
const { init } = await import("./init");
|
|
71
71
|
return init({
|
|
72
72
|
name: ctx.options.name || ctx.options._positional,
|
|
73
|
+
template: ctx.options.template,
|
|
73
74
|
css: ctx.options.css as any,
|
|
74
75
|
ui: ctx.options.ui as any,
|
|
75
76
|
theme: ctx.options.theme === "true",
|
package/src/commands/start.ts
CHANGED
|
@@ -8,12 +8,6 @@ import {
|
|
|
8
8
|
startServer,
|
|
9
9
|
loadEnv,
|
|
10
10
|
validateAndReport,
|
|
11
|
-
readLockfile,
|
|
12
|
-
readMcpConfig,
|
|
13
|
-
validateWithPolicy,
|
|
14
|
-
detectMode,
|
|
15
|
-
formatPolicyAction,
|
|
16
|
-
formatValidationResult,
|
|
17
11
|
type RoutesManifest,
|
|
18
12
|
type BundleManifest,
|
|
19
13
|
} from "@mandujs/core";
|
|
@@ -21,6 +15,11 @@ import { resolveFromCwd } from "../util/fs";
|
|
|
21
15
|
import { CLI_ERROR_CODES, printCLIError } from "../errors";
|
|
22
16
|
import { resolveManifest } from "../util/manifest";
|
|
23
17
|
import { resolveAvailablePort } from "../util/port";
|
|
18
|
+
import {
|
|
19
|
+
validateRuntimeLockfile,
|
|
20
|
+
handleBlockedLockfile,
|
|
21
|
+
printRuntimeLockfileStatus,
|
|
22
|
+
} from "../util/lockfile";
|
|
24
23
|
import { registerManifestHandlers } from "../util/handlers";
|
|
25
24
|
import path from "path";
|
|
26
25
|
import fs from "fs";
|
|
@@ -55,48 +54,15 @@ export async function start(options: StartOptions = {}): Promise<void> {
|
|
|
55
54
|
}
|
|
56
55
|
|
|
57
56
|
// Lockfile 검증 (strict: block 정책)
|
|
58
|
-
const lockfile = await
|
|
59
|
-
|
|
60
|
-
try {
|
|
61
|
-
mcpConfig = await readMcpConfig(rootDir);
|
|
62
|
-
} catch (error) {
|
|
63
|
-
console.warn(
|
|
64
|
-
`⚠️ MCP 설정 로드 실패: ${error instanceof Error ? error.message : String(error)}`
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
const { result: lockResult, action, bypassed } = validateWithPolicy(
|
|
68
|
-
config,
|
|
69
|
-
lockfile,
|
|
70
|
-
detectMode(),
|
|
71
|
-
mcpConfig
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
if (action === "block") {
|
|
75
|
-
console.error("🛑 서버 시작 차단: Lockfile 불일치");
|
|
76
|
-
console.error(" 설정이 변경되었습니다. 의도한 변경이라면:");
|
|
77
|
-
console.error(" $ mandu lock");
|
|
78
|
-
console.error("");
|
|
79
|
-
console.error(" 변경 사항 확인:");
|
|
80
|
-
console.error(" $ mandu lock --diff");
|
|
81
|
-
if (lockResult) {
|
|
82
|
-
console.error("");
|
|
83
|
-
console.error(formatValidationResult(lockResult));
|
|
84
|
-
}
|
|
85
|
-
process.exit(1);
|
|
86
|
-
}
|
|
57
|
+
const { lockfile, lockResult, action, bypassed } = await validateRuntimeLockfile(config, rootDir);
|
|
58
|
+
handleBlockedLockfile(action, lockResult);
|
|
87
59
|
|
|
88
60
|
const serverConfig = config.server ?? {};
|
|
89
61
|
|
|
90
62
|
console.log(`🥟 Mandu Production Server`);
|
|
91
63
|
|
|
92
64
|
// Lockfile 상태 출력
|
|
93
|
-
|
|
94
|
-
console.log(`⚠️ ${formatPolicyAction(action, bypassed)}`);
|
|
95
|
-
} else if (lockfile && lockResult?.valid) {
|
|
96
|
-
console.log(`🔒 설정 무결성 확인됨 (${lockResult.currentHash?.slice(0, 8)})`);
|
|
97
|
-
} else if (!lockfile) {
|
|
98
|
-
console.log(`💡 Lockfile 없음 - 'mandu lock'으로 생성 권장`);
|
|
99
|
-
}
|
|
65
|
+
printRuntimeLockfileStatus(action, bypassed, lockfile, lockResult);
|
|
100
66
|
|
|
101
67
|
// .env 파일 로드 (production 모드)
|
|
102
68
|
const envResult = await loadEnv({
|
|
@@ -167,6 +133,7 @@ export async function start(options: StartOptions = {}): Promise<void> {
|
|
|
167
133
|
bundleManifest,
|
|
168
134
|
cors: serverConfig.cors,
|
|
169
135
|
streaming: serverConfig.streaming,
|
|
136
|
+
rateLimit: serverConfig.rateLimit,
|
|
170
137
|
});
|
|
171
138
|
|
|
172
139
|
const actualPort = server.server.port ?? port;
|
package/src/errors/codes.ts
CHANGED
|
@@ -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];
|
package/src/errors/index.ts
CHANGED
|
@@ -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";
|