@mandujs/core 0.9.4 → 0.9.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 +52 -52
- package/src/client/router.ts +57 -22
package/package.json
CHANGED
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@mandujs/core",
|
|
3
|
-
"version": "0.9.
|
|
4
|
-
"description": "Mandu Framework Core - Spec, Generator, Guard, Runtime",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "./src/index.ts",
|
|
7
|
-
"types": "./src/index.ts",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": "./src/index.ts",
|
|
10
|
-
"./client": "./src/client/index.ts",
|
|
11
|
-
"./*": "./src/*"
|
|
12
|
-
},
|
|
13
|
-
"files": [
|
|
14
|
-
"src/**/*"
|
|
15
|
-
],
|
|
16
|
-
"scripts": {
|
|
17
|
-
"test": "bun test",
|
|
18
|
-
"test:hydration": "bun test tests/hydration",
|
|
19
|
-
"test:watch": "bun test --watch"
|
|
20
|
-
},
|
|
21
|
-
"devDependencies": {
|
|
22
|
-
"@happy-dom/global-registrator": "^15.0.0"
|
|
23
|
-
},
|
|
24
|
-
"keywords": [
|
|
25
|
-
"mandu",
|
|
26
|
-
"framework",
|
|
27
|
-
"agent",
|
|
28
|
-
"ai",
|
|
29
|
-
"code-generation"
|
|
30
|
-
],
|
|
31
|
-
"repository": {
|
|
32
|
-
"type": "git",
|
|
33
|
-
"url": "git+https://github.com/konamgil/mandu.git",
|
|
34
|
-
"directory": "packages/core"
|
|
35
|
-
},
|
|
36
|
-
"author": "konamgil",
|
|
37
|
-
"license": "MIT",
|
|
38
|
-
"publishConfig": {
|
|
39
|
-
"access": "public"
|
|
40
|
-
},
|
|
41
|
-
"engines": {
|
|
42
|
-
"bun": ">=1.0.0"
|
|
43
|
-
},
|
|
44
|
-
"peerDependencies": {
|
|
45
|
-
"react": ">=18.0.0",
|
|
46
|
-
"react-dom": ">=18.0.0",
|
|
47
|
-
"zod": ">=3.0.0"
|
|
48
|
-
},
|
|
49
|
-
"dependencies": {
|
|
50
|
-
"ollama": "^0.6.3"
|
|
51
|
-
}
|
|
52
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@mandujs/core",
|
|
3
|
+
"version": "0.9.5",
|
|
4
|
+
"description": "Mandu Framework Core - Spec, Generator, Guard, Runtime",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./src/index.ts",
|
|
7
|
+
"types": "./src/index.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./src/index.ts",
|
|
10
|
+
"./client": "./src/client/index.ts",
|
|
11
|
+
"./*": "./src/*"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"src/**/*"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"test": "bun test",
|
|
18
|
+
"test:hydration": "bun test tests/hydration",
|
|
19
|
+
"test:watch": "bun test --watch"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@happy-dom/global-registrator": "^15.0.0"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"mandu",
|
|
26
|
+
"framework",
|
|
27
|
+
"agent",
|
|
28
|
+
"ai",
|
|
29
|
+
"code-generation"
|
|
30
|
+
],
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/konamgil/mandu.git",
|
|
34
|
+
"directory": "packages/core"
|
|
35
|
+
},
|
|
36
|
+
"author": "konamgil",
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"bun": ">=1.0.0"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"react": ">=18.0.0",
|
|
46
|
+
"react-dom": ">=18.0.0",
|
|
47
|
+
"zod": ">=3.0.0"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"ollama": "^0.6.3"
|
|
51
|
+
}
|
|
52
|
+
}
|
package/src/client/router.ts
CHANGED
|
@@ -33,15 +33,49 @@ export interface NavigateOptions {
|
|
|
33
33
|
|
|
34
34
|
type RouterListener = (state: RouterState) => void;
|
|
35
35
|
|
|
36
|
-
// ========== Router State ==========
|
|
36
|
+
// ========== Global Router State (모든 모듈에서 동일 인스턴스 공유) ==========
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
38
|
+
declare global {
|
|
39
|
+
interface Window {
|
|
40
|
+
__MANDU_ROUTER_STATE__?: RouterState;
|
|
41
|
+
__MANDU_ROUTER_LISTENERS__?: Set<RouterListener>;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
function getGlobalRouterState(): RouterState {
|
|
46
|
+
if (typeof window === "undefined") {
|
|
47
|
+
return { currentRoute: null, loaderData: undefined, navigation: { state: "idle" } };
|
|
48
|
+
}
|
|
49
|
+
if (!window.__MANDU_ROUTER_STATE__) {
|
|
50
|
+
window.__MANDU_ROUTER_STATE__ = {
|
|
51
|
+
currentRoute: null,
|
|
52
|
+
loaderData: undefined,
|
|
53
|
+
navigation: { state: "idle" },
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return window.__MANDU_ROUTER_STATE__;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function setGlobalRouterState(state: RouterState): void {
|
|
60
|
+
if (typeof window !== "undefined") {
|
|
61
|
+
window.__MANDU_ROUTER_STATE__ = state;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function getGlobalListeners(): Set<RouterListener> {
|
|
66
|
+
if (typeof window === "undefined") {
|
|
67
|
+
return new Set();
|
|
68
|
+
}
|
|
69
|
+
if (!window.__MANDU_ROUTER_LISTENERS__) {
|
|
70
|
+
window.__MANDU_ROUTER_LISTENERS__ = new Set();
|
|
71
|
+
}
|
|
72
|
+
return window.__MANDU_ROUTER_LISTENERS__;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Getter for routerState (전역 상태 참조)
|
|
76
|
+
const getRouterStateInternal = () => getGlobalRouterState();
|
|
77
|
+
const setRouterStateInternal = (state: RouterState) => setGlobalRouterState(state);
|
|
78
|
+
const listeners = { get current() { return getGlobalListeners(); } };
|
|
45
79
|
|
|
46
80
|
/**
|
|
47
81
|
* 초기화: 서버에서 전달된 라우트 정보로 상태 설정
|
|
@@ -56,7 +90,7 @@ function initializeFromServer(): void {
|
|
|
56
90
|
// URL에서 실제 params 추출
|
|
57
91
|
const params = extractParamsFromPath(route.pattern, window.location.pathname);
|
|
58
92
|
|
|
59
|
-
|
|
93
|
+
setRouterStateInternal({
|
|
60
94
|
currentRoute: {
|
|
61
95
|
id: route.id,
|
|
62
96
|
pattern: route.pattern,
|
|
@@ -64,7 +98,7 @@ function initializeFromServer(): void {
|
|
|
64
98
|
},
|
|
65
99
|
loaderData: data?.[route.id]?.serverData,
|
|
66
100
|
navigation: { state: "idle" },
|
|
67
|
-
};
|
|
101
|
+
});
|
|
68
102
|
}
|
|
69
103
|
}
|
|
70
104
|
|
|
@@ -157,10 +191,10 @@ export async function navigate(
|
|
|
157
191
|
}
|
|
158
192
|
|
|
159
193
|
// 로딩 상태 시작
|
|
160
|
-
|
|
161
|
-
...
|
|
194
|
+
setRouterStateInternal({
|
|
195
|
+
...getRouterStateInternal(),
|
|
162
196
|
navigation: { state: "loading", location: to },
|
|
163
|
-
};
|
|
197
|
+
});
|
|
164
198
|
notifyListeners();
|
|
165
199
|
|
|
166
200
|
// 데이터 fetch
|
|
@@ -184,7 +218,7 @@ export async function navigate(
|
|
|
184
218
|
}
|
|
185
219
|
|
|
186
220
|
// 상태 업데이트
|
|
187
|
-
|
|
221
|
+
setRouterStateInternal({
|
|
188
222
|
currentRoute: {
|
|
189
223
|
id: data.routeId,
|
|
190
224
|
pattern: data.pattern,
|
|
@@ -192,7 +226,7 @@ export async function navigate(
|
|
|
192
226
|
},
|
|
193
227
|
loaderData: data.loaderData,
|
|
194
228
|
navigation: { state: "idle" },
|
|
195
|
-
};
|
|
229
|
+
});
|
|
196
230
|
|
|
197
231
|
// __MANDU_DATA__ 업데이트
|
|
198
232
|
if (typeof window !== "undefined") {
|
|
@@ -236,9 +270,10 @@ function handlePopState(event: PopStateEvent): void {
|
|
|
236
270
|
* 리스너에게 상태 변경 알림
|
|
237
271
|
*/
|
|
238
272
|
function notifyListeners(): void {
|
|
239
|
-
|
|
273
|
+
const state = getRouterStateInternal();
|
|
274
|
+
for (const listener of listeners.current) {
|
|
240
275
|
try {
|
|
241
|
-
listener(
|
|
276
|
+
listener(state);
|
|
242
277
|
} catch (error) {
|
|
243
278
|
console.error("[Mandu Router] Listener error:", error);
|
|
244
279
|
}
|
|
@@ -249,36 +284,36 @@ function notifyListeners(): void {
|
|
|
249
284
|
* 상태 변경 구독
|
|
250
285
|
*/
|
|
251
286
|
export function subscribe(listener: RouterListener): () => void {
|
|
252
|
-
listeners.add(listener);
|
|
253
|
-
return () => listeners.delete(listener);
|
|
287
|
+
listeners.current.add(listener);
|
|
288
|
+
return () => listeners.current.delete(listener);
|
|
254
289
|
}
|
|
255
290
|
|
|
256
291
|
/**
|
|
257
292
|
* 현재 라우터 상태 가져오기
|
|
258
293
|
*/
|
|
259
294
|
export function getRouterState(): RouterState {
|
|
260
|
-
return
|
|
295
|
+
return getRouterStateInternal();
|
|
261
296
|
}
|
|
262
297
|
|
|
263
298
|
/**
|
|
264
299
|
* 현재 라우트 정보 가져오기
|
|
265
300
|
*/
|
|
266
301
|
export function getCurrentRoute(): RouteInfo | null {
|
|
267
|
-
return
|
|
302
|
+
return getRouterStateInternal().currentRoute;
|
|
268
303
|
}
|
|
269
304
|
|
|
270
305
|
/**
|
|
271
306
|
* 현재 loader 데이터 가져오기
|
|
272
307
|
*/
|
|
273
308
|
export function getLoaderData<T = unknown>(): T | undefined {
|
|
274
|
-
return
|
|
309
|
+
return getRouterStateInternal().loaderData as T | undefined;
|
|
275
310
|
}
|
|
276
311
|
|
|
277
312
|
/**
|
|
278
313
|
* 네비게이션 상태 가져오기
|
|
279
314
|
*/
|
|
280
315
|
export function getNavigationState(): NavigationState {
|
|
281
|
-
return
|
|
316
|
+
return getRouterStateInternal().navigation;
|
|
282
317
|
}
|
|
283
318
|
|
|
284
319
|
// ========== Link Click Handler ==========
|