@mandujs/core 0.18.2 → 0.18.5
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 +8 -2
- package/src/bundler/build.ts +39 -35
- package/src/bundler/css.ts +332 -302
- package/src/bundler/dev.ts +34 -3
- package/src/config/mandu.ts +1 -1
- package/src/config/validate.ts +1 -1
- package/src/contract/registry.ts +591 -568
- package/src/resource/generator.ts +5 -4
- package/src/runtime/escape.ts +12 -0
- package/src/runtime/server.ts +1 -1
- package/src/runtime/shims.ts +48 -0
- package/src/runtime/ssr.ts +29 -10
- package/src/runtime/streaming-ssr.ts +13 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mandujs/core",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.5",
|
|
4
4
|
"description": "Mandu Framework Core - Spec, Generator, Guard, Runtime",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -44,7 +44,13 @@
|
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"react": "^19.0.0",
|
|
47
|
-
"react-dom": "^19.0.0"
|
|
47
|
+
"react-dom": "^19.0.0",
|
|
48
|
+
"@tailwindcss/cli": ">=4.0.0"
|
|
49
|
+
},
|
|
50
|
+
"peerDependenciesMeta": {
|
|
51
|
+
"@tailwindcss/cli": {
|
|
52
|
+
"optional": true
|
|
53
|
+
}
|
|
48
54
|
},
|
|
49
55
|
"dependencies": {
|
|
50
56
|
"chokidar": "^5.0.0",
|
package/src/bundler/build.ts
CHANGED
|
@@ -205,11 +205,11 @@ async function loadAndHydrate(element, src) {
|
|
|
205
205
|
// Dynamic import - 이 시점에 Island 모듈 로드
|
|
206
206
|
const module = await import(src);
|
|
207
207
|
const island = module.default;
|
|
208
|
+
const data = getServerData(id);
|
|
208
209
|
|
|
209
210
|
// Mandu Island (preferred)
|
|
210
211
|
if (island && island.__mandu_island === true) {
|
|
211
212
|
const { definition } = island;
|
|
212
|
-
const data = getServerData(id);
|
|
213
213
|
|
|
214
214
|
// Island 컴포넌트 (Error Boundary + Loading 지원)
|
|
215
215
|
function IslandComponent() {
|
|
@@ -258,11 +258,14 @@ async function loadAndHydrate(element, src) {
|
|
|
258
258
|
|
|
259
259
|
console.log('[Mandu] Hydrated:', id);
|
|
260
260
|
}
|
|
261
|
-
// Plain React component fallback
|
|
261
|
+
// Plain React component fallback (e.g. "use client" pages)
|
|
262
262
|
else if (typeof island === 'function' || React.isValidElement(island)) {
|
|
263
263
|
console.warn('[Mandu] Plain component hydration:', id);
|
|
264
|
-
|
|
265
|
-
const root =
|
|
264
|
+
|
|
265
|
+
const root = typeof island === 'function'
|
|
266
|
+
? hydrateRoot(element, React.createElement(island, data))
|
|
267
|
+
: hydrateRoot(element, island);
|
|
268
|
+
|
|
266
269
|
hydratedRoots.set(id, root);
|
|
267
270
|
|
|
268
271
|
// 완료 표시
|
|
@@ -390,6 +393,8 @@ import React, {
|
|
|
390
393
|
Suspense,
|
|
391
394
|
StrictMode,
|
|
392
395
|
Profiler,
|
|
396
|
+
// Misc
|
|
397
|
+
version,
|
|
393
398
|
// Types
|
|
394
399
|
Component,
|
|
395
400
|
PureComponent,
|
|
@@ -401,15 +406,16 @@ import { jsx, jsxs } from 'react/jsx-runtime';
|
|
|
401
406
|
import { jsxDEV } from 'react/jsx-dev-runtime';
|
|
402
407
|
|
|
403
408
|
// React internals (ReactDOM이 내부적으로 접근 필요)
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
// React 19 client internals (Playwright headless 환경 호환성)
|
|
409
|
+
// React 19+: __CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE
|
|
410
|
+
// React <=18: __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
|
|
407
411
|
const __CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE =
|
|
408
412
|
React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE || {};
|
|
413
|
+
const __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED =
|
|
414
|
+
React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED || {};
|
|
409
415
|
|
|
410
|
-
// Null safety for Playwright headless browsers
|
|
416
|
+
// Null safety for Playwright headless browsers (React 19)
|
|
411
417
|
if (__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.S == null) {
|
|
412
|
-
__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.S = function() {};
|
|
418
|
+
__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE.S = function () {};
|
|
413
419
|
}
|
|
414
420
|
|
|
415
421
|
// 전역 React 설정 (모든 모듈에서 동일 인스턴스 공유)
|
|
@@ -447,20 +453,18 @@ export {
|
|
|
447
453
|
Suspense,
|
|
448
454
|
StrictMode,
|
|
449
455
|
Profiler,
|
|
456
|
+
version,
|
|
450
457
|
Component,
|
|
451
458
|
PureComponent,
|
|
452
459
|
Children,
|
|
453
|
-
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
|
|
454
460
|
__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,
|
|
461
|
+
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
|
|
455
462
|
// JSX Runtime exports
|
|
456
463
|
jsx,
|
|
457
464
|
jsxs,
|
|
458
465
|
jsxDEV,
|
|
459
466
|
};
|
|
460
467
|
|
|
461
|
-
// Version export (React 19 compatibility)
|
|
462
|
-
export const version = React.version;
|
|
463
|
-
|
|
464
468
|
// Default export
|
|
465
469
|
export default React;
|
|
466
470
|
`;
|
|
@@ -478,10 +482,6 @@ function generateReactDOMShimSource(): string {
|
|
|
478
482
|
import ReactDOM, {
|
|
479
483
|
createPortal,
|
|
480
484
|
flushSync,
|
|
481
|
-
render,
|
|
482
|
-
unmountComponentAtNode,
|
|
483
|
-
findDOMNode,
|
|
484
|
-
hydrate,
|
|
485
485
|
version,
|
|
486
486
|
} from 'react-dom';
|
|
487
487
|
|
|
@@ -489,10 +489,6 @@ import ReactDOM, {
|
|
|
489
489
|
export {
|
|
490
490
|
createPortal,
|
|
491
491
|
flushSync,
|
|
492
|
-
render,
|
|
493
|
-
unmountComponentAtNode,
|
|
494
|
-
findDOMNode,
|
|
495
|
-
hydrate,
|
|
496
492
|
version,
|
|
497
493
|
};
|
|
498
494
|
|
|
@@ -849,10 +845,8 @@ async function buildRuntime(
|
|
|
849
845
|
},
|
|
850
846
|
});
|
|
851
847
|
|
|
852
|
-
// 소스 파일 정리
|
|
853
|
-
await fs.unlink(runtimePath).catch(() => {});
|
|
854
|
-
|
|
855
848
|
if (!result.success) {
|
|
849
|
+
// 실패 시 디버깅을 위해 소스 파일을 남겨둠 (_runtime.src.js)
|
|
856
850
|
return {
|
|
857
851
|
success: false,
|
|
858
852
|
outputPath: "",
|
|
@@ -860,17 +854,28 @@ async function buildRuntime(
|
|
|
860
854
|
};
|
|
861
855
|
}
|
|
862
856
|
|
|
857
|
+
// 성공 시에만 소스 파일 정리
|
|
858
|
+
await fs.unlink(runtimePath).catch(() => {});
|
|
859
|
+
|
|
863
860
|
return {
|
|
864
861
|
success: true,
|
|
865
862
|
outputPath: `/.mandu/client/${outputName}`,
|
|
866
863
|
errors: [],
|
|
867
864
|
};
|
|
868
|
-
} catch (error) {
|
|
869
|
-
|
|
865
|
+
} catch (error: any) {
|
|
866
|
+
// 예외 발생 시에도 디버깅을 위해 소스 파일을 남겨둠
|
|
867
|
+
const extra: string[] = [];
|
|
868
|
+
if (error?.errors && Array.isArray(error.errors)) {
|
|
869
|
+
extra.push(...error.errors.map((e: any) => String(e?.message || e)));
|
|
870
|
+
}
|
|
871
|
+
if (error?.logs && Array.isArray(error.logs)) {
|
|
872
|
+
extra.push(...error.logs.map((l: any) => String(l?.message || l)));
|
|
873
|
+
}
|
|
874
|
+
|
|
870
875
|
return {
|
|
871
876
|
success: false,
|
|
872
877
|
outputPath: "",
|
|
873
|
-
errors: [String(error)],
|
|
878
|
+
errors: [String(error), ...extra].filter(Boolean),
|
|
874
879
|
};
|
|
875
880
|
}
|
|
876
881
|
}
|
|
@@ -1200,20 +1205,19 @@ export async function buildClientBundles(
|
|
|
1200
1205
|
};
|
|
1201
1206
|
}
|
|
1202
1207
|
|
|
1203
|
-
// 3. Runtime 번들 빌드
|
|
1204
|
-
const runtimeResult = await
|
|
1208
|
+
// 3-4. Runtime, Router, Vendor 번들 병렬 빌드 (서로 독립적)
|
|
1209
|
+
const [runtimeResult, routerResult, vendorResult] = await Promise.all([
|
|
1210
|
+
buildRuntime(outDir, options),
|
|
1211
|
+
buildRouterRuntime(outDir, options),
|
|
1212
|
+
buildVendorShims(outDir, options),
|
|
1213
|
+
]);
|
|
1214
|
+
|
|
1205
1215
|
if (!runtimeResult.success) {
|
|
1206
1216
|
errors.push(...runtimeResult.errors.map((e) => `[Runtime] ${e}`));
|
|
1207
1217
|
}
|
|
1208
|
-
|
|
1209
|
-
// 3.5. Client-side Router 런타임 빌드
|
|
1210
|
-
const routerResult = await buildRouterRuntime(outDir, options);
|
|
1211
1218
|
if (!routerResult.success) {
|
|
1212
1219
|
errors.push(...routerResult.errors.map((e) => `[Router] ${e}`));
|
|
1213
1220
|
}
|
|
1214
|
-
|
|
1215
|
-
// 4. Vendor shim 번들 빌드 (React, ReactDOM, ReactDOMClient)
|
|
1216
|
-
const vendorResult = await buildVendorShims(outDir, options);
|
|
1217
1221
|
if (!vendorResult.success) {
|
|
1218
1222
|
errors.push(...vendorResult.errors);
|
|
1219
1223
|
}
|