@mandujs/cli 0.13.2 → 0.14.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mandujs/cli",
3
- "version": "0.13.2",
3
+ "version": "0.14.0",
4
4
  "description": "Agent-Native Fullstack Framework - 에이전트가 코딩해도 아키텍처가 무너지지 않는 개발 OS",
5
5
  "type": "module",
6
6
  "main": "./src/main.ts",
@@ -36,7 +36,7 @@ export async function check(): Promise<boolean> {
36
36
  const quiet = false;
37
37
  const strictWarnings = process.env.CI === "true";
38
38
  const enableFsRoutes = await isDirectory(path.resolve(rootDir, "app"));
39
- const specPath = resolveFromCwd("spec/routes.manifest.json");
39
+ const specPath = resolveFromCwd(".mandu/routes.manifest.json");
40
40
  const hasSpec = await pathExists(specPath);
41
41
 
42
42
  let success = true;
@@ -71,8 +71,6 @@ export async function check(): Promise<boolean> {
71
71
  if (format === "console") {
72
72
  const result = await generateManifest(rootDir, {
73
73
  scanner: config.fsRoutes,
74
- outputPath: ".mandu/routes.manifest.json",
75
- skipLegacy: true,
76
74
  });
77
75
  routesSummary.count = result.manifest.routes.length;
78
76
  routesSummary.warnings = result.warnings;
@@ -217,9 +215,9 @@ export async function check(): Promise<boolean> {
217
215
  }
218
216
  } else {
219
217
  if (quiet) {
220
- print("ℹ️ spec/routes.manifest.json 없음 - 레거시 Guard 스킵");
218
+ print("ℹ️ .mandu/routes.manifest.json 없음 - Guard 스킵");
221
219
  } else {
222
- log("ℹ️ spec/routes.manifest.json 없음 - 레거시 Guard 스킵");
220
+ log("ℹ️ .mandu/routes.manifest.json 없음 - Guard 스킵");
223
221
  }
224
222
  }
225
223
 
@@ -344,7 +344,6 @@ export async function dev(options: DevOptions = {}): Promise<void> {
344
344
 
345
345
  // FS Routes 실시간 감시
346
346
  const routesWatcher = await watchFSRoutes(rootDir, {
347
- skipLegacy: true,
348
347
  onChange: async (result) => {
349
348
  const timestamp = new Date().toLocaleTimeString();
350
349
  console.log(`\n🔄 [${timestamp}] 라우트 변경 감지`);
@@ -32,7 +32,7 @@ export async function doctor(options: DoctorOptions = {}): Promise<boolean> {
32
32
  const inferredFormat = format ?? (output ? (path.extname(output).toLowerCase() === ".json" ? "json" : "markdown") : undefined);
33
33
  const resolvedFormat = inferredFormat ?? "console";
34
34
 
35
- const specPath = resolveFromCwd("spec/routes.manifest.json");
35
+ const specPath = resolveFromCwd(".mandu/routes.manifest.json");
36
36
  const rootDir = getRootDir();
37
37
 
38
38
  console.log(`🩺 Mandu Doctor`);
@@ -1,22 +1,25 @@
1
- import { loadManifest, generateRoutes, buildGenerateReport, printReportSummary, writeReport } from "@mandujs/core";
1
+ import { loadManifest, generateManifest, generateRoutes, buildGenerateReport, printReportSummary, writeReport } from "@mandujs/core";
2
2
  import { resolveFromCwd, getRootDir } from "../util/fs";
3
3
 
4
4
  export async function generateApply(): Promise<boolean> {
5
- const specPath = resolveFromCwd("spec/routes.manifest.json");
6
5
  const rootDir = getRootDir();
6
+ const manifestPath = resolveFromCwd(".mandu/routes.manifest.json");
7
7
 
8
8
  console.log(`🥟 Mandu Generate`);
9
- console.log(`📄 Spec 파일: ${specPath}\n`);
9
+ console.log(`📄 FS Routes 기반 코드 생성\n`);
10
10
 
11
- const result = await loadManifest(specPath);
11
+ // Regenerate manifest from FS Routes
12
+ const fsResult = await generateManifest(rootDir);
13
+ console.log(`✅ 매니페스트 생성 완료 (${fsResult.fsRoutesCount}개 라우트)`);
14
+
15
+ const result = await loadManifest(manifestPath);
12
16
 
13
17
  if (!result.success || !result.data) {
14
- console.error("❌ Spec 로드 실패:");
18
+ console.error("❌ 매니페스트 로드 실패:");
15
19
  result.errors?.forEach((e) => console.error(` - ${e}`));
16
20
  return false;
17
21
  }
18
22
 
19
- console.log(`✅ Spec 로드 완료 (${result.data.routes.length}개 라우트)`);
20
23
  console.log(`🔄 코드 생성 중...\n`);
21
24
 
22
25
  const generateResult = await generateRoutes(result.data, rootDir);
@@ -16,7 +16,7 @@ export interface GuardCheckOptions {
16
16
  export async function guardCheck(options: GuardCheckOptions = {}): Promise<boolean> {
17
17
  const { autoCorrect = true } = options;
18
18
 
19
- const specPath = resolveFromCwd("spec/routes.manifest.json");
19
+ const specPath = resolveFromCwd(".mandu/routes.manifest.json");
20
20
  const rootDir = getRootDir();
21
21
 
22
22
  console.log(`🥟 Mandu Guard (Legacy Spec)`);
@@ -347,10 +347,10 @@ registerCommand({
347
347
  },
348
348
  });
349
349
 
350
- // 레거시 명령어
350
+ // 레거시 명령어 (DEPRECATED)
351
351
  registerCommand({
352
352
  id: "spec-upsert",
353
- description: "Spec 파일 검증 및 lock 갱신 (레거시)",
353
+ description: "[DEPRECATED] Spec 파일 검증 및 lock 갱신 → routes generate 사용",
354
354
  async run(ctx) {
355
355
  const { specUpsert } = await import("./spec-upsert");
356
356
  return specUpsert({ file: ctx.options.file });
@@ -359,7 +359,7 @@ registerCommand({
359
359
 
360
360
  registerCommand({
361
361
  id: "generate",
362
- description: "Spec에서 코드 생성 (레거시)",
362
+ description: "FS Routes 기반 코드 생성",
363
363
  async run() {
364
364
  const { generateApply } = await import("./generate-apply");
365
365
  return generateApply();
@@ -55,8 +55,7 @@ export async function routesGenerate(options: RoutesGenerateOptions = {}): Promi
55
55
  try {
56
56
  const generateOptions: GenerateOptions = {
57
57
  scanner: config.fsRoutes,
58
- outputPath: options.output ?? ".mandu/routes.manifest.json",
59
- skipLegacy: true, // 레거시 병합 비활성화
58
+ outputPath: options.output,
60
59
  };
61
60
 
62
61
  const result = await generateManifest(rootDir, generateOptions);
@@ -7,9 +7,13 @@ export interface SpecUpsertOptions {
7
7
  }
8
8
 
9
9
  export async function specUpsert(options: SpecUpsertOptions): Promise<boolean> {
10
+ console.warn("⚠️ DEPRECATED: spec-upsert는 더 이상 필요하지 않습니다.");
11
+ console.warn(" FS Routes(app/)가 유일한 라우트 소스입니다.");
12
+ console.warn(" 대신 'bunx mandu routes generate'를 사용하세요.\n");
13
+
10
14
  const specPath = options.file
11
15
  ? resolveFromCwd(options.file)
12
- : resolveFromCwd("spec/routes.manifest.json");
16
+ : resolveFromCwd(".mandu/routes.manifest.json");
13
17
 
14
18
  console.log(`🥟 Mandu Spec Upsert`);
15
19
  console.log(`📄 Spec 파일: ${specPath}\n`);
@@ -31,7 +35,7 @@ export async function specUpsert(options: SpecUpsertOptions): Promise<boolean> {
31
35
  console.log(` ${kindIcon} ${route.id}: ${route.pattern} (${route.kind})`);
32
36
  }
33
37
 
34
- const lockPath = resolveFromCwd("spec/spec.lock.json");
38
+ const lockPath = resolveFromCwd(".mandu/spec.lock.json");
35
39
  const previousLock = await readLock(lockPath);
36
40
  const newLock = await writeLock(lockPath, result.data);
37
41
 
@@ -7,7 +7,7 @@ import {
7
7
  } from "@mandujs/core";
8
8
  import { isDirectory } from "./fs";
9
9
 
10
- export type ManifestSource = "fs" | "spec";
10
+ export type ManifestSource = "fs";
11
11
 
12
12
  export interface ResolvedManifest {
13
13
  manifest: RoutesManifest;
@@ -22,31 +22,17 @@ export async function resolveManifest(
22
22
  const appDir = path.resolve(rootDir, "app");
23
23
  const hasApp = await isDirectory(appDir);
24
24
 
25
- if (hasApp) {
26
- const result = await generateManifest(rootDir, {
27
- scanner: options.fsRoutes,
28
- outputPath: options.outputPath,
29
- skipLegacy: true,
30
- });
31
- return {
32
- manifest: result.manifest,
33
- source: "fs",
34
- warnings: result.warnings,
35
- };
25
+ if (!hasApp) {
26
+ throw new Error("No app/ directory found. Create app/ routes to get started.");
36
27
  }
37
28
 
38
- const specPath = path.join(rootDir, "spec", "routes.manifest.json");
39
- if (await Bun.file(specPath).exists()) {
40
- const result = await loadManifest(specPath);
41
- if (!result.success) {
42
- throw new Error(result.errors?.join(", ") || "Failed to load routes manifest");
43
- }
44
- return {
45
- manifest: result.data!,
46
- source: "spec",
47
- warnings: [],
48
- };
49
- }
50
-
51
- throw new Error("No routes found. Create app/ routes or spec/routes.manifest.json");
29
+ const result = await generateManifest(rootDir, {
30
+ scanner: options.fsRoutes,
31
+ outputPath: options.outputPath,
32
+ });
33
+ return {
34
+ manifest: result.manifest,
35
+ source: "fs",
36
+ warnings: result.warnings,
37
+ };
52
38
  }