@mandujs/core 0.12.2 → 0.13.0

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.
Files changed (173) hide show
  1. package/README.ko.md +304 -304
  2. package/README.md +653 -653
  3. package/package.json +1 -1
  4. package/src/brain/architecture/analyzer.ts +28 -26
  5. package/src/brain/doctor/analyzer.ts +1 -1
  6. package/src/bundler/build.ts +91 -91
  7. package/src/bundler/css.ts +302 -302
  8. package/src/bundler/dev.ts +0 -1
  9. package/src/change/history.ts +3 -3
  10. package/src/change/snapshot.ts +10 -9
  11. package/src/change/transaction.ts +2 -2
  12. package/src/client/Link.tsx +227 -227
  13. package/src/client/globals.ts +44 -44
  14. package/src/client/hooks.ts +267 -267
  15. package/src/client/index.ts +5 -5
  16. package/src/client/island.ts +8 -8
  17. package/src/client/router.ts +435 -435
  18. package/src/client/runtime.ts +23 -23
  19. package/src/client/serialize.ts +404 -404
  20. package/src/client/window-state.ts +101 -101
  21. package/src/config/mandu.ts +94 -96
  22. package/src/config/validate.ts +213 -215
  23. package/src/config/watcher.ts +311 -311
  24. package/src/constants.ts +40 -40
  25. package/src/content/content-layer.ts +314 -314
  26. package/src/content/content.test.ts +433 -433
  27. package/src/content/data-store.ts +245 -245
  28. package/src/content/digest.ts +133 -133
  29. package/src/content/index.ts +164 -164
  30. package/src/content/loader-context.ts +172 -172
  31. package/src/content/loaders/api.ts +216 -216
  32. package/src/content/loaders/file.ts +169 -169
  33. package/src/content/loaders/glob.ts +252 -252
  34. package/src/content/loaders/index.ts +34 -34
  35. package/src/content/loaders/types.ts +137 -137
  36. package/src/content/meta-store.ts +209 -209
  37. package/src/content/types.ts +282 -282
  38. package/src/content/watcher.ts +135 -135
  39. package/src/contract/client-safe.test.ts +42 -42
  40. package/src/contract/client-safe.ts +114 -114
  41. package/src/contract/client.ts +16 -16
  42. package/src/contract/define.ts +459 -459
  43. package/src/contract/handler.ts +10 -10
  44. package/src/contract/normalize.test.ts +276 -276
  45. package/src/contract/normalize.ts +404 -404
  46. package/src/contract/registry.test.ts +206 -206
  47. package/src/contract/registry.ts +568 -568
  48. package/src/contract/schema.ts +48 -48
  49. package/src/contract/types.ts +58 -58
  50. package/src/contract/validator.ts +32 -32
  51. package/src/devtools/ai/context-builder.ts +375 -375
  52. package/src/devtools/ai/index.ts +25 -25
  53. package/src/devtools/ai/mcp-connector.ts +465 -465
  54. package/src/devtools/client/catchers/error-catcher.ts +327 -327
  55. package/src/devtools/client/catchers/index.ts +18 -18
  56. package/src/devtools/client/catchers/network-proxy.ts +363 -363
  57. package/src/devtools/client/components/index.ts +39 -39
  58. package/src/devtools/client/components/kitchen-root.tsx +362 -362
  59. package/src/devtools/client/components/mandu-character.tsx +241 -241
  60. package/src/devtools/client/components/overlay.tsx +368 -368
  61. package/src/devtools/client/components/panel/errors-panel.tsx +259 -259
  62. package/src/devtools/client/components/panel/guard-panel.tsx +244 -244
  63. package/src/devtools/client/components/panel/index.ts +32 -32
  64. package/src/devtools/client/components/panel/islands-panel.tsx +304 -304
  65. package/src/devtools/client/components/panel/network-panel.tsx +292 -292
  66. package/src/devtools/client/components/panel/panel-container.tsx +259 -259
  67. package/src/devtools/client/filters/context-filters.ts +282 -282
  68. package/src/devtools/client/filters/index.ts +16 -16
  69. package/src/devtools/client/index.ts +63 -63
  70. package/src/devtools/client/persistence.ts +335 -335
  71. package/src/devtools/client/state-manager.ts +478 -478
  72. package/src/devtools/design-tokens.ts +263 -263
  73. package/src/devtools/hook/create-hook.ts +207 -207
  74. package/src/devtools/hook/index.ts +13 -13
  75. package/src/devtools/index.ts +439 -439
  76. package/src/devtools/init.ts +266 -266
  77. package/src/devtools/protocol.ts +237 -237
  78. package/src/devtools/server/index.ts +17 -17
  79. package/src/devtools/server/source-context.ts +444 -444
  80. package/src/devtools/types.ts +319 -319
  81. package/src/devtools/worker/index.ts +25 -25
  82. package/src/devtools/worker/redaction-worker.ts +222 -222
  83. package/src/devtools/worker/worker-manager.ts +409 -409
  84. package/src/error/classifier.ts +2 -2
  85. package/src/error/domains.ts +265 -265
  86. package/src/error/formatter.ts +32 -32
  87. package/src/error/result.ts +46 -46
  88. package/src/error/stack-analyzer.ts +5 -0
  89. package/src/error/types.ts +6 -6
  90. package/src/errors/extractor.ts +409 -409
  91. package/src/errors/index.ts +19 -19
  92. package/src/filling/auth.ts +308 -308
  93. package/src/filling/context.ts +569 -569
  94. package/src/filling/deps.ts +238 -238
  95. package/src/generator/contract-glue.ts +2 -1
  96. package/src/generator/generate.ts +12 -10
  97. package/src/generator/index.ts +3 -3
  98. package/src/generator/templates.ts +80 -79
  99. package/src/guard/analyzer.ts +360 -360
  100. package/src/guard/ast-analyzer.ts +806 -806
  101. package/src/guard/auto-correct.ts +1 -1
  102. package/src/guard/check.ts +128 -128
  103. package/src/guard/contract-guard.ts +9 -9
  104. package/src/guard/file-type.test.ts +24 -24
  105. package/src/guard/presets/atomic.ts +70 -70
  106. package/src/guard/presets/clean.ts +77 -77
  107. package/src/guard/presets/cqrs.test.ts +35 -14
  108. package/src/guard/presets/fsd.ts +79 -79
  109. package/src/guard/presets/hexagonal.ts +68 -68
  110. package/src/guard/presets/index.ts +291 -291
  111. package/src/guard/reporter.ts +445 -445
  112. package/src/guard/rules.ts +12 -12
  113. package/src/guard/statistics.ts +578 -578
  114. package/src/guard/suggestions.ts +358 -358
  115. package/src/guard/types.ts +348 -348
  116. package/src/guard/validator.ts +834 -834
  117. package/src/guard/watcher.ts +404 -404
  118. package/src/index.ts +1 -0
  119. package/src/intent/index.ts +310 -310
  120. package/src/island/index.ts +304 -304
  121. package/src/logging/index.ts +22 -22
  122. package/src/logging/transports.ts +365 -365
  123. package/src/paths.test.ts +47 -0
  124. package/src/paths.ts +47 -0
  125. package/src/plugins/index.ts +38 -38
  126. package/src/plugins/registry.ts +377 -377
  127. package/src/plugins/types.ts +363 -363
  128. package/src/report/build.ts +1 -1
  129. package/src/report/index.ts +1 -1
  130. package/src/router/fs-patterns.ts +387 -387
  131. package/src/router/fs-routes.ts +344 -401
  132. package/src/router/fs-scanner.ts +497 -497
  133. package/src/router/fs-types.ts +270 -278
  134. package/src/router/index.ts +81 -81
  135. package/src/runtime/boundary.tsx +232 -232
  136. package/src/runtime/compose.ts +222 -222
  137. package/src/runtime/lifecycle.ts +381 -381
  138. package/src/runtime/logger.test.ts +345 -345
  139. package/src/runtime/logger.ts +677 -677
  140. package/src/runtime/router.test.ts +476 -476
  141. package/src/runtime/router.ts +105 -105
  142. package/src/runtime/security.ts +155 -155
  143. package/src/runtime/server.ts +24 -24
  144. package/src/runtime/session-key.ts +328 -328
  145. package/src/runtime/ssr.ts +367 -367
  146. package/src/runtime/streaming-ssr.ts +1245 -1245
  147. package/src/runtime/trace.ts +144 -144
  148. package/src/seo/index.ts +214 -214
  149. package/src/seo/integration/ssr.ts +307 -307
  150. package/src/seo/render/basic.ts +427 -427
  151. package/src/seo/render/index.ts +143 -143
  152. package/src/seo/render/jsonld.ts +539 -539
  153. package/src/seo/render/opengraph.ts +191 -191
  154. package/src/seo/render/robots.ts +116 -116
  155. package/src/seo/render/sitemap.ts +137 -137
  156. package/src/seo/render/twitter.ts +126 -126
  157. package/src/seo/resolve/index.ts +353 -353
  158. package/src/seo/resolve/opengraph.ts +143 -143
  159. package/src/seo/resolve/robots.ts +73 -73
  160. package/src/seo/resolve/title.ts +94 -94
  161. package/src/seo/resolve/twitter.ts +73 -73
  162. package/src/seo/resolve/url.ts +97 -97
  163. package/src/seo/routes/index.ts +290 -290
  164. package/src/seo/types.ts +575 -575
  165. package/src/slot/validator.ts +39 -39
  166. package/src/spec/index.ts +3 -3
  167. package/src/spec/load.ts +76 -76
  168. package/src/spec/lock.ts +56 -56
  169. package/src/utils/bun.ts +8 -8
  170. package/src/utils/lru-cache.ts +75 -75
  171. package/src/utils/safe-io.ts +188 -188
  172. package/src/utils/string-safe.ts +298 -298
  173. package/src/watcher/rules.ts +5 -5
