@nine-lab/nine-mu 0.1.373 → 0.1.374

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": "@nine-lab/nine-mu",
3
- "version": "0.1.373",
3
+ "version": "0.1.374",
4
4
  "description": "AI-Driven Full-Stack Code Fabrication Engine",
5
5
  "type": "module",
6
6
  "main": "./dist/nine-mu.umd.js",
@@ -22,6 +22,52 @@ const ScreenProvider = ({ children }) => {
22
22
  );
23
23
  };
24
24
 
25
+ const createDynamicRoutes = (menuData, projectViews) => {
26
+ // 기본 404 및 홈 설정
27
+ const lazyLoad = (viewPath) => {
28
+ const importer = projectViews[viewPath];
29
+ // 404 파일은 라이브러리 내부에 두거나 주입받음
30
+ //if (!importer) return lazy(() => import('./Error404.jsx').catch(() => ({ default: () => React.createElement('div', null, '404 Not Found') })));
31
+ return lazy(() => importer());
32
+ };
33
+
34
+ const dynamicRoutes = [
35
+ { path: "/", Component: lazyLoad("./views/admin/Home.jsx") },
36
+ { path: "/admin", Component: lazyLoad("./views/admin/Home.jsx") },
37
+ ];
38
+
39
+ if (menuData && Array.isArray(menuData)) {
40
+ menuData.forEach((menu) => {
41
+ if (menu.level === 2 && menu.path) {
42
+ const cleanPath = menu.path.replace(/^\/+|\/+$/g, "");
43
+ const pathParts = cleanPath.split("/");
44
+ const len = pathParts.length;
45
+
46
+ let combinedName = "";
47
+ const startIdx = Math.max(0, len - 2);
48
+ for (let i = startIdx; i < len; i++) {
49
+ const words = pathParts[i].toLowerCase().split(/[-_]/).filter(Boolean);
50
+ combinedName += words.map(w => w.charAt(0).toUpperCase() + w.slice(1)).join("");
51
+ }
52
+ const pascalName = combinedName || "GeneratedComponent";
53
+ const sanitizedParts = pathParts.map(part => part.replace(/-/g, "_"));
54
+ const fullFolderPath = sanitizedParts.join("/");
55
+
56
+ // 사용자 프로젝트 루트 기준 상대 경로 매핑
57
+ const componentPath = `./views/${fullFolderPath}/${pascalName}.jsx`;
58
+
59
+ dynamicRoutes.push({
60
+ path: menu.path,
61
+ Component: lazyLoad(componentPath)
62
+ });
63
+ }
64
+ });
65
+ }
66
+
67
+ //dynamicRoutes.push({ path: "*", Component: lazyLoad("./frame/Error404.jsx") });
68
+ return dynamicRoutes;
69
+ };
70
+
25
71
  // ==========================================
26
72
  // 2. 내부 기능 B: 에러 바운더리 및 CSS 스타일
27
73
  // ==========================================
@@ -142,16 +188,32 @@ class NineExceptionHook extends React.Component {
142
188
  }
143
189
  }
144
190
 
145
- export function NineHook({ children, onCatch, fallback, styles, containerStyle }) {
146
- // 사용자는 무조건 이거 하나만 쓰면 끝!
147
- // 내부적으로 상태(ScreenProvider)를 먼저 주입하고, 그 안에서 에러(NineExceptionHook)가 자식들을 감싸안아 보호합니다.
191
+ export function NineHook({ menuData, views, onCatch, fallback, styles, containerStyle }) {
192
+ // 내부에서 자동으로 라우트 배열 생성
193
+ const dynamicRoutes = createDynamicRoutes(menuData, views);
194
+
148
195
  return React.createElement(
149
196
  ScreenProvider,
150
197
  null,
151
198
  React.createElement(
152
199
  NineExceptionHook,
153
200
  { onCatch, fallback, styles, containerStyle },
154
- children
201
+ // 💡 Suspense 로딩도 라이브러리가 책임지고 터미널 감성으로 처리
202
+ React.createElement(
203
+ Suspense,
204
+ { fallback: React.createElement('div', { style: { padding: '25px', color: '#666', fontFamily: 'monospace' } }, '>> Loading component matrix...') },
205
+ React.createElement(
206
+ Routes,
207
+ null,
208
+ dynamicRoutes.map((route) =>
209
+ React.createElement(Route, {
210
+ key: route.path,
211
+ path: route.path,
212
+ element: React.createElement(route.Component, { key: route.path })
213
+ })
214
+ )
215
+ )
216
+ )
155
217
  )
156
218
  );
157
219
  }