@mandujs/core 0.18.8 → 0.18.9

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.8",
3
+ "version": "0.18.9",
4
4
  "description": "Mandu Framework Core - Spec, Generator, Guard, Runtime",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -744,6 +744,72 @@ if (document.readyState === 'loading') {
744
744
  `;
745
745
  }
746
746
 
747
+ /**
748
+ * DevTools 번들 빌드 (개발 모드 전용)
749
+ * devtools/init.ts를 브라우저용 번들로 컴파일하여 _devtools.js 생성
750
+ */
751
+ async function buildDevtoolsBundle(
752
+ outDir: string,
753
+ options: BundlerOptions
754
+ ): Promise<{ success: boolean; outputPath: string; errors: string[] }> {
755
+ const srcPath = path.join(outDir, "_devtools.src.js");
756
+ const outputName = "_devtools.js";
757
+
758
+ // devtools/init.ts의 절대 경로 (build.ts → ../devtools/init.ts)
759
+ const devtoolsInitPath = path.resolve(
760
+ import.meta.dir, '..', 'devtools', 'init.ts'
761
+ ).replace(/\\/g, '/');
762
+
763
+ const source = `
764
+ import { initManduKitchen } from "${devtoolsInitPath}";
765
+ if (typeof window !== 'undefined') {
766
+ window.__MANDU_DEV_TOOLS__ = true;
767
+ initManduKitchen({ position: 'bottom-right' });
768
+ }
769
+ `;
770
+
771
+ try {
772
+ await Bun.write(srcPath, source);
773
+
774
+ const result = await Bun.build({
775
+ entrypoints: [srcPath],
776
+ outdir: outDir,
777
+ naming: outputName,
778
+ minify: false, // dev only
779
+ sourcemap: options.sourcemap ? "external" : "none",
780
+ target: "browser",
781
+ external: ["react", "react-dom", "react-dom/client"],
782
+ define: {
783
+ "process.env.NODE_ENV": JSON.stringify("development"),
784
+ ...options.define,
785
+ },
786
+ });
787
+
788
+ await fs.unlink(srcPath).catch(() => {});
789
+
790
+ if (!result.success) {
791
+ return {
792
+ success: false,
793
+ outputPath: "",
794
+ errors: result.logs.map((l) => l.message),
795
+ };
796
+ }
797
+
798
+ return {
799
+ success: true,
800
+ outputPath: `/.mandu/client/${outputName}`,
801
+ errors: [],
802
+ };
803
+ } catch (error) {
804
+ await fs.unlink(srcPath).catch(() => {});
805
+ return {
806
+ success: false,
807
+ outputPath: "",
808
+ errors: [String(error)],
809
+ };
810
+ }
811
+ }
812
+
747
813
  /**
748
814
  * Router 런타임 번들 빌드
749
815
  */
@@ -1251,22 +1317,34 @@ export async function buildClientBundles(
1251
1317
  return { success: errors.length === 0, outputs, errors, manifest: existingManifest, stats };
1252
1318
  }
1253
1319
 
1254
- // 3-4. Runtime, Router, Vendor 번들 병렬 빌드 (서로 독립적)
1255
- const [runtimeResult, routerResult, vendorResult] = await Promise.all([
1320
+ // 3-4. Runtime, Router, Vendor, DevTools 번들 병렬 빌드 (서로 독립적)
1321
+ const buildPromises: Promise<any>[] = [
1256
1322
  buildRuntime(outDir, options),
1257
1323
  buildRouterRuntime(outDir, options),
1258
1324
  buildVendorShims(outDir, options),
1259
- ]);
1325
+ ];
1326
+
1327
+ // DevTools 번들은 dev 모드에서만 빌드
1328
+ const isDev = env === "development";
1329
+ if (isDev) {
1330
+ buildPromises.push(buildDevtoolsBundle(outDir, options));
1331
+ }
1332
+
1333
+ const [runtimeResult, routerResult, vendorResult, devtoolsResult] = await Promise.all(buildPromises);
1260
1334
 
1261
1335
  if (!runtimeResult.success) {
1262
- errors.push(...runtimeResult.errors.map((e) => `[Runtime] ${e}`));
1336
+ errors.push(...runtimeResult.errors.map((e: string) => `[Runtime] ${e}`));
1263
1337
  }
1264
1338
  if (!routerResult.success) {
1265
- errors.push(...routerResult.errors.map((e) => `[Router] ${e}`));
1339
+ errors.push(...routerResult.errors.map((e: string) => `[Router] ${e}`));
1266
1340
  }
1267
1341
  if (!vendorResult.success) {
1268
1342
  errors.push(...vendorResult.errors);
1269
1343
  }
1344
+ if (devtoolsResult && !devtoolsResult.success) {
1345
+ // DevTools 빌드 실패는 경고만 (개발 중단시키지 않음)
1346
+ console.warn("[Mandu] DevTools bundle build failed:", devtoolsResult.errors.join(", "));
1347
+ }
1270
1348
 
1271
1349
  // 5. 각 Island 번들 빌드
1272
1350
  for (const route of hydratedRoutes) {
@@ -410,13 +410,6 @@ 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
-
420
413
  console.log("[Mandu Router] Initialized");
421
414
  }
422
415
 
@@ -238,10 +238,10 @@ export function renderToHTML(element: ReactElement, options: SSROptions = {}): s
238
238
  hmrScript = generateHMRScript(hmrPort);
239
239
  }
240
240
 
241
- // DevTools 부트스트랩 스크립트 (개발 모드)
241
+ // DevTools 번들 로드 (개발 모드)
242
242
  let devtoolsScript = "";
243
243
  if (isDev) {
244
- devtoolsScript = generateDevtoolsBootstrapScript();
244
+ devtoolsScript = generateDevtoolsScript();
245
245
  }
246
246
 
247
247
  return `<!doctype html>
@@ -372,15 +372,11 @@ function generateHMRScript(port: number): string {
372
372
  }
373
373
 
374
374
  /**
375
- * DevTools 부트스트랩 스크립트 생성 (개발 모드 전용)
375
+ * DevTools 번들 로드 스크립트 생성 (개발 모드 전용)
376
+ * _devtools.js 번들이 자체적으로 initManduKitchen()을 호출
376
377
  */
377
- function generateDevtoolsBootstrapScript(): string {
378
- return `<script>
379
- (function() {
380
- if (typeof window === 'undefined') return;
381
- window.__MANDU_DEV_TOOLS__ = true;
382
- })();
383
- </script>`;
378
+ function generateDevtoolsScript(): string {
379
+ return `<script type="module" src="/.mandu/client/_devtools.js"></script>`;
384
380
  }
385
381
 
386
382
  export function createHTMLResponse(html: string, status: number = 200): Response {
@@ -530,6 +530,11 @@ function generateHTMLTailContent(options: StreamingSSROptions): string {
530
530
  scripts.push(generateHMRScript(hmrPort));
531
531
  }
532
532
 
533
+ // 10. DevTools 번들 로드 (개발 모드)
534
+ if (isDev) {
535
+ scripts.push(`<script type="module" src="/.mandu/client/_devtools.js"></script>`);
536
+ }
537
+
533
538
  // Island wrapper 닫기 (hydration이 필요한 경우)
534
539
  const needsHydration = hydration && hydration.strategy !== "none" && routeId && bundleManifest;
535
540
  const islandCloseTag = needsHydration ? "</div>" : "";