@@ -1,238 +1,238 @@
1
- /**
2
- * DNA-002: Dependency Injection Pattern
3
- *
4
- * Filling 핸들러의 의존성을 명시적으로 주입
5
- * - 테스트 시 목킹 용이
6
- * - 의존성 역전 원칙 (DIP) 준수
7
- * - 외부 서비스와의 결합도 감소
8
- */
9
-
10
- /**
11
- * 데이터베이스 의존성 인터페이스
12
- */
13
- export interface DbDeps {
14
- /**
15
- * SQL 쿼리 실행
16
- */
17
- query: <T>(sql: string, params?: unknown[]) => Promise<T>;
18
-
19
- /**
20
- * 트랜잭션 실행
21
- */
22
- transaction: <T>(fn: () => Promise<T>) => Promise<T>;
23
- }
24
-
25
- /**
26
- * 캐시 의존성 인터페이스
27
- */
28
- export interface CacheDeps {
29
- /**
30
- * 캐시에서 값 조회
31
- */
32
- get: <T>(key: string) => Promise<T | null>;
33
-
34
- /**
35
- * 캐시에 값 저장
36
- * @param ttl - Time to live (초 단위)
37
- */
38
- set: <T>(key: string, value: T, ttl?: number) => Promise<void>;
39
-
40
- /**
41
- * 캐시에서 값 삭제
42
- */
43
- delete: (key: string) => Promise<void>;
44
-
45
- /**
46
- * 패턴에 맞는 키 삭제
47
- */
48
- deletePattern?: (pattern: string) => Promise<void>;
49
- }
50
-
51
- /**
52
- * 로거 의존성 인터페이스
53
- */
54
- export interface LoggerDeps {
55
- debug: (msg: string, data?: unknown) => void;
56
- info: (msg: string, data?: unknown) => void;
57
- warn: (msg: string, data?: unknown) => void;
58
- error: (msg: string, data?: unknown) => void;
59
- }
60
-
61
- /**
62
- * 이벤트 버스 의존성 인터페이스
63
- */
64
- export interface EventBusDeps {
65
- /**
66
- * 이벤트 발행
67
- */
68
- emit: (event: string, payload: unknown) => void;
69
-
70
- /**
71
- * 이벤트 구독
72
- */
73
- on: (event: string, handler: (payload: unknown) => void) => () => void;
74
- }
75
-
76
- /**
77
- * Filling 핸들러 의존성 타입
78
- *
79
- * 모든 필드는 선택적 → 필요한 것만 주입
80
- */
81
- export interface FillingDeps {
82
- /**
83
- * 데이터베이스 접근
84
- */
85
- db?: DbDeps;
86
-
87
- /**
88
- * 캐시 접근
89
- */
90
- cache?: CacheDeps;
91
-
92
- /**
93
- * HTTP 클라이언트
94
- */
95
- fetch?: typeof fetch;
96
-
97
- /**
98
- * 로거
99
- */
100
- logger?: LoggerDeps;
101
-
102
- /**
103
- * 이벤트 버스
104
- */
105
- events?: EventBusDeps;
106
-
107
- /**
108
- * 현재 시간 (테스트용)
109
- */
110
- now?: () => Date;
111
-
112
- /**
113
- * UUID 생성 (테스트용)
114
- */
115
- uuid?: () => string;
116
-
117
- /**
118
- * 커스텀 의존성
119
- */
120
- [key: string]: unknown;
121
- }
122
-
123
- /**
124
- * 기본 의존성 생성
125
- *
126
- * @example
127
- * ```ts
128
- * const deps = createDefaultDeps();
129
- * console.log(deps.now()); // 현재 시간
130
- * ```
131
- */
132
- export function createDefaultDeps(): FillingDeps {
133
- return {
134
- fetch: globalThis.fetch,
135
- logger: {
136
- debug: (msg, data) => console.debug(`[DEBUG] ${msg}`, data ?? ""),
137
- info: (msg, data) => console.info(`[INFO] ${msg}`, data ?? ""),
138
- warn: (msg, data) => console.warn(`[WARN] ${msg}`, data ?? ""),
139
- error: (msg, data) => console.error(`[ERROR] ${msg}`, data ?? ""),
140
- },
141
- now: () => new Date(),
142
- uuid: () => crypto.randomUUID(),
143
- };
144
- }
145
-
146
- /**
147
- * 테스트용 목 의존성 생성 헬퍼
148
- *
149
- * @example
150
- * ```ts
151
- * const mockDeps = createMockDeps({
152
- * db: {
153
- * query: vi.fn().mockResolvedValue([{ id: 1, name: "Test" }]),
154
- * transaction: vi.fn(fn => fn()),
155
- * },
156
- * now: () => new Date("2025-01-01"),
157
- * });
158
- * ```
159
- */
160
- export function createMockDeps(overrides: Partial<FillingDeps> = {}): FillingDeps {
161
- const noop = () => {};
162
- const asyncNoop = async () => {};
163
-
164
- return {
165
- db: {
166
- query: async () => [] as any,
167
- transaction: async (fn) => fn(),
168
- },
169
- cache: {
170
- get: async () => null,
171
- set: asyncNoop,
172
- delete: asyncNoop,
173
- },
174
- fetch: async () => new Response(),
175
- logger: {
176
- debug: noop,
177
- info: noop,
178
- warn: noop,
179
- error: noop,
180
- },
181
- events: {
182
- emit: noop,
183
- on: () => noop,
184
- },
185
- now: () => new Date("2025-01-01T00:00:00Z"),
186
- uuid: () => "00000000-0000-0000-0000-000000000000",
187
- ...overrides,
188
- };
189
- }
190
-
191
- /**
192
- * 의존성 병합 (기본값 + 커스텀)
193
- */
194
- export function mergeDeps(
195
- base: FillingDeps,
196
- overrides: Partial<FillingDeps>
197
- ): FillingDeps {
198
- return { ...base, ...overrides };
199
- }
200
-
201
- /**
202
- * 의존성 컨테이너 (싱글톤 관리)
203
- */
204
- class DepsContainer {
205
- private deps: FillingDeps = createDefaultDeps();
206
-
207
- /**
208
- * 전역 의존성 설정
209
- */
210
- set(deps: Partial<FillingDeps>): void {
211
- this.deps = mergeDeps(this.deps, deps);
212
- }
213
-
214
- /**
215
- * 전역 의존성 가져오기
216
- */
217
- get(): FillingDeps {
218
- return this.deps;
219
- }
220
-
221
- /**
222
- * 기본값으로 리셋
223
- */
224
- reset(): void {
225
- this.deps = createDefaultDeps();
226
- }
227
- }
228
-
229
- /**
230
- * 전역 의존성 컨테이너
231
- */
232
- export const globalDeps = new DepsContainer();
233
-
234
- /**
235
- * 의존성 주입 데코레이터 타입
236
- * (향후 클래스 기반 핸들러 지원 시)
237
- */
238
- export type InjectDeps<T extends keyof FillingDeps> = Pick<FillingDeps, T>;
1
+ /**
2
+ * DNA-002: Dependency Injection Pattern
3
+ *
4
+ * Filling 핸들러의 의존성을 명시적으로 주입
5
+ * - 테스트 시 목킹 용이
6
+ * - 의존성 역전 원칙 (DIP) 준수
7
+ * - 외부 서비스와의 결합도 감소
8
+ */
9
+
10
+ /**
11
+ * 데이터베이스 의존성 인터페이스
12
+ */
13
+ export interface DbDeps {
14
+ /**
15
+ * SQL 쿼리 실행
16
+ */
17
+ query: <T>(sql: string, params?: unknown[]) => Promise<T>;
18
+
19
+ /**
20
+ * 트랜잭션 실행
21
+ */
22
+ transaction: <T>(fn: () => Promise<T>) => Promise<T>;
23
+ }
24
+
25
+ /**
26
+ * 캐시 의존성 인터페이스
27
+ */
28
+ export interface CacheDeps {
29
+ /**
30
+ * 캐시에서 값 조회
31
+ */
32
+ get: <T>(key: string) => Promise<T | null>;
33
+
34
+ /**
35
+ * 캐시에 값 저장
36
+ * @param ttl - Time to live (초 단위)
37
+ */
38
+ set: <T>(key: string, value: T, ttl?: number) => Promise<void>;
39
+
40
+ /**
41
+ * 캐시에서 값 삭제
42
+ */
43
+ delete: (key: string) => Promise<void>;
44
+
45
+ /**
46
+ * 패턴에 맞는 키 삭제
47
+ */
48
+ deletePattern?: (pattern: string) => Promise<void>;
49
+ }
50
+
51
+ /**
52
+ * 로거 의존성 인터페이스
53
+ */
54
+ export interface LoggerDeps {
55
+ debug: (msg: string, data?: unknown) => void;
56
+ info: (msg: string, data?: unknown) => void;
57
+ warn: (msg: string, data?: unknown) => void;
58
+ error: (msg: string, data?: unknown) => void;
59
+ }
60
+
61
+ /**
62
+ * 이벤트 버스 의존성 인터페이스
63
+ */
64
+ export interface EventBusDeps {
65
+ /**
66
+ * 이벤트 발행
67
+ */
68
+ emit: (event: string, payload: unknown) => void;
69
+
70
+ /**
71
+ * 이벤트 구독
72
+ */
73
+ on: (event: string, handler: (payload: unknown) => void) => () => void;
74
+ }
75
+
76
+ /**
77
+ * Filling 핸들러 의존성 타입
78
+ *
79
+ * 모든 필드는 선택적 → 필요한 것만 주입
80
+ */
81
+ export interface FillingDeps {
82
+ /**
83
+ * 데이터베이스 접근
84
+ */
85
+ db?: DbDeps;
86
+
87
+ /**
88
+ * 캐시 접근
89
+ */
90
+ cache?: CacheDeps;
91
+
92
+ /**
93
+ * HTTP 클라이언트
94
+ */
95
+ fetch?: typeof fetch;
96
+
97
+ /**
98
+ * 로거
99
+ */
100
+ logger?: LoggerDeps;
101
+
102
+ /**
103
+ * 이벤트 버스
104
+ */
105
+ events?: EventBusDeps;
106
+
107
+ /**
108
+ * 현재 시간 (테스트용)
109
+ */
110
+ now?: () => Date;
111
+
112
+ /**
113
+ * UUID 생성 (테스트용)
114
+ */
115
+ uuid?: () => string;
116
+
117
+ /**
118
+ * 커스텀 의존성
119
+ */
120
+ [key: string]: unknown;
121
+ }
122
+
123
+ /**
124
+ * 기본 의존성 생성
125
+ *
126
+ * @example
127
+ * ```ts
128
+ * const deps = createDefaultDeps();
129
+ * console.log(deps.now()); // 현재 시간
130
+ * ```
131
+ */
132
+ export function createDefaultDeps(): FillingDeps {
133
+ return {
134
+ fetch: globalThis.fetch,
135
+ logger: {
136
+ debug: (msg, data) => console.debug(`[DEBUG] ${msg}`, data ?? ""),
137
+ info: (msg, data) => console.info(`[INFO] ${msg}`, data ?? ""),
138
+ warn: (msg, data) => console.warn(`[WARN] ${msg}`, data ?? ""),
139
+ error: (msg, data) => console.error(`[ERROR] ${msg}`, data ?? ""),
140
+ },
141
+ now: () => new Date(),
142
+ uuid: () => crypto.randomUUID(),
143
+ };
144
+ }
145
+
146
+ /**
147
+ * 테스트용 목 의존성 생성 헬퍼
148
+ *
149
+ * @example
150
+ * ```ts
151
+ * const mockDeps = createMockDeps({
152
+ * db: {
153
+ * query: vi.fn().mockResolvedValue([{ id: 1, name: "Test" }]),
154
+ * transaction: vi.fn(fn => fn()),
155
+ * },
156
+ * now: () => new Date("2025-01-01"),
157
+ * });
158
+ * ```
159
+ */
160
+ export function createMockDeps(overrides: Partial<FillingDeps> = {}): FillingDeps {
161
+ const noop = () => {};
162
+ const asyncNoop = async () => {};
163
+
164
+ return {
165
+ db: {
166
+ query: async () => [] as any,
167
+ transaction: async (fn) => fn(),
168
+ },
169
+ cache: {
170
+ get: async () => null,
171
+ set: asyncNoop,
172
+ delete: asyncNoop,
173
+ },
174
+ fetch: async () => new Response(),
175
+ logger: {
176
+ debug: noop,
177
+ info: noop,
178
+ warn: noop,
179
+ error: noop,
180
+ },
181
+ events: {
182
+ emit: noop,
183
+ on: () => noop,
184
+ },
185
+ now: () => new Date("2025-01-01T00:00:00Z"),
186
+ uuid: () => "00000000-0000-0000-0000-000000000000",
187
+ ...overrides,
188
+ };
189
+ }
190
+
191
+ /**
192
+ * 의존성 병합 (기본값 + 커스텀)
193
+ */
194
+ export function mergeDeps(
195
+ base: FillingDeps,
196
+ overrides: Partial<FillingDeps>
197
+ ): FillingDeps {
198
+ return { ...base, ...overrides };
199
+ }
200
+
201
+ /**
202
+ * 의존성 컨테이너 (싱글톤 관리)
203
+ */
204
+ class DepsContainer {
205
+ private deps: FillingDeps = createDefaultDeps();
206
+
207
+ /**
208
+ * 전역 의존성 설정
209
+ */
210
+ set(deps: Partial<FillingDeps>): void {
211
+ this.deps = mergeDeps(this.deps, deps);
212
+ }
213
+
214
+ /**
215
+ * 전역 의존성 가져오기
216
+ */
217
+ get(): FillingDeps {
218
+ return this.deps;
219
+ }
220
+
221
+ /**
222
+ * 기본값으로 리셋
223
+ */
224
+ reset(): void {
225
+ this.deps = createDefaultDeps();
226
+ }
227
+ }
228
+
229
+ /**
230
+ * 전역 의존성 컨테이너
231
+ */
232
+ export const globalDeps = new DepsContainer();
233
+
234
+ /**
235
+ * 의존성 주입 데코레이터 타입
236
+ * (향후 클래스 기반 핸들러 지원 시)
237
+ */
238
+ export type InjectDeps<T extends keyof FillingDeps> = Pick<FillingDeps, T>;
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  import type { RouteSpec } from "../spec/schema";
7
+ import { GENERATED_RELATIVE_PATHS } from "../paths";
7
8
 
