@mandujs/core 0.9.12 → 0.9.14
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 +1 -1
- package/src/brain/types.ts +2 -0
- package/src/generator/generate.ts +8 -0
- package/src/watcher/rules.ts +20 -0
- package/src/watcher/watcher.ts +19 -3
package/package.json
CHANGED
package/src/brain/types.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { RoutesManifest, RouteSpec } from "../spec/schema";
|
|
|
2
2
|
import { generateApiHandler, generatePageComponent, generateSlotLogic } from "./templates";
|
|
3
3
|
import { generateContractTypeGlue, generateContractTemplate, generateContractTypesIndex } from "./contract-glue";
|
|
4
4
|
import { computeHash } from "../spec/lock";
|
|
5
|
+
import { getWatcher } from "../watcher/watcher";
|
|
5
6
|
import path from "path";
|
|
6
7
|
import fs from "fs/promises";
|
|
7
8
|
|
|
@@ -135,6 +136,10 @@ export async function generateRoutes(
|
|
|
135
136
|
warnings: [],
|
|
136
137
|
};
|
|
137
138
|
|
|
139
|
+
// Suppress watcher during generation to avoid false positives
|
|
140
|
+
const watcher = getWatcher();
|
|
141
|
+
watcher?.suppress();
|
|
142
|
+
|
|
138
143
|
const serverRoutesDir = path.join(rootDir, "apps/server/generated/routes");
|
|
139
144
|
const webRoutesDir = path.join(rootDir, "apps/web/generated/routes");
|
|
140
145
|
const typesDir = path.join(rootDir, "apps/server/generated/types");
|
|
@@ -338,5 +343,8 @@ export async function generateRoutes(
|
|
|
338
343
|
const mapPath = path.join(mapDir, "generated.map.json");
|
|
339
344
|
await Bun.write(mapPath, JSON.stringify(generatedMap, null, 2));
|
|
340
345
|
|
|
346
|
+
// Resume watcher after generation
|
|
347
|
+
watcher?.resume();
|
|
348
|
+
|
|
341
349
|
return result;
|
|
342
350
|
}
|
package/src/watcher/rules.ts
CHANGED
|
@@ -63,6 +63,14 @@ export const MVP_RULES: ArchRule[] = [
|
|
|
63
63
|
message: "Generated 파일에서 금지된 모듈이 import되었습니다.",
|
|
64
64
|
forbiddenImports: ["fs", "child_process", "cluster", "worker_threads"],
|
|
65
65
|
},
|
|
66
|
+
{
|
|
67
|
+
id: "SLOT_MODIFIED",
|
|
68
|
+
name: "Slot File Modified",
|
|
69
|
+
description: "Slot 파일이 수정되었습니다",
|
|
70
|
+
pattern: "spec/slots/*.slot.ts",
|
|
71
|
+
action: "warn",
|
|
72
|
+
message: "Slot 수정 감지. mandu_validate_slot 또는 mandu_guard_check로 검증하세요.",
|
|
73
|
+
},
|
|
66
74
|
{
|
|
67
75
|
id: "ISLAND_FIRST_MODIFIED",
|
|
68
76
|
name: "Island-First ComponentModule Modified",
|
|
@@ -236,6 +244,18 @@ export async function validateFile(
|
|
|
236
244
|
event,
|
|
237
245
|
});
|
|
238
246
|
}
|
|
247
|
+
|
|
248
|
+
// Slot modified: info level notification
|
|
249
|
+
if (rule.id === "SLOT_MODIFIED" && event !== "delete") {
|
|
250
|
+
warnings.push({
|
|
251
|
+
ruleId: rule.id,
|
|
252
|
+
file: relativePath,
|
|
253
|
+
message: rule.message,
|
|
254
|
+
timestamp: new Date(),
|
|
255
|
+
event,
|
|
256
|
+
level: "info",
|
|
257
|
+
});
|
|
258
|
+
}
|
|
239
259
|
}
|
|
240
260
|
|
|
241
261
|
return warnings;
|
package/src/watcher/watcher.ts
CHANGED
|
@@ -21,7 +21,7 @@ import chokidar, { type FSWatcher } from "chokidar";
|
|
|
21
21
|
*/
|
|
22
22
|
function formatWarning(warning: WatchWarning): string {
|
|
23
23
|
const time = new Date().toLocaleTimeString("ko-KR", { hour12: false });
|
|
24
|
-
const icon = warning.event === "delete" ? "[DEL]" : "[WARN]";
|
|
24
|
+
const icon = warning.level === "info" ? "[INFO]" : warning.event === "delete" ? "[DEL]" : "[WARN]";
|
|
25
25
|
return `${time} ${icon} ${warning.ruleId}\n ${warning.file}\n ${warning.message}\n`;
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -67,6 +67,7 @@ export class FileWatcher {
|
|
|
67
67
|
private logFile: string | null = null;
|
|
68
68
|
private logStream: fs.WriteStream | null = null;
|
|
69
69
|
private tailProcess: ChildProcess | null = null;
|
|
70
|
+
private _suppressed: boolean = false;
|
|
70
71
|
|
|
71
72
|
constructor(config: WatcherConfig) {
|
|
72
73
|
this.config = {
|
|
@@ -105,8 +106,7 @@ export class FileWatcher {
|
|
|
105
106
|
`${"=".repeat(50)}\n\n`
|
|
106
107
|
);
|
|
107
108
|
|
|
108
|
-
//
|
|
109
|
-
this.openLogTerminal(this.logFile, rootDir);
|
|
109
|
+
// Terminal is now handled by ActivityMonitor in MCP server
|
|
110
110
|
|
|
111
111
|
// Build sets for fast lookup
|
|
112
112
|
const ignoredSet = new Set(ignoreDirs || []);
|
|
@@ -230,6 +230,20 @@ export class FileWatcher {
|
|
|
230
230
|
this.recentWarnings = [];
|
|
231
231
|
}
|
|
232
232
|
|
|
233
|
+
/**
|
|
234
|
+
* Suppress warnings (e.g. during generate)
|
|
235
|
+
*/
|
|
236
|
+
suppress(): void {
|
|
237
|
+
this._suppressed = true;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Resume warnings after suppression
|
|
242
|
+
*/
|
|
243
|
+
resume(): void {
|
|
244
|
+
this._suppressed = false;
|
|
245
|
+
}
|
|
246
|
+
|
|
233
247
|
/**
|
|
234
248
|
* Open a new terminal window tailing the log file
|
|
235
249
|
*/
|
|
@@ -267,6 +281,8 @@ export class FileWatcher {
|
|
|
267
281
|
event: "create" | "modify" | "delete",
|
|
268
282
|
filePath: string
|
|
269
283
|
): Promise<void> {
|
|
284
|
+
if (this._suppressed) return;
|
|
285
|
+
|
|
270
286
|
const { rootDir } = this.config;
|
|
271
287
|
|
|
272
288
|
// Validate file against rules
|