@mandujs/core 0.18.19 → 0.18.20

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/core",
3
- "version": "0.18.19",
3
+ "version": "0.18.20",
4
4
  "description": "Mandu Framework Core - Spec, Generator, Guard, Runtime",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -19,6 +19,11 @@ export interface DevBundlerOptions {
19
19
  onRebuild?: (result: RebuildResult) => void;
20
20
  /** 에러 콜백 */
21
21
  onError?: (error: Error, routeId?: string) => void;
22
+ /**
23
+ * SSR 파일 변경 콜백 (page.tsx, layout.tsx 등)
24
+ * 클라이언트 번들 리빌드 없이 서버 핸들러 재등록이 필요한 경우 호출
25
+ */
26
+ onSSRChange?: (filePath: string) => void;
22
27
  /**
23
28
  * 추가 watch 디렉토리 (공통 컴포넌트 등)
24
29
  * 상대 경로 또는 절대 경로 모두 지원
@@ -75,6 +80,7 @@ export async function startDevBundler(options: DevBundlerOptions): Promise<DevBu
75
80
  manifest,
76
81
  onRebuild,
77
82
  onError,
83
+ onSSRChange,
78
84
  watchDirs: customWatchDirs = [],
79
85
  disableDefaultWatchDirs = false,
80
86
  } = options;
@@ -94,6 +100,7 @@ export async function startDevBundler(options: DevBundlerOptions): Promise<DevBu
94
100
 
95
101
  // clientModule 경로에서 routeId 매핑 생성
96
102
  const clientModuleToRoute = new Map<string, string>();
103
+ const serverModuleSet = new Set<string>(); // SSR 모듈 (page.tsx, layout.tsx)
97
104
  const watchDirs = new Set<string>();
98
105
  const commonWatchDirs = new Set<string>(); // 공통 디렉토리 (전체 재빌드 트리거)
99
106
 
@@ -117,6 +124,20 @@ export async function startDevBundler(options: DevBundlerOptions): Promise<DevBu
117
124
  // 감시할 디렉토리 추가
118
125
  watchDirs.add(dir);
119
126
  }
127
+
128
+ // SSR 모듈 등록 (page.tsx, layout.tsx) — #151
129
+ if (route.componentModule) {
130
+ const absPath = path.resolve(rootDir, route.componentModule).replace(/\\/g, "/");
131
+ serverModuleSet.add(absPath);
132
+ watchDirs.add(path.dirname(path.resolve(rootDir, route.componentModule)));
133
+ }
134
+ if (route.layoutChain) {
135
+ for (const layoutPath of route.layoutChain) {
136
+ const absPath = path.resolve(rootDir, layoutPath).replace(/\\/g, "/");
137
+ serverModuleSet.add(absPath);
138
+ watchDirs.add(path.dirname(path.resolve(rootDir, layoutPath)));
139
+ }
140
+ }
120
141
  }
121
142
 
122
143
  // spec/slots 디렉토리도 추가
@@ -248,7 +269,14 @@ export async function startDevBundler(options: DevBundlerOptions): Promise<DevBu
248
269
  }
249
270
  }
250
271
 
251
- if (!routeId) return;
272
+ if (!routeId) {
273
+ // SSR 모듈 변경 감지 (page.tsx, layout.tsx) — #151
274
+ if (onSSRChange && serverModuleSet.has(normalizedPath)) {
275
+ console.log(`\n🔄 SSR file changed: ${path.basename(changedFile)}`);
276
+ onSSRChange(normalizedPath);
277
+ }
278
+ return;
279
+ }
252
280
 
253
281
  const route = manifest.routes.find((r) => r.id === routeId);
254
282
  if (!route || !route.clientModule) return;
@@ -1168,6 +1168,7 @@ function startBunServerWithFallback(options: {
1168
1168
  port: 0,
1169
1169
  hostname,
1170
1170
  fetch,
1171
+ idleTimeout: 255,
1171
1172
  });
1172
1173
  return { server, port: server.port ?? 0, attempts: 0 };
1173
1174
  }
@@ -1182,6 +1183,7 @@ function startBunServerWithFallback(options: {
1182
1183
  port: candidate,
1183
1184
  hostname,
1184
1185
  fetch,
1186
+ idleTimeout: 255,
1185
1187
  });
1186
1188
  return { server, port: server.port ?? candidate, attempts: attempt };
1187
1189
  } catch (error) {