8
9
  /**
9
10
  * Convert string to PascalCase
@@ -63,7 +64,7 @@ function computeRelativePath(fromDir: string, toPath: string): string {
63
64
  */
64
65
  export function generateContractTypeGlue(
65
66
  route: RouteSpec,
66
- typesDir: string = "apps/server/generated/types"
67
+ typesDir: string = GENERATED_RELATIVE_PATHS.types
67
68
  ): string {
68
69
  if (!route.contractModule) {
69
70
  return "";
@@ -3,6 +3,7 @@ import { generateApiHandler, generatePageComponent, generateSlotLogic } from "./
3
3
  import { generateContractTypeGlue, generateContractTemplate, generateContractTypesIndex } from "./contract-glue";
4
4
  import { computeHash } from "../spec/lock";
5
5
  import { getWatcher } from "../watcher/watcher";
6
+ import { resolveGeneratedPaths, GENERATED_RELATIVE_PATHS } from "../paths";
6
7
  import path from "path";
7
8
  import fs from "fs/promises";
8
9
  import fsSync from "fs";
@@ -141,10 +142,11 @@ export async function generateRoutes(
141
142
  const watcher = getWatcher();
142
143
  watcher?.suppress();
143
144
 
144
- const serverRoutesDir = path.join(rootDir, "apps/server/generated/routes");
145
- const webRoutesDir = path.join(rootDir, "apps/web/generated/routes");
146
- const typesDir = path.join(rootDir, "apps/server/generated/types");
147
- const mapDir = path.join(rootDir, "packages/core/map");
145
+ const generatedPaths = resolveGeneratedPaths(rootDir);
146
+ const serverRoutesDir = generatedPaths.serverRoutesDir;
147
+ const webRoutesDir = generatedPaths.webRoutesDir;
148
+ const typesDir = generatedPaths.typesDir;
149
+ const mapDir = generatedPaths.mapDir;
148
150
 
149
151
  await ensureDir(serverRoutesDir);
150
152
  await ensureDir(webRoutesDir);
@@ -155,7 +157,7 @@ export async function generateRoutes(
155
157
  version: manifest.version,
156
158
  generatedAt: new Date().toISOString(),
157
159
  specSource: {
158
- path: "spec/routes.manifest.json",
160
+ path: ".mandu/routes.manifest.json",
159
161
  hash: computeHash(manifest),
160
162
  },
161
163
  files: {},
@@ -177,7 +179,7 @@ export async function generateRoutes(
177
179
  try {
178
180
  // Spec 위치 정보
179
181
  const specLocation: SpecLocation = {
180
- file: "spec/routes.manifest.json",
182
+ file: ".mandu/routes.manifest.json",
181
183
  routeIndex,
182
184
  jsonPath: `routes[${routeIndex}]`,
183
185
  };
@@ -221,19 +223,19 @@ export async function generateRoutes(
221
223
  const typeFilePath = path.join(typesDir, typeFileName);
222
224
  expectedTypeFiles.add(typeFileName);
223
225
 
224
- const typeGlueContent = generateContractTypeGlue(route, "apps/server/generated/types");
226
+ const typeGlueContent = generateContractTypeGlue(route, GENERATED_RELATIVE_PATHS.types);
225
227
  await Bun.write(typeFilePath, typeGlueContent);
226
228
  result.created.push(typeFilePath);
227
229
 
228
230
  contractMapping = {
229
231
  contractPath: route.contractModule,
230
- typeGluePath: `apps/server/generated/types/${typeFileName}`,
232
+ typeGluePath: `${GENERATED_RELATIVE_PATHS.types}/${typeFileName}`,
231
233
  };
232
234
 
233
235
  routesWithContracts.push(route.id);
234
236
  }
235
237
 
236
- generatedMap.files[`apps/server/generated/routes/${serverFileName}`] = {
238
+ generatedMap.files[`${GENERATED_RELATIVE_PATHS.serverRoutes}/${serverFileName}`] = {
237
239
  routeId: route.id,
238
240
  kind: route.kind as "api" | "page",
239
241
  specLocation,
@@ -269,7 +271,7 @@ export async function generateRoutes(
269
271
  await Bun.write(webFilePath, componentContent);
270
272
  result.created.push(webFilePath);
271
273
 
272
- generatedMap.files[`apps/web/generated/routes/${webFileName}`] = {
274
+ generatedMap.files[`${GENERATED_RELATIVE_PATHS.webRoutes}/${webFileName}`] = {
273
275
  routeId: route.id,
274
276
  kind: route.kind,
275
277
  specLocation,
@@ -1,3 +1,3 @@
1
- export * from "./generate";
2
- export * from "./templates";
3
- export * from "./contract-glue";
1
+ export * from "./generate";
2
+ export * from "./templates";
3
+ export * from "./contract-glue";