@mandujs/core 0.18.6 → 0.18.8
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/bundler/dev.ts +22 -16
- package/src/client/router.ts +7 -0
- package/src/filling/filling.ts +12 -0
- package/src/runtime/ssr.ts +19 -0
package/package.json
CHANGED
package/src/bundler/dev.ts
CHANGED
|
@@ -103,8 +103,18 @@ export async function startDevBundler(options: DevBundlerOptions): Promise<DevBu
|
|
|
103
103
|
const normalizedPath = absPath.replace(/\\/g, "/");
|
|
104
104
|
clientModuleToRoute.set(normalizedPath, route.id);
|
|
105
105
|
|
|
106
|
-
//
|
|
106
|
+
// Also register *.client.tsx/ts files in the same directory (#140)
|
|
107
|
+
// e.g. if clientModule is app/page.island.tsx, also map app/page.client.tsx → same routeId
|
|
107
108
|
const dir = path.dirname(absPath);
|
|
109
|
+
const baseStem = path.basename(absPath).replace(/\.(island|client)\.(tsx?|jsx?)$/, "");
|
|
110
|
+
for (const ext of [".client.tsx", ".client.ts", ".client.jsx", ".client.js"]) {
|
|
111
|
+
const clientPath = path.join(dir, baseStem + ext).replace(/\\/g, "/");
|
|
112
|
+
if (clientPath !== normalizedPath) {
|
|
113
|
+
clientModuleToRoute.set(clientPath, route.id);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// 감시할 디렉토리 추가
|
|
108
118
|
watchDirs.add(dir);
|
|
109
119
|
}
|
|
110
120
|
}
|
|
@@ -224,21 +234,17 @@ export async function startDevBundler(options: DevBundlerOptions): Promise<DevBu
|
|
|
224
234
|
// clientModule 매핑에서 routeId 찾기
|
|
225
235
|
let routeId = clientModuleToRoute.get(normalizedPath);
|
|
226
236
|
|
|
227
|
-
//
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
const route = manifest.routes.find((r) => r.id === basename);
|
|
239
|
-
if (route) {
|
|
240
|
-
routeId = route.id;
|
|
241
|
-
}
|
|
237
|
+
// Fallback for *.client.tsx/ts: find route whose clientModule is in the same directory (#140)
|
|
238
|
+
// basename matching (e.g. "page" !== "index") is unreliable — use directory-based matching instead
|
|
239
|
+
if (!routeId && (changedFile.endsWith(".client.ts") || changedFile.endsWith(".client.tsx"))) {
|
|
240
|
+
const changedDir = path.dirname(path.resolve(rootDir, changedFile)).replace(/\\/g, "/");
|
|
241
|
+
const matchedRoute = manifest.routes.find((r) => {
|
|
242
|
+
if (!r.clientModule) return false;
|
|
243
|
+
const routeDir = path.dirname(path.resolve(rootDir, r.clientModule)).replace(/\\/g, "/");
|
|
244
|
+
return routeDir === changedDir;
|
|
245
|
+
});
|
|
246
|
+
if (matchedRoute) {
|
|
247
|
+
routeId = matchedRoute.id;
|
|
242
248
|
}
|
|
243
249
|
}
|
|
244
250
|
|
package/src/client/router.ts
CHANGED
|
@@ -410,6 +410,13 @@ export function initializeRouter(): void {
|
|
|
410
410
|
// 링크 클릭 이벤트 위임
|
|
411
411
|
document.addEventListener("click", handleLinkClick);
|
|
412
412
|
|
|
413
|
+
// DevTools 자동 초기화 (개발 모드에서 SSR이 __MANDU_DEV_TOOLS__를 주입한 경우)
|
|
414
|
+
if ((window as any).__MANDU_DEV_TOOLS__) {
|
|
415
|
+
import("../devtools/init").then(({ initManduKitchen }) => {
|
|
416
|
+
initManduKitchen({ position: "bottom-right" });
|
|
417
|
+
}).catch(() => {});
|
|
418
|
+
}
|
|
419
|
+
|
|
413
420
|
console.log("[Mandu Router] Initialized");
|
|
414
421
|
}
|
|
415
422
|
|
package/src/filling/filling.ts
CHANGED
|
@@ -375,6 +375,18 @@ export class ManduFilling<TLoaderData = unknown> {
|
|
|
375
375
|
return Array.from(this.config.handlers.keys());
|
|
376
376
|
}
|
|
377
377
|
|
|
378
|
+
/**
|
|
379
|
+
* Convert to named handler exports compatible with Mandu route.ts files.
|
|
380
|
+
* Usage: export const { GET, POST } = filling.toHandlers();
|
|
381
|
+
*/
|
|
382
|
+
toHandlers(): Partial<Record<HttpMethod, (req: Request) => Promise<Response>>> {
|
|
383
|
+
const result: Partial<Record<HttpMethod, (req: Request) => Promise<Response>>> = {};
|
|
384
|
+
for (const method of this.config.handlers.keys()) {
|
|
385
|
+
result[method] = (req: Request) => this.handle(req, {}, undefined);
|
|
386
|
+
}
|
|
387
|
+
return result;
|
|
388
|
+
}
|
|
389
|
+
|
|
378
390
|
hasMethod(method: HttpMethod): boolean {
|
|
379
391
|
return this.config.handlers.has(method);
|
|
380
392
|
}
|
package/src/runtime/ssr.ts
CHANGED
|
@@ -238,6 +238,12 @@ export function renderToHTML(element: ReactElement, options: SSROptions = {}): s
|
|
|
238
238
|
hmrScript = generateHMRScript(hmrPort);
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
+
// DevTools 부트스트랩 스크립트 (개발 모드)
|
|
242
|
+
let devtoolsScript = "";
|
|
243
|
+
if (isDev) {
|
|
244
|
+
devtoolsScript = generateDevtoolsBootstrapScript();
|
|
245
|
+
}
|
|
246
|
+
|
|
241
247
|
return `<!doctype html>
|
|
242
248
|
<html lang="${escapeHtmlAttr(lang)}">
|
|
243
249
|
<head>
|
|
@@ -255,6 +261,7 @@ export function renderToHTML(element: ReactElement, options: SSROptions = {}): s
|
|
|
255
261
|
${needsHydration ? REACT_INTERNALS_SHIM_SCRIPT : ""}
|
|
256
262
|
${routerScript}
|
|
257
263
|
${hmrScript}
|
|
264
|
+
${devtoolsScript}
|
|
258
265
|
${bodyEndTags}
|
|
259
266
|
</body>
|
|
260
267
|
</html>`;
|
|
@@ -364,6 +371,18 @@ function generateHMRScript(port: number): string {
|
|
|
364
371
|
</script>`;
|
|
365
372
|
}
|
|
366
373
|
|
|
374
|
+
/**
|
|
375
|
+
* DevTools 부트스트랩 스크립트 생성 (개발 모드 전용)
|
|
376
|
+
*/
|
|
377
|
+
function generateDevtoolsBootstrapScript(): string {
|
|
378
|
+
return `<script>
|
|
379
|
+
(function() {
|
|
380
|
+
if (typeof window === 'undefined') return;
|
|
381
|
+
window.__MANDU_DEV_TOOLS__ = true;
|
|
382
|
+
})();
|
|
383
|
+
</script>`;
|
|
384
|
+
}
|
|
385
|
+
|
|
367
386
|
export function createHTMLResponse(html: string, status: number = 200): Response {
|
|
368
387
|
return new Response(html, {
|
|
369
388
|
status,
|