@mandujs/core 0.19.0 → 0.19.2
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/README.ko.md +0 -14
- package/package.json +4 -1
- package/src/brain/architecture/analyzer.ts +4 -4
- package/src/brain/doctor/analyzer.ts +18 -14
- package/src/bundler/build.test.ts +127 -0
- package/src/bundler/build.ts +291 -113
- package/src/bundler/css.ts +20 -5
- package/src/bundler/dev.ts +55 -2
- package/src/bundler/prerender.ts +195 -0
- package/src/change/snapshot.ts +4 -23
- package/src/change/types.ts +2 -3
- package/src/client/Form.tsx +105 -0
- package/src/client/__tests__/use-sse.test.ts +153 -0
- package/src/client/hooks.ts +105 -6
- package/src/client/index.ts +35 -6
- package/src/client/router.ts +670 -433
- package/src/client/rpc.ts +140 -0
- package/src/client/runtime.ts +24 -21
- package/src/client/use-fetch.ts +239 -0
- package/src/client/use-head.ts +197 -0
- package/src/client/use-sse.ts +378 -0
- package/src/components/Image.tsx +162 -0
- package/src/config/mandu.ts +5 -0
- package/src/config/validate.ts +34 -0
- package/src/content/index.ts +5 -1
- package/src/devtools/client/catchers/error-catcher.ts +17 -0
- package/src/devtools/client/catchers/network-proxy.ts +390 -367
- package/src/devtools/client/components/kitchen-root.tsx +479 -467
- package/src/devtools/client/components/panel/diff-viewer.tsx +219 -0
- package/src/devtools/client/components/panel/guard-panel.tsx +374 -244
- package/src/devtools/client/components/panel/index.ts +45 -32
- package/src/devtools/client/components/panel/panel-container.tsx +332 -312
- package/src/devtools/client/components/panel/preview-panel.tsx +188 -0
- package/src/devtools/client/state-manager.ts +535 -478
- package/src/devtools/design-tokens.ts +265 -264
- package/src/devtools/types.ts +345 -319
- package/src/filling/filling.ts +336 -14
- package/src/filling/index.ts +5 -1
- package/src/filling/session.ts +216 -0
- package/src/filling/ws.ts +78 -0
- package/src/generator/generate.ts +2 -2
- package/src/guard/auto-correct.ts +0 -29
- package/src/guard/check.ts +14 -31
- package/src/guard/presets/index.ts +296 -294
- package/src/guard/rules.ts +15 -19
- package/src/guard/validator.ts +834 -834
- package/src/index.ts +5 -1
- package/src/island/index.ts +373 -304
- package/src/kitchen/api/contract-api.ts +225 -0
- package/src/kitchen/api/diff-parser.ts +108 -0
- package/src/kitchen/api/file-api.ts +273 -0
- package/src/kitchen/api/guard-api.ts +83 -0
- package/src/kitchen/api/guard-decisions.ts +100 -0
- package/src/kitchen/api/routes-api.ts +50 -0
- package/src/kitchen/index.ts +21 -0
- package/src/kitchen/kitchen-handler.ts +256 -0
- package/src/kitchen/kitchen-ui.ts +1732 -0
- package/src/kitchen/stream/activity-sse.ts +145 -0
- package/src/kitchen/stream/file-tailer.ts +99 -0
- package/src/middleware/compress.ts +62 -0
- package/src/middleware/cors.ts +47 -0
- package/src/middleware/index.ts +10 -0
- package/src/middleware/jwt.ts +134 -0
- package/src/middleware/logger.ts +58 -0
- package/src/middleware/timeout.ts +55 -0
- package/src/paths.ts +0 -4
- package/src/plugins/hooks.ts +64 -0
- package/src/plugins/index.ts +3 -0
- package/src/plugins/types.ts +5 -0
- package/src/report/build.ts +0 -6
- package/src/resource/__tests__/backward-compat.test.ts +0 -1
- package/src/router/fs-patterns.ts +11 -1
- package/src/router/fs-routes.ts +78 -14
- package/src/router/fs-scanner.ts +2 -2
- package/src/router/fs-types.ts +2 -1
- package/src/runtime/adapter-bun.ts +62 -0
- package/src/runtime/adapter.ts +47 -0
- package/src/runtime/cache.ts +310 -0
- package/src/runtime/handler.ts +65 -0
- package/src/runtime/image-handler.ts +195 -0
- package/src/runtime/index.ts +12 -0
- package/src/runtime/middleware.ts +263 -0
- package/src/runtime/server.ts +662 -83
- package/src/runtime/ssr.ts +55 -29
- package/src/runtime/streaming-ssr.ts +106 -82
- package/src/spec/index.ts +0 -1
- package/src/spec/schema.ts +1 -0
- package/src/testing/index.ts +144 -0
- package/src/watcher/watcher.ts +27 -1
- package/src/spec/lock.ts +0 -56
package/src/client/hooks.ts
CHANGED
|
@@ -3,17 +3,20 @@
|
|
|
3
3
|
* React hooks for client-side routing
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import { useState, useEffect, useCallback, useSyncExternalStore } from "react";
|
|
6
|
+
import { useState, useEffect, useCallback, useMemo, useSyncExternalStore } from "react";
|
|
7
7
|
import {
|
|
8
8
|
subscribe,
|
|
9
9
|
getRouterState,
|
|
10
10
|
getCurrentRoute,
|
|
11
11
|
getLoaderData,
|
|
12
|
+
getActionData,
|
|
12
13
|
getNavigationState,
|
|
13
14
|
navigate,
|
|
15
|
+
submitAction,
|
|
14
16
|
type RouteInfo,
|
|
15
17
|
type NavigationState,
|
|
16
18
|
type NavigateOptions,
|
|
19
|
+
type ActionResult,
|
|
17
20
|
} from "./router";
|
|
18
21
|
|
|
19
22
|
/**
|
|
@@ -235,12 +238,18 @@ export function useRouter() {
|
|
|
235
238
|
export function useMatch(pattern: string): boolean {
|
|
236
239
|
const pathname = usePathname();
|
|
237
240
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
.replace(
|
|
241
|
+
const regex = useMemo(() => {
|
|
242
|
+
// 파라미터를 플레이스홀더로 치환 → 나머지 특수문자 이스케이프 → 플레이스홀더 복원
|
|
243
|
+
const PLACEHOLDER = "\x00PARAM\x00";
|
|
244
|
+
const withPlaceholders = pattern.replace(/:[a-zA-Z_][a-zA-Z0-9_]*/g, PLACEHOLDER);
|
|
245
|
+
const escaped = withPlaceholders.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
246
|
+
const regexStr = escaped.replace(
|
|
247
|
+
new RegExp(PLACEHOLDER.replace(/\x00/g, "\\x00"), "g"),
|
|
248
|
+
"[^/]+"
|
|
249
|
+
);
|
|
250
|
+
return new RegExp(`^${regexStr}$`);
|
|
251
|
+
}, [pattern]);
|
|
242
252
|
|
|
243
|
-
const regex = new RegExp(`^${regexStr}$`);
|
|
244
253
|
return regex.test(pathname);
|
|
245
254
|
}
|
|
246
255
|
|
|
@@ -265,3 +274,93 @@ export function useGoForward(): () => void {
|
|
|
265
274
|
}
|
|
266
275
|
}, []);
|
|
267
276
|
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Action 데이터 접근
|
|
280
|
+
* filling.action()의 결과 데이터
|
|
281
|
+
*
|
|
282
|
+
* @example
|
|
283
|
+
* ```tsx
|
|
284
|
+
* const actionData = useActionData<{ created: boolean }>();
|
|
285
|
+
* if (actionData?.created) { ... }
|
|
286
|
+
* ```
|
|
287
|
+
*/
|
|
288
|
+
export function useActionData<T = unknown>(): T | undefined {
|
|
289
|
+
const state = useRouterState();
|
|
290
|
+
return state.actionData as T | undefined;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Action 제출 함수
|
|
295
|
+
*
|
|
296
|
+
* @example
|
|
297
|
+
* ```tsx
|
|
298
|
+
* const submit = useSubmit();
|
|
299
|
+
* const handleCreate = () => submit("/api/todos", { title: "New" }, "create");
|
|
300
|
+
* ```
|
|
301
|
+
*/
|
|
302
|
+
export function useSubmit(): (
|
|
303
|
+
url: string,
|
|
304
|
+
data: FormData | Record<string, unknown>,
|
|
305
|
+
actionName?: string,
|
|
306
|
+
method?: string
|
|
307
|
+
) => Promise<ActionResult> {
|
|
308
|
+
return useCallback(
|
|
309
|
+
(url: string, data: FormData | Record<string, unknown>, actionName = "default", method = "POST") => {
|
|
310
|
+
return submitAction(url, data, actionName, method);
|
|
311
|
+
},
|
|
312
|
+
[]
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Mandu 통합 상태 훅
|
|
318
|
+
* 라우트, 데이터, 네비게이션, 액션 상태를 하나의 객체로 제공
|
|
319
|
+
*
|
|
320
|
+
* @example
|
|
321
|
+
* ```tsx
|
|
322
|
+
* const {
|
|
323
|
+
* url, params, routeId,
|
|
324
|
+
* loaderData, actionData,
|
|
325
|
+
* navigation,
|
|
326
|
+
* navigate, submit,
|
|
327
|
+
* } = useMandu();
|
|
328
|
+
* ```
|
|
329
|
+
*/
|
|
330
|
+
export function useMandu() {
|
|
331
|
+
const state = useRouterState();
|
|
332
|
+
const navigateFn = useNavigate();
|
|
333
|
+
const submitFn = useSubmit();
|
|
334
|
+
|
|
335
|
+
// URL은 라우터 상태가 실제로 바뀔 때만 재생성한다.
|
|
336
|
+
// query-only navigation도 반영되도록 상태 전체를 의존성으로 사용한다.
|
|
337
|
+
const url = useMemo(
|
|
338
|
+
() => typeof window !== "undefined" ? new URL(window.location.href) : null,
|
|
339
|
+
[state]
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
return {
|
|
343
|
+
/** 현재 URL (브라우저) */
|
|
344
|
+
url,
|
|
345
|
+
/** URL 파라미터 */
|
|
346
|
+
params: (state.currentRoute?.params ?? {}) as Record<string, string>,
|
|
347
|
+
/** 현재 라우트 ID */
|
|
348
|
+
routeId: state.currentRoute?.id ?? "",
|
|
349
|
+
/** 라우트 패턴 */
|
|
350
|
+
pattern: state.currentRoute?.pattern ?? "",
|
|
351
|
+
/** Loader 데이터 */
|
|
352
|
+
loaderData: state.loaderData,
|
|
353
|
+
/** 마지막 Action 결과 */
|
|
354
|
+
actionData: state.actionData,
|
|
355
|
+
/** 네비게이션 상태 */
|
|
356
|
+
navigation: state.navigation,
|
|
357
|
+
/** 네비게이션 중 여부 */
|
|
358
|
+
isNavigating: state.navigation.state === "loading",
|
|
359
|
+
/** Action 제출 중 여부 */
|
|
360
|
+
isSubmitting: state.navigation.state === "submitting",
|
|
361
|
+
/** 프로그래매틱 네비게이션 */
|
|
362
|
+
navigate: navigateFn,
|
|
363
|
+
/** Action 제출 */
|
|
364
|
+
submit: submitFn,
|
|
365
|
+
};
|
|
366
|
+
}
|
package/src/client/index.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Mandu Client Module
|
|
3
|
-
*
|
|
2
|
+
* Mandu Client Module
|
|
3
|
+
* Client-side hydration and routing API
|
|
4
4
|
*
|
|
5
5
|
* @example
|
|
6
6
|
* ```typescript
|
|
7
|
-
* // Island
|
|
7
|
+
* // Island component
|
|
8
8
|
* import { Mandu } from "@mandujs/core/client";
|
|
9
9
|
*
|
|
10
10
|
* export default Mandu.island<TodosData>({
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
*
|
|
16
16
|
* @example
|
|
17
17
|
* ```typescript
|
|
18
|
-
* // Client-side
|
|
18
|
+
* // Client-side routing
|
|
19
19
|
* import { Link, useRouter } from "@mandujs/core/client";
|
|
20
20
|
*
|
|
21
21
|
* function Nav() {
|
|
@@ -63,6 +63,15 @@ export {
|
|
|
63
63
|
type HydrationPriority,
|
|
64
64
|
} from "./runtime";
|
|
65
65
|
|
|
66
|
+
// SSE / ReadableStream API (microtask-starvation-safe)
|
|
67
|
+
export {
|
|
68
|
+
useSSE,
|
|
69
|
+
readStreamWithYield,
|
|
70
|
+
type UseSSEOptions,
|
|
71
|
+
type UseSSEReturn,
|
|
72
|
+
type ReadStreamOptions,
|
|
73
|
+
} from "./use-sse";
|
|
74
|
+
|
|
66
75
|
// Client-side Router API
|
|
67
76
|
export {
|
|
68
77
|
navigate,
|
|
@@ -71,18 +80,35 @@ export {
|
|
|
71
80
|
getRouterState,
|
|
72
81
|
getCurrentRoute,
|
|
73
82
|
getLoaderData,
|
|
83
|
+
getActionData,
|
|
74
84
|
getNavigationState,
|
|
75
85
|
initializeRouter,
|
|
76
86
|
cleanupRouter,
|
|
87
|
+
submitAction,
|
|
88
|
+
setShouldRevalidate,
|
|
77
89
|
type RouteInfo,
|
|
78
90
|
type NavigationState,
|
|
79
91
|
type RouterState,
|
|
80
92
|
type NavigateOptions,
|
|
93
|
+
type ActionResult,
|
|
94
|
+
type ShouldRevalidateFunction,
|
|
81
95
|
} from "./router";
|
|
82
96
|
|
|
83
97
|
// Link Components
|
|
84
98
|
export { Link, NavLink, type LinkProps, type NavLinkProps } from "./Link";
|
|
85
99
|
|
|
100
|
+
// Form Component (Progressive Enhancement)
|
|
101
|
+
export { Form, type FormProps, type FormState } from "./Form";
|
|
102
|
+
|
|
103
|
+
// RPC Client
|
|
104
|
+
export { createClient, RpcError, type RpcMethods, type RpcRequestOptions, type RpcClientOptions } from "./rpc";
|
|
105
|
+
|
|
106
|
+
// useFetch Composable
|
|
107
|
+
export { useFetch, type UseFetchOptions, type UseFetchReturn } from "./use-fetch";
|
|
108
|
+
|
|
109
|
+
// Head Management
|
|
110
|
+
export { useHead, useSeoMeta, resetSSRHead, getSSRHeadTags, type HeadConfig, type SeoMetaConfig } from "./use-head";
|
|
111
|
+
|
|
86
112
|
// Stable interaction components
|
|
87
113
|
export { ManduButton, ManduModalTrigger } from "./interaction";
|
|
88
114
|
|
|
@@ -100,9 +126,12 @@ export {
|
|
|
100
126
|
useGoBack,
|
|
101
127
|
useGoForward,
|
|
102
128
|
useRouterState,
|
|
129
|
+
useActionData,
|
|
130
|
+
useSubmit,
|
|
131
|
+
useMandu,
|
|
103
132
|
} from "./hooks";
|
|
104
133
|
|
|
105
|
-
// Props Serialization (Fresh
|
|
134
|
+
// Props Serialization (Fresh style)
|
|
106
135
|
export {
|
|
107
136
|
serializeProps,
|
|
108
137
|
deserializeProps,
|
|
@@ -118,7 +147,7 @@ import { Link, NavLink } from "./Link";
|
|
|
118
147
|
|
|
119
148
|
/**
|
|
120
149
|
* Mandu Client namespace
|
|
121
|
-
* v0.8.0: Hydration
|
|
150
|
+
* v0.8.0: Hydration is handled automatically (generateRuntimeSource)
|
|
122
151
|
* Note: Use `ManduClient` to avoid conflict with other Mandu exports
|
|
123
152
|
*/
|
|
124
153
|
export const ManduClient = {
|