@simplysm/sd-cli 14.0.11 → 14.0.12

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 (263) hide show
  1. package/README.md +58 -253
  2. package/dist/angular/client-transform-stylesheet.js +1 -1
  3. package/dist/angular/client-transform-stylesheet.js.map +1 -1
  4. package/dist/angular/vite-angular-plugin.d.ts +1 -1
  5. package/dist/angular/vite-angular-plugin.d.ts.map +1 -1
  6. package/dist/angular/vite-angular-plugin.js +60 -34
  7. package/dist/angular/vite-angular-plugin.js.map +1 -1
  8. package/dist/angular/vite-postcss-inline-plugin.d.ts +1 -1
  9. package/dist/angular/vite-postcss-inline-plugin.js +1 -1
  10. package/dist/capacitor/capacitor.d.ts +14 -2
  11. package/dist/capacitor/capacitor.d.ts.map +1 -1
  12. package/dist/capacitor/capacitor.js +131 -17
  13. package/dist/capacitor/capacitor.js.map +1 -1
  14. package/dist/commands/build.d.ts +3 -10
  15. package/dist/commands/build.d.ts.map +1 -1
  16. package/dist/commands/build.js +3 -10
  17. package/dist/commands/build.js.map +1 -1
  18. package/dist/commands/check.js +3 -3
  19. package/dist/commands/check.js.map +1 -1
  20. package/dist/commands/dev.d.ts +3 -9
  21. package/dist/commands/dev.d.ts.map +1 -1
  22. package/dist/commands/dev.js +3 -9
  23. package/dist/commands/dev.js.map +1 -1
  24. package/dist/commands/device.d.ts +3 -3
  25. package/dist/commands/device.js +5 -5
  26. package/dist/commands/device.js.map +1 -1
  27. package/dist/commands/publish.d.ts +1 -1
  28. package/dist/commands/publish.d.ts.map +1 -1
  29. package/dist/commands/publish.js +18 -26
  30. package/dist/commands/publish.js.map +1 -1
  31. package/dist/commands/replace-deps.d.ts +3 -3
  32. package/dist/commands/replace-deps.d.ts.map +1 -1
  33. package/dist/commands/replace-deps.js +1 -1
  34. package/dist/commands/typecheck.d.ts +4 -3
  35. package/dist/commands/typecheck.d.ts.map +1 -1
  36. package/dist/commands/typecheck.js +5 -11
  37. package/dist/commands/typecheck.js.map +1 -1
  38. package/dist/commands/watch.d.ts +9 -9
  39. package/dist/commands/watch.js +9 -9
  40. package/dist/electron/electron.d.ts.map +1 -1
  41. package/dist/electron/electron.js +42 -3
  42. package/dist/electron/electron.js.map +1 -1
  43. package/dist/engines/BaseEngine.d.ts +1 -1
  44. package/dist/engines/BaseEngine.d.ts.map +1 -1
  45. package/dist/engines/BaseEngine.js +3 -1
  46. package/dist/engines/BaseEngine.js.map +1 -1
  47. package/dist/engines/NgtscEngine.d.ts +7 -7
  48. package/dist/engines/NgtscEngine.d.ts.map +1 -1
  49. package/dist/engines/NgtscEngine.js +3 -3
  50. package/dist/engines/ServerEsbuildEngine.d.ts +7 -7
  51. package/dist/engines/ServerEsbuildEngine.d.ts.map +1 -1
  52. package/dist/engines/ServerEsbuildEngine.js +3 -3
  53. package/dist/engines/TscEngine.d.ts +7 -7
  54. package/dist/engines/TscEngine.d.ts.map +1 -1
  55. package/dist/engines/TscEngine.js +3 -3
  56. package/dist/engines/ViteEngine.d.ts +1 -1
  57. package/dist/engines/ViteEngine.d.ts.map +1 -1
  58. package/dist/engines/ViteEngine.js +7 -12
  59. package/dist/engines/ViteEngine.js.map +1 -1
  60. package/dist/engines/index.d.ts +5 -5
  61. package/dist/engines/index.js +5 -5
  62. package/dist/engines/types.d.ts +20 -20
  63. package/dist/engines/types.d.ts.map +1 -1
  64. package/dist/infra/ResultCollector.d.ts +9 -9
  65. package/dist/infra/ResultCollector.js +8 -8
  66. package/dist/infra/SignalHandler.d.ts +7 -7
  67. package/dist/infra/SignalHandler.js +7 -7
  68. package/dist/infra/WorkerManager.d.ts +14 -14
  69. package/dist/infra/WorkerManager.js +14 -14
  70. package/dist/orchestrators/BuildOrchestrator.d.ts +25 -25
  71. package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
  72. package/dist/orchestrators/BuildOrchestrator.js +29 -29
  73. package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
  74. package/dist/orchestrators/DevWatchOrchestrator.d.ts +7 -7
  75. package/dist/orchestrators/DevWatchOrchestrator.d.ts.map +1 -1
  76. package/dist/orchestrators/DevWatchOrchestrator.js +34 -34
  77. package/dist/orchestrators/DevWatchOrchestrator.js.map +1 -1
  78. package/dist/sd-cli-entry.d.ts +2 -2
  79. package/dist/sd-cli-entry.d.ts.map +1 -1
  80. package/dist/sd-cli-entry.js +15 -8
  81. package/dist/sd-cli-entry.js.map +1 -1
  82. package/dist/sd-cli.d.ts +3 -3
  83. package/dist/sd-cli.js +16 -16
  84. package/dist/sd-cli.js.map +1 -1
  85. package/dist/sd-config.types.d.ts +105 -105
  86. package/dist/sd-config.types.d.ts.map +1 -1
  87. package/dist/utils/angular-compiler.js +5 -5
  88. package/dist/utils/angular-compiler.js.map +1 -1
  89. package/dist/utils/build-env.d.ts +1 -1
  90. package/dist/utils/build-env.js +1 -1
  91. package/dist/utils/concurrency.d.ts +7 -7
  92. package/dist/utils/concurrency.js +7 -7
  93. package/dist/utils/copy-public.d.ts +9 -9
  94. package/dist/utils/copy-public.js +17 -17
  95. package/dist/utils/copy-public.js.map +1 -1
  96. package/dist/utils/copy-src.d.ts +9 -9
  97. package/dist/utils/copy-src.js +11 -11
  98. package/dist/utils/copy-src.js.map +1 -1
  99. package/dist/utils/engine-stop.d.ts +8 -9
  100. package/dist/utils/engine-stop.d.ts.map +1 -1
  101. package/dist/utils/engine-stop.js +9 -10
  102. package/dist/utils/engine-stop.js.map +1 -1
  103. package/dist/utils/esbuild-config.d.ts +23 -23
  104. package/dist/utils/esbuild-config.d.ts.map +1 -1
  105. package/dist/utils/esbuild-config.js +25 -25
  106. package/dist/utils/esbuild-config.js.map +1 -1
  107. package/dist/utils/lint-with-program.d.ts +15 -15
  108. package/dist/utils/lint-with-program.d.ts.map +1 -1
  109. package/dist/utils/lint-with-program.js +29 -29
  110. package/dist/utils/lint-with-program.js.map +1 -1
  111. package/dist/utils/ngtsc-build-core.d.ts +8 -8
  112. package/dist/utils/ngtsc-build-core.d.ts.map +1 -1
  113. package/dist/utils/ngtsc-build-core.js +14 -14
  114. package/dist/utils/ngtsc-build-core.js.map +1 -1
  115. package/dist/utils/output-path-rewriter.d.ts +14 -14
  116. package/dist/utils/output-path-rewriter.js +18 -18
  117. package/dist/utils/output-path-rewriter.js.map +1 -1
  118. package/dist/utils/output-utils.d.ts +6 -6
  119. package/dist/utils/output-utils.js +11 -11
  120. package/dist/utils/output-utils.js.map +1 -1
  121. package/dist/utils/package-utils.d.ts +21 -21
  122. package/dist/utils/package-utils.d.ts.map +1 -1
  123. package/dist/utils/package-utils.js +56 -45
  124. package/dist/utils/package-utils.js.map +1 -1
  125. package/dist/utils/replace-deps.d.ts +25 -25
  126. package/dist/utils/replace-deps.d.ts.map +1 -1
  127. package/dist/utils/replace-deps.js +84 -65
  128. package/dist/utils/replace-deps.js.map +1 -1
  129. package/dist/utils/sd-config.d.ts +3 -3
  130. package/dist/utils/sd-config.js +3 -3
  131. package/dist/utils/tsc-build.d.ts +13 -13
  132. package/dist/utils/tsc-build.d.ts.map +1 -1
  133. package/dist/utils/tsc-build.js +9 -9
  134. package/dist/utils/tsc-build.js.map +1 -1
  135. package/dist/utils/tsconfig.d.ts +11 -9
  136. package/dist/utils/tsconfig.d.ts.map +1 -1
  137. package/dist/utils/tsconfig.js +11 -9
  138. package/dist/utils/tsconfig.js.map +1 -1
  139. package/dist/utils/typecheck-non-package.d.ts +5 -6
  140. package/dist/utils/typecheck-non-package.d.ts.map +1 -1
  141. package/dist/utils/typecheck-non-package.js +7 -8
  142. package/dist/utils/typecheck-non-package.js.map +1 -1
  143. package/dist/utils/typecheck-serialization.d.ts +8 -8
  144. package/dist/utils/typecheck-serialization.d.ts.map +1 -1
  145. package/dist/utils/typecheck-serialization.js +12 -16
  146. package/dist/utils/typecheck-serialization.js.map +1 -1
  147. package/dist/utils/vite-config.d.ts +8 -5
  148. package/dist/utils/vite-config.d.ts.map +1 -1
  149. package/dist/utils/vite-config.js +36 -29
  150. package/dist/utils/vite-config.js.map +1 -1
  151. package/dist/utils/vite-scope-watch-plugin.d.ts.map +1 -1
  152. package/dist/utils/vite-scope-watch-plugin.js +1 -1
  153. package/dist/utils/vite-scope-watch-plugin.js.map +1 -1
  154. package/dist/utils/worker-events.d.ts +12 -12
  155. package/dist/utils/worker-events.d.ts.map +1 -1
  156. package/dist/utils/worker-events.js +10 -10
  157. package/dist/utils/worker-events.js.map +1 -1
  158. package/dist/utils/worker-utils.d.ts +12 -13
  159. package/dist/utils/worker-utils.d.ts.map +1 -1
  160. package/dist/utils/worker-utils.js +12 -13
  161. package/dist/utils/worker-utils.js.map +1 -1
  162. package/dist/vitest-plugin.d.ts.map +1 -1
  163. package/dist/vitest-plugin.js +5 -7
  164. package/dist/vitest-plugin.js.map +1 -1
  165. package/dist/workers/client.worker.d.ts +4 -2
  166. package/dist/workers/client.worker.d.ts.map +1 -1
  167. package/dist/workers/client.worker.js +209 -1
  168. package/dist/workers/client.worker.js.map +1 -1
  169. package/dist/workers/library-build.worker.d.ts +1 -1
  170. package/dist/workers/library-build.worker.d.ts.map +1 -1
  171. package/dist/workers/library-build.worker.js +7 -7
  172. package/dist/workers/library-build.worker.js.map +1 -1
  173. package/dist/workers/lint.worker.d.ts +2 -2
  174. package/dist/workers/lint.worker.js +2 -2
  175. package/dist/workers/ngtsc-build.worker.js +30 -30
  176. package/dist/workers/ngtsc-build.worker.js.map +1 -1
  177. package/dist/workers/server-build.worker.d.ts +17 -17
  178. package/dist/workers/server-build.worker.d.ts.map +1 -1
  179. package/dist/workers/server-build.worker.js +46 -46
  180. package/dist/workers/server-build.worker.js.map +1 -1
  181. package/dist/workers/server-runtime.worker.d.ts +7 -7
  182. package/dist/workers/server-runtime.worker.d.ts.map +1 -1
  183. package/dist/workers/server-runtime.worker.js +17 -17
  184. package/dist/workers/server-runtime.worker.js.map +1 -1
  185. package/docs/config.md +340 -0
  186. package/docs/publish-configuration-types.md +87 -0
  187. package/docs/pwa-configuration-types.md +55 -0
  188. package/docs/vitest-plugin.md +47 -0
  189. package/package.json +9 -7
  190. package/src/angular/client-transform-stylesheet.ts +1 -1
  191. package/src/angular/vite-angular-plugin.ts +70 -37
  192. package/src/angular/vite-postcss-inline-plugin.ts +1 -1
  193. package/src/capacitor/capacitor.ts +159 -23
  194. package/src/commands/build.ts +3 -10
  195. package/src/commands/check.ts +3 -3
  196. package/src/commands/dev.ts +3 -9
  197. package/src/commands/device.ts +5 -5
  198. package/src/commands/publish.ts +30 -26
  199. package/src/commands/replace-deps.ts +3 -3
  200. package/src/commands/typecheck.ts +7 -13
  201. package/src/commands/watch.ts +9 -9
  202. package/src/electron/electron.ts +49 -4
  203. package/src/engines/BaseEngine.ts +4 -1
  204. package/src/engines/NgtscEngine.ts +7 -7
  205. package/src/engines/ServerEsbuildEngine.ts +7 -7
  206. package/src/engines/TscEngine.ts +7 -7
  207. package/src/engines/ViteEngine.ts +8 -13
  208. package/src/engines/index.ts +5 -5
  209. package/src/engines/types.ts +20 -20
  210. package/src/infra/ResultCollector.ts +9 -9
  211. package/src/infra/SignalHandler.ts +7 -7
  212. package/src/infra/WorkerManager.ts +14 -14
  213. package/src/orchestrators/BuildOrchestrator.ts +37 -37
  214. package/src/orchestrators/DevWatchOrchestrator.ts +36 -36
  215. package/src/sd-cli-entry.ts +15 -8
  216. package/src/sd-cli.ts +16 -16
  217. package/src/sd-config.types.ts +107 -107
  218. package/src/utils/angular-compiler.ts +5 -5
  219. package/src/utils/build-env.ts +1 -1
  220. package/src/utils/concurrency.ts +7 -7
  221. package/src/utils/copy-public.ts +17 -17
  222. package/src/utils/copy-src.ts +11 -11
  223. package/src/utils/engine-stop.ts +9 -10
  224. package/src/utils/esbuild-config.ts +29 -29
  225. package/src/utils/lint-with-program.ts +34 -34
  226. package/src/utils/ngtsc-build-core.ts +17 -17
  227. package/src/utils/output-path-rewriter.ts +18 -18
  228. package/src/utils/output-utils.ts +11 -11
  229. package/src/utils/package-utils.ts +57 -45
  230. package/src/utils/replace-deps.ts +92 -67
  231. package/src/utils/sd-config.ts +3 -3
  232. package/src/utils/tsc-build.ts +18 -18
  233. package/src/utils/tsconfig.ts +11 -9
  234. package/src/utils/typecheck-non-package.ts +7 -8
  235. package/src/utils/typecheck-serialization.ts +13 -15
  236. package/src/utils/vite-config.ts +45 -35
  237. package/src/utils/vite-scope-watch-plugin.ts +6 -1
  238. package/src/utils/worker-events.ts +16 -16
  239. package/src/utils/worker-utils.ts +12 -13
  240. package/src/vitest-plugin.ts +5 -8
  241. package/src/workers/client.worker.ts +236 -2
  242. package/src/workers/library-build.worker.ts +8 -8
  243. package/src/workers/lint.worker.ts +2 -2
  244. package/src/workers/ngtsc-build.worker.ts +31 -31
  245. package/src/workers/server-build.worker.ts +60 -60
  246. package/src/workers/server-runtime.worker.ts +22 -22
  247. package/tests/angular/vite-angular-plugin-hmr-fallback.spec.ts +1 -0
  248. package/tests/angular/vite-angular-plugin-hmr.spec.ts +78 -0
  249. package/tests/angular/vite-angular-plugin.spec.ts +67 -0
  250. package/tests/capacitor/capacitor-build.spec.ts +6 -4
  251. package/tests/capacitor/capacitor-icon.spec.ts +7 -5
  252. package/tests/capacitor/capacitor-init.spec.ts +120 -10
  253. package/tests/capacitor/capacitor-run.spec.ts +14 -17
  254. package/tests/capacitor/capacitor-workspace.spec.ts +5 -3
  255. package/tests/commands/check.spec.ts +2 -2
  256. package/tests/commands/publish.spec.ts +2 -2
  257. package/tests/commands/typecheck.spec.ts +8 -0
  258. package/tests/electron/electron.spec.ts +12 -10
  259. package/tests/engines/base-engine.spec.ts +37 -0
  260. package/tests/engines/vite-engine.spec.ts +115 -3
  261. package/tests/utils/vite-config.spec.ts +144 -90
  262. package/tests/workers/client-worker.spec.ts +690 -0
  263. package/tests/workers/server-build-worker.spec.ts +3 -3
@@ -7,12 +7,12 @@ import { exec } from "child_process";
7
7
  import { promisify } from "util";
8
8
 
9
9
  /**
10
- * Match glob patterns from replaceDeps config with target package list
11
- * and return { targetName, sourcePath } pairs
10
+ * replaceDeps 설정의 glob 패턴을 대상 패키지 목록과 매칭하여
11
+ * { targetName, sourcePath } 쌍을 반환한다.
12
12
  *
13
- * @param replaceDeps - replaceDeps config from sd.config.ts (key: glob pattern, value: source path)
14
- * @param targetNames - List of package names found in node_modules (e.g., ["@simplysm/solid", ...])
15
- * @returns Array of matched { targetName, sourcePath }
13
+ * @param replaceDeps - sd.config.ts replaceDeps 설정 (키: glob 패턴, 값: 소스 경로)
14
+ * @param targetNames - node_modules에서 찾은 패키지명 목록 (예: ["@simplysm/solid", ...])
15
+ * @returns 매칭된 { targetName, sourcePath } 배열
16
16
  */
17
17
  export function resolveReplaceDepEntries(
18
18
  replaceDeps: Record<string, string>,
@@ -21,7 +21,7 @@ export function resolveReplaceDepEntries(
21
21
  const results: Array<{ targetName: string; sourcePath: string }> = [];
22
22
 
23
23
  for (const [pattern, sourceTemplate] of Object.entries(replaceDeps)) {
24
- // Convert glob pattern to regex: * → (.*), . → \., / → [\\/]
24
+ // glob 패턴을 정규식으로 변환: * → (.*), . → \., / → [\\/]
25
25
  const regexpText = pattern.replace(/[\\/.+*]/g, (ch) => {
26
26
  if (ch === "*") return "(.*)";
27
27
  if (ch === ".") return "\\.";
@@ -36,7 +36,7 @@ export function resolveReplaceDepEntries(
36
36
  const match = regex.exec(targetName);
37
37
  if (match == null) continue;
38
38
 
39
- // If capture group exists, substitute * in source path with captured value
39
+ // 캡처 그룹이 있으면 소스 경로의 *를 캡처된 값으로 치환
40
40
  const sourcePath = hasWildcard ? sourceTemplate.replace(/\*/g, match[1]) : sourceTemplate;
41
41
 
42
42
  results.push({ targetName, sourcePath });
@@ -47,11 +47,11 @@ export function resolveReplaceDepEntries(
47
47
  }
48
48
 
49
49
  /**
50
- * Parse pnpm-workspace.yaml content and return array of workspace packages globs
51
- * Simple line parsing without separate YAML library
50
+ * pnpm-workspace.yaml 내용을 파싱하여 워크스페이스 패키지 glob 배열을 반환한다.
51
+ * 별도 YAML 라이브러리 없이 간단한 파싱으로 처리한다.
52
52
  *
53
- * @param content - Content of pnpm-workspace.yaml file
54
- * @returns Array of glob patterns (e.g., ["packages/*", "tools/*"])
53
+ * @param content - pnpm-workspace.yaml 파일 내용
54
+ * @returns glob 패턴 배열 (예: ["packages/*", "tools/*"])
55
55
  */
56
56
  export function parseWorkspaceGlobs(content: string): string[] {
57
57
  const lines = content.split("\n");
@@ -66,7 +66,7 @@ export function parseWorkspaceGlobs(content: string): string[] {
66
66
  continue;
67
67
  }
68
68
 
69
- // List items in packages section
69
+ // packages 섹션의 목록 항목
70
70
  if (inPackages && trimmed.startsWith("- ")) {
71
71
  const value = trimmed
72
72
  .slice(2)
@@ -76,7 +76,7 @@ export function parseWorkspaceGlobs(content: string): string[] {
76
76
  continue;
77
77
  }
78
78
 
79
- // End when other section starts
79
+ // 다른 섹션이 시작되면 종료
80
80
  if (inPackages && trimmed !== "" && !trimmed.startsWith("#")) {
81
81
  break;
82
82
  }
@@ -86,16 +86,16 @@ export function parseWorkspaceGlobs(content: string): string[] {
86
86
  }
87
87
 
88
88
  /**
89
- * Names to exclude during copy
89
+ * 복사 제외할 이름 목록
90
90
  */
91
91
  const EXCLUDED_NAMES = new Set(["node_modules", "package.json", ".cache", "tests"]);
92
92
 
93
93
  /**
94
- * Filter function for replaceDeps copy
95
- * Excludes node_modules, package.json, .cache, tests
94
+ * replaceDeps 복사용 필터 함수
95
+ * node_modules, package.json, .cache, tests를 제외한다.
96
96
  *
97
- * @param itemPath - Absolute path of item to copy
98
- * @returns true if copy target, false if excluded
97
+ * @param itemPath - 복사할 항목의 절대 경로
98
+ * @returns 복사 대상이면 true, 제외 대상이면 false
99
99
  */
100
100
  function replaceDepsCopyFilter(itemPath: string): boolean {
101
101
  const basename = path.basename(itemPath);
@@ -103,7 +103,7 @@ function replaceDepsCopyFilter(itemPath: string): boolean {
103
103
  }
104
104
 
105
105
  /**
106
- * replaceDeps copy/replace item
106
+ * replaceDeps 복사/교체 항목
107
107
  */
108
108
  export interface ReplaceDepEntry {
109
109
  targetName: string;
@@ -114,7 +114,7 @@ export interface ReplaceDepEntry {
114
114
  }
115
115
 
116
116
  /**
117
- * Return type of watchReplaceDeps
117
+ * watchReplaceDeps의 반환 타입
118
118
  */
119
119
  export interface WatchReplaceDepResult {
120
120
  entries: ReplaceDepEntry[];
@@ -122,13 +122,13 @@ export interface WatchReplaceDepResult {
122
122
  }
123
123
 
124
124
  /**
125
- * Collect project root and workspace package paths.
125
+ * 프로젝트 루트 워크스페이스 패키지 경로를 수집한다.
126
126
  *
127
- * Parse pnpm-workspace.yaml to collect absolute paths of workspace packages.
128
- * If file is missing or parsing fails, return only root path.
127
+ * pnpm-workspace.yaml 파싱하여 워크스페이스 패키지의 절대 경로를 수집한다.
128
+ * 파일이 없거나 파싱 실패 루트 경로만 반환한다.
129
129
  *
130
- * @param projectRoot - Project root path
131
- * @returns [root, ...workspace package paths] array
130
+ * @param projectRoot - 프로젝트 루트 경로
131
+ * @returns [루트, ...워크스페이스 패키지 경로] 배열
132
132
  */
133
133
  async function collectSearchRoots(projectRoot: string): Promise<string[]> {
134
134
  const searchRoots = [projectRoot];
@@ -143,23 +143,23 @@ async function collectSearchRoots(projectRoot: string): Promise<string[]> {
143
143
  searchRoots.push(...dirs);
144
144
  }
145
145
  } catch {
146
- // If pnpm-workspace.yaml doesn't exist, only process root
146
+ // pnpm-workspace.yaml 존재하지 않으면 루트만 처리
147
147
  }
148
148
 
149
149
  return searchRoots;
150
150
  }
151
151
 
152
152
  /**
153
- * Resolve all replacement target items from replaceDeps config.
153
+ * replaceDeps 설정에서 모든 교체 대상 항목을 해결한다.
154
154
  *
155
- * 1. Parse pnpm-workspace.yaml → workspace package paths
156
- * 2. Find matching packages in [root, ...workspace packages] node_modules
157
- * 3. Pattern matching + verify source path exists + resolve symlinks
155
+ * 1. pnpm-workspace.yaml 파싱 워크스페이스 패키지 경로
156
+ * 2. [루트, ...워크스페이스 패키지] node_modules에서 매칭 패키지 탐색
157
+ * 3. 패턴 매칭 + 소스 경로 존재 확인 + symlink 해결
158
158
  *
159
- * @param projectRoot - Project root path
160
- * @param replaceDeps - replaceDeps config from sd.config.ts
161
- * @param logger - consola logger
162
- * @returns Array of resolved replacement target items
159
+ * @param projectRoot - 프로젝트 루트 경로
160
+ * @param replaceDeps - sd.config.ts의 replaceDeps 설정
161
+ * @param logger - consola 로거
162
+ * @returns 해결된 교체 대상 항목 배열
163
163
  */
164
164
  async function resolveAllReplaceDepEntries(
165
165
  projectRoot: string,
@@ -167,35 +167,47 @@ async function resolveAllReplaceDepEntries(
167
167
  logger: ReturnType<typeof consola.withTag>,
168
168
  ): Promise<ReplaceDepEntry[]> {
169
169
  const entries: ReplaceDepEntry[] = [];
170
+ const searchedDirs = new Set<string>();
170
171
 
172
+ // 초기 탐색 대상: 프로젝트 루트 + workspace 패키지들의 node_modules
171
173
  const searchRoots = await collectSearchRoots(projectRoot);
174
+ const pendingDirs: string[] = searchRoots.map((root) =>
175
+ pathx.posix(path.join(root, "node_modules")),
176
+ );
172
177
 
173
- for (const searchRoot of searchRoots) {
174
- const nodeModulesDir = pathx.posix(path.join(searchRoot, "node_modules"));
178
+ // 교체된 패키지의 node_modules도 재귀적으로 탐색 (간접 의존성 교체)
179
+ while (pendingDirs.length > 0) {
180
+ const nodeModulesDir = pendingDirs.pop()!;
181
+
182
+ if (searchedDirs.has(nodeModulesDir)) continue;
183
+ searchedDirs.add(nodeModulesDir);
175
184
 
176
185
  try {
177
186
  await fs.promises.access(nodeModulesDir);
178
187
  } catch {
179
- continue; // Skip if node_modules doesn't exist
188
+ logger.debug(`[replace-deps] 접근 불가: ${nodeModulesDir}`);
189
+ continue;
180
190
  }
181
191
 
182
- // Search node_modules directories using each glob pattern from replaceDeps
192
+ // replaceDeps의 glob 패턴으로 node_modules 디렉토리 탐색
183
193
  const targetNames: string[] = [];
184
194
  for (const pattern of Object.keys(replaceDeps)) {
185
195
  const matches = await glob(pattern, { cwd: nodeModulesDir });
186
196
  targetNames.push(...matches);
187
197
  }
188
198
 
199
+ logger.debug(`[replace-deps] 탐색: ${nodeModulesDir} → ${targetNames.length}개 매칭 (${targetNames.join(", ")})`);
200
+
189
201
  if (targetNames.length === 0) continue;
190
202
 
191
- // Pattern matching and path resolution
203
+ // 패턴 매칭 경로 해결
192
204
  const matchedEntries = resolveReplaceDepEntries(replaceDeps, targetNames);
193
205
 
194
206
  for (const { targetName, sourcePath } of matchedEntries) {
195
207
  const targetPath = pathx.posix(path.join(nodeModulesDir, targetName));
196
208
  const resolvedSourcePath = pathx.posixResolve(projectRoot, sourcePath);
197
209
 
198
- // Verify source path exists
210
+ // 소스 경로 존재 확인
199
211
  try {
200
212
  await fs.promises.access(resolvedSourcePath);
201
213
  } catch {
@@ -203,7 +215,7 @@ async function resolveAllReplaceDepEntries(
203
215
  continue;
204
216
  }
205
217
 
206
- // If targetPath is symlink, resolve to get actual .pnpm store path
218
+ // targetPath symlink이면 실제 .pnpm 저장소 경로로 해결
207
219
  let actualTargetPath = targetPath;
208
220
  try {
209
221
  const stat = await fs.promises.lstat(targetPath);
@@ -211,9 +223,12 @@ async function resolveAllReplaceDepEntries(
211
223
  actualTargetPath = pathx.posix(await fs.promises.realpath(targetPath));
212
224
  }
213
225
  } catch {
214
- // If targetPath doesn't exist, use as-is
226
+ // targetPath 존재하지 않으면 그대로 사용
215
227
  }
216
228
 
229
+ // 동일 actualTargetPath가 이미 등록된 경우 건너뜀 (pnpm 중복 방지)
230
+ if (entries.some((e) => e.actualTargetPath === actualTargetPath)) continue;
231
+
217
232
  entries.push({
218
233
  targetName,
219
234
  sourcePath,
@@ -221,6 +236,13 @@ async function resolveAllReplaceDepEntries(
221
236
  resolvedSourcePath,
222
237
  actualTargetPath,
223
238
  });
239
+
240
+ // 교체된 패키지의 node_modules를 탐색 대기열에 추가
241
+ const depth = targetName.split(/[/\\]/).length;
242
+ const entryNodeModulesDir = pathx.posix(
243
+ path.resolve(actualTargetPath, ...Array(depth).fill("..")),
244
+ );
245
+ pendingDirs.push(entryNodeModulesDir);
224
246
  }
225
247
  }
226
248
 
@@ -228,14 +250,14 @@ async function resolveAllReplaceDepEntries(
228
250
  }
229
251
 
230
252
  /**
231
- * Replace packages in node_modules with source directories according to replaceDeps config.
253
+ * replaceDeps 설정에 따라 node_modules 패키지를 소스 디렉토리로 교체한다.
232
254
  *
233
- * 1. Parse pnpm-workspace.yaml → workspace package paths
234
- * 2. Find matching packages in [root, ...workspace packages] node_modules
235
- * 3. Remove existing symlinks/directoriescopy source path (excluding node_modules, package.json, .cache, tests)
255
+ * 1. pnpm-workspace.yaml 파싱 워크스페이스 패키지 경로
256
+ * 2. [루트, ...워크스페이스 패키지] node_modules에서 매칭 패키지 탐색
257
+ * 3. 기존 symlink/디렉토리 제거소스 경로 복사 (node_modules, package.json, .cache, tests 제외)
236
258
  *
237
- * @param projectRoot - Project root path
238
- * @param replaceDeps - replaceDeps config from sd.config.ts
259
+ * @param projectRoot - 프로젝트 루트 경로
260
+ * @param replaceDeps - sd.config.ts의 replaceDeps 설정
239
261
  */
240
262
  export async function setupReplaceDeps(
241
263
  projectRoot: string,
@@ -250,7 +272,7 @@ export async function setupReplaceDeps(
250
272
 
251
273
  for (const { targetName, resolvedSourcePath, actualTargetPath } of entries) {
252
274
  try {
253
- // Overwrite-copy source files to actualTargetPath (maintain existing directory, preserve symlinks)
275
+ // 소스 파일을 actualTargetPath에 덮어쓰기 복사 (기존 디렉토리 유지, symlink 보존)
254
276
  await fsx.copy(resolvedSourcePath, actualTargetPath, replaceDepsCopyFilter);
255
277
 
256
278
  setupCount += 1;
@@ -261,7 +283,7 @@ export async function setupReplaceDeps(
261
283
 
262
284
  logger.success(`replace-deps 설정 완료 (${setupCount}개 의존성 교체)`);
263
285
 
264
- // Run postinstall scripts from replaced packages
286
+ // 교체된 패키지의 postinstall 스크립트 실행
265
287
  for (const { targetName, resolvedSourcePath, actualTargetPath } of entries) {
266
288
  const sourcePkgJsonPath = pathx.posix(path.join(resolvedSourcePath, "package.json"));
267
289
  try {
@@ -282,16 +304,16 @@ export async function setupReplaceDeps(
282
304
  }
283
305
 
284
306
  /**
285
- * Watch source directories according to replaceDeps config and copy changes to target paths.
307
+ * replaceDeps 설정에 따라 소스 디렉토리를 감시하고 변경사항을 대상 경로에 복사한다.
286
308
  *
287
- * 1. Parse pnpm-workspace.yaml → workspace package paths
288
- * 2. Find matching packages in [root, ...workspace packages] node_modules
289
- * 3. Watch source directories with FsWatcher (300ms delay)
290
- * 4. Copy changes to target paths (excluding node_modules, package.json, .cache, tests)
309
+ * 1. pnpm-workspace.yaml 파싱 워크스페이스 패키지 경로
310
+ * 2. [루트, ...워크스페이스 패키지] node_modules에서 매칭 패키지 탐색
311
+ * 3. FsWatcher로 소스 디렉토리 감시 (300ms 딜레이)
312
+ * 4. 변경사항을 대상 경로에 복사 (node_modules, package.json, .cache, tests 제외)
291
313
  *
292
- * @param projectRoot - Project root path
293
- * @param replaceDeps - replaceDeps config from sd.config.ts
294
- * @returns entries and dispose function
314
+ * @param projectRoot - 프로젝트 루트 경로
315
+ * @param replaceDeps - sd.config.ts의 replaceDeps 설정
316
+ * @returns entries dispose 함수
295
317
  */
296
318
  export async function watchReplaceDeps(
297
319
  projectRoot: string,
@@ -301,7 +323,7 @@ export async function watchReplaceDeps(
301
323
 
302
324
  const entries = await resolveAllReplaceDepEntries(projectRoot, replaceDeps, logger);
303
325
 
304
- // Setup source directory watchers
326
+ // 소스 디렉토리 감시자 설정
305
327
  const watchers: FsWatcher[] = [];
306
328
  const watchedSources = new Set<string>();
307
329
 
@@ -315,10 +337,13 @@ export async function watchReplaceDeps(
315
337
  pathx.posix(path.join(entry.resolvedSourcePath, name)),
316
338
  );
317
339
 
318
- const watcher = await FsWatcher.watch([entry.resolvedSourcePath], { followSymlinks: false });
340
+ const watcher = await FsWatcher.watch([entry.resolvedSourcePath], {
341
+ followSymlinks: false,
342
+ ignored: [...EXCLUDED_NAMES].map((name) => `**/${name}`),
343
+ });
319
344
  watcher.onChange({ delay: 300 }, async (changeInfos) => {
320
345
  for (const { path: changedPath } of changeInfos) {
321
- // Filter excluded items: basename match or path within excluded directory
346
+ // 제외 항목 필터: basename 매칭 또는 제외 디렉토리 경로
322
347
  if (
323
348
  EXCLUDED_NAMES.has(path.basename(changedPath)) ||
324
349
  excludedPaths.some((ep) => pathx.isChildPath(changedPath, ep))
@@ -326,26 +351,26 @@ export async function watchReplaceDeps(
326
351
  continue;
327
352
  }
328
353
 
329
- // Copy for all entries using this source path
354
+ // 소스 경로를 사용하는 모든 항목에 대해 복사
330
355
  for (const e of entries) {
331
356
  if (e.resolvedSourcePath !== entry.resolvedSourcePath) continue;
332
357
 
333
- // Calculate relative path from source
358
+ // 소스로부터의 상대 경로 계산
334
359
  const relativePath = pathx.posix(path.relative(e.resolvedSourcePath, changedPath));
335
360
  const destPath = pathx.posix(path.join(e.actualTargetPath, relativePath));
336
361
 
337
362
  try {
338
- // Check if source exists
363
+ // 소스 존재 여부 확인
339
364
  let sourceExists = false;
340
365
  try {
341
366
  await fs.promises.access(changedPath);
342
367
  sourceExists = true;
343
368
  } catch {
344
- // Source was deleted
369
+ // 소스가 삭제됨
345
370
  }
346
371
 
347
372
  if (sourceExists) {
348
- // Check if source is directory or file
373
+ // 소스가 디렉토리인지 파일인지 확인
349
374
  const stat = await fs.promises.stat(changedPath);
350
375
  if (stat.isDirectory()) {
351
376
  await fsx.mkdir(destPath);
@@ -354,7 +379,7 @@ export async function watchReplaceDeps(
354
379
  await fsx.copy(changedPath, destPath, replaceDepsCopyFilter);
355
380
  }
356
381
  } else {
357
- // Source was deleted delete target
382
+ // 소스가 삭제됨대상도 삭제
358
383
  await fsx.rm(destPath);
359
384
  }
360
385
  } catch (err) {
@@ -7,9 +7,9 @@ import type { SdConfig, SdConfigParams } from "../sd-config.types";
7
7
  const logger = consola.withTag("sd:cli:sd-config");
8
8
 
9
9
  /**
10
- * Load sd.config.ts
11
- * @returns SdConfig object
12
- * @throws if sd.config.ts is missing or format is incorrect
10
+ * sd.config.ts를 로드한다.
11
+ * @returns SdConfig 객체
12
+ * @throws sd.config.ts 없거나 형식이 잘못된 경우
13
13
  */
14
14
  export async function loadSdConfig(params: SdConfigParams): Promise<SdConfig> {
15
15
  const sdConfigPath = pathx.posixResolve(params.cwd, "sd.config.ts");
@@ -17,23 +17,23 @@ import { createOutputPathRewriter, addJsExtensionToImports } from "./output-path
17
17
  import { isWorkspaceDiagnostic, formatDiagnosticError } from "./diagnostic-utils";
18
18
 
19
19
  /**
20
- * Options for package-mode tsc build
20
+ * 패키지 모드 tsc 빌드 옵션
21
21
  */
22
22
  export interface TscPackageBuildOptions {
23
23
  pkgDir: string;
24
24
  cwd: string;
25
- /** Output control flags: which files to emit */
25
+ /** 출력 제어 플래그: emit할 파일 종류 */
26
26
  output: { js: boolean; dts: boolean };
27
- /** Pre-parsed tsconfig. If provided, skips parseTsconfig() call. */
27
+ /** 미리 파싱된 tsconfig. 제공 parseTsconfig() 호출을 스킵한다. */
28
28
  parsedConfig?: ts.ParsedCommandLine;
29
- /** Typecheck environment. When set, adjusts compilerOptions via getCompilerOptionsForEnv(). */
29
+ /** 타입체크 환경. 설정 getCompilerOptionsForEnv()로 compilerOptions 조정한다. */
30
30
  env?: TypecheckEnv;
31
- /** Include tests/ files in typecheck-only mode. Defaults to false. */
31
+ /** 타입체크 전용 모드에서 tests/ 파일 포함 여부. 기본값 false. */
32
32
  includeTests?: boolean;
33
33
  }
34
34
 
35
35
  /**
36
- * Result of package-mode tsc build
36
+ * 패키지 모드 tsc 빌드 결과
37
37
  */
38
38
  export interface TscPackageBuildResult {
39
39
  success: boolean;
@@ -41,20 +41,20 @@ export interface TscPackageBuildResult {
41
41
  diagnostics: SerializedDiagnostic[];
42
42
  errorCount: number;
43
43
  warningCount: number;
44
- /** ts.Program exposed for lint-with-program integration */
44
+ /** lint-with-program 통합을 위해 노출된 ts.Program */
45
45
  program?: ts.Program;
46
- /** Files affected in this build (normalized forward-slash paths).
47
- * Used for incremental lint in watch mode. */
46
+ /** 빌드에서 영향받은 파일 (정규화된 순방향 슬래시 경로).
47
+ * watch 모드에서 증분 lint 사용한다. */
48
48
  affectedFiles?: ReadonlySet<string>;
49
49
  }
50
50
 
51
51
  /**
52
- * Run TypeScript incremental build for a package.
52
+ * 패키지에 대해 TypeScript 증분 빌드를 실행한다.
53
53
  *
54
- * - output.js || output.dts: emit mode (src files only, generates output files)
55
- * - neither: typecheck only (src files only by default, src + test files when includeTests=true)
54
+ * - output.js || output.dts: emit 모드 (src 파일만, 출력 파일 생성)
55
+ * - 아님: 타입체크만 (기본 src 파일만, includeTests=true이면 src + test 파일)
56
56
  *
57
- * Uses tsBuildInfoFile for incremental compilation across runs.
57
+ * 실행 증분 컴파일을 위해 tsBuildInfoFile을 사용한다.
58
58
  */
59
59
  export function runTscPackageBuild(options: TscPackageBuildOptions): TscPackageBuildResult {
60
60
  try {
@@ -144,9 +144,9 @@ export function runTscPackageBuild(options: TscPackageBuildOptions): TscPackageB
144
144
  host,
145
145
  );
146
146
 
147
- // Track affected files via builder program's incremental analysis.
148
- // getSemanticDiagnosticsOfNextAffectedFile iterates files that changed since the last build.
149
- // affected can be ts.SourceFile or ts.Program (when global scope changes).
147
+ // builder program의 증분 분석을 통해 affected 파일을 추적한다.
148
+ // getSemanticDiagnosticsOfNextAffectedFile 마지막 빌드 이후 변경된 파일을 순회한다.
149
+ // affected ts.SourceFile 또는 ts.Program(전역 스코프 변경 )일 수 있다.
150
150
  let affectedFiles: Set<string> | undefined = new Set<string>();
151
151
 
152
152
  while (true) {
@@ -155,7 +155,7 @@ export function runTscPackageBuild(options: TscPackageBuildOptions): TscPackageB
155
155
  if ("fileName" in result.affected) {
156
156
  affectedFiles?.add(pathx.posix(result.affected.fileName));
157
157
  } else {
158
- // ts.Program returnedglobal change, treat as full rebuild
158
+ // ts.Program 반환전역 변경, 전체 재빌드로 처리
159
159
  affectedFiles = undefined;
160
160
  }
161
161
  }
@@ -173,7 +173,7 @@ export function runTscPackageBuild(options: TscPackageBuildOptions): TscPackageB
173
173
  ...emitResult.diagnostics,
174
174
  ];
175
175
 
176
- // Workspace scope: exclude node_modules, keep all workspace diagnostics
176
+ // 워크스페이스 범위: node_modules 제외, 모든 워크스페이스 진단 유지
177
177
  const filteredDiagnostics = allDiagnostics.filter(
178
178
  (d) => isWorkspaceDiagnostic(d, options.cwd),
179
179
  );
@@ -13,7 +13,7 @@ export type TypecheckEnv = "node" | "browser";
13
13
  const DOM_LIB_PATTERNS = ["dom", "webworker"] as const;
14
14
 
15
15
  /**
16
- * Extract @types/* package names from package.json devDependencies.
16
+ * package.json devDependencies에서 @types/* 패키지명을 추출한다.
17
17
  */
18
18
  export function getTypesFromPackageJson(packageDir: string): string[] {
19
19
  const packageJsonPath = path.join(packageDir, "package.json");
@@ -33,10 +33,10 @@ export function getTypesFromPackageJson(packageDir: string): string[] {
33
33
  }
34
34
 
35
35
  /**
36
- * Adjust compilerOptions for the given typecheck environment.
36
+ * 지정된 타입체크 환경에 맞게 compilerOptions를 조정한다.
37
37
  *
38
- * - node env: remove browser-related libs (dom, webworker patterns). types unchanged.
39
- * - browser env: lib unchanged. types set explicitly from devDeps minus "node".
38
+ * - node 환경: 브라우저 관련 lib(dom, webworker 패턴) 제거한다. types 변경 없음.
39
+ * - browser 환경: lib 변경 없음. types devDeps에서 "node"를 제외하고 명시적으로 설정한다.
40
40
  */
41
41
  export function getCompilerOptionsForEnv(
42
42
  baseOptions: ts.CompilerOptions,
@@ -64,8 +64,10 @@ export function getCompilerOptionsForEnv(
64
64
  }
65
65
 
66
66
  /**
67
- * Map package target to typecheck environments.
68
- * neutral/undefineddual typecheck (node + browser).
67
+ * 패키지 target 타입체크 환경으로 매핑한다.
68
+ * - server ["node"], client ["browser"]
69
+ * - node → ["node"], browser → ["browser"]
70
+ * - neutral/undefined → 이중 타입체크 (["node", "browser"]).
69
71
  */
70
72
  export function toTypecheckEnvs(target: string | undefined): TypecheckEnv[] {
71
73
  if (target === "node" || target === "server") return ["node"];
@@ -76,7 +78,7 @@ export function toTypecheckEnvs(target: string | undefined): TypecheckEnv[] {
76
78
  //#endregion
77
79
 
78
80
  /**
79
- * Parse tsconfig.json from the given directory.
81
+ * 지정된 디렉토리에서 tsconfig.json 파싱한다.
80
82
  */
81
83
  export function parseTsconfig(dir: string): ts.ParsedCommandLine {
82
84
  const tsconfigPath = path.join(dir, "tsconfig.json");
@@ -98,7 +100,7 @@ export function parseTsconfig(dir: string): ts.ParsedCommandLine {
98
100
  }
99
101
 
100
102
  /**
101
- * Get source files (under src/) from a package, filtered by the parsed tsconfig.
103
+ * 패키지에서 소스 파일(src/ 하위) 파싱된 tsconfig 기준으로 필터링하여 반환한다.
102
104
  */
103
105
  export function getPackageSourceFiles(
104
106
  pkgDir: string,
@@ -111,7 +113,7 @@ export function getPackageSourceFiles(
111
113
  }
112
114
 
113
115
  /**
114
- * Get all files (src + tests) from a package, filtered by the parsed tsconfig.
116
+ * 패키지의 모든 파일(src + tests) 파싱된 tsconfig 기준으로 필터링하여 반환한다.
115
117
  */
116
118
  export function getPackageFiles(
117
119
  pkgDir: string,
@@ -15,13 +15,12 @@ export interface NonPackageTypecheckResult {
15
15
  }
16
16
 
17
17
  /**
18
- * Typecheck non-package files (root-level configs + package root configs).
19
- * Extracted from dts.worker.ts non-package mode.
18
+ * 비패키지 파일(루트 레벨 설정 + 패키지 루트 설정)을 타입체크한다.
20
19
  *
21
- * Non-package files include:
22
- * - Root-level files (vitest.config.ts, etc.) — not under packages/
23
- * - Package root config files (packages/{pkg}/vitest.config.ts) — depth 2 under packages/
24
- * Excludes package source files (packages/{pkg}/src/...)
20
+ * 비패키지 파일 범위:
21
+ * - 루트 레벨 파일 (vitest.config.ts ) — packages/ 외부
22
+ * - 패키지 루트 설정 파일 (packages/{pkg}/vitest.config.ts) — packages/ 하위 깊이 2
23
+ * 패키지 소스 파일(packages/{pkg}/src/...)은 제외한다.
25
24
  */
26
25
  export function typecheckNonPackageFiles(cwd: string): NonPackageTypecheckResult {
27
26
  logger.debug("비패키지 파일 타입체크 시작");
@@ -32,10 +31,10 @@ export function typecheckNonPackageFiles(cwd: string): NonPackageTypecheckResult
32
31
  const normalized = pathx.posixResolve(fileName);
33
32
  const normalizedPkgDir = pathx.posixResolve(packagesDir);
34
33
 
35
- // Files outside packages/ directory
34
+ // packages/ 디렉토리 외부 파일
36
35
  if (!normalized.startsWith(normalizedPkgDir + "/")) return true;
37
36
 
38
- // Files directly in package root (e.g., packages/{pkg}/file.ts — depth 2)
37
+ // 패키지 루트에 직접 위치한 파일 (예: packages/{pkg}/file.ts — 깊이 2)
39
38
  const relative = pathx.posix(path.relative(normalizedPkgDir, normalized));
40
39
  return relative.split("/").length === 2;
41
40
  };
@@ -2,7 +2,7 @@ import ts from "typescript";
2
2
  import { fsx } from "@simplysm/core-node";
3
3
 
4
4
  /**
5
- * Serialized Diagnostic that can be passed to Worker
5
+ * Worker로 전달할 있는 직렬화된 Diagnostic
6
6
  */
7
7
  export interface SerializedDiagnostic {
8
8
  category: number;
@@ -16,11 +16,11 @@ export interface SerializedDiagnostic {
16
16
  }
17
17
 
18
18
  /**
19
- * Convert Diagnostic to serializable form
20
- * (remove circular references/functions for structured clone communication between Worker threads)
19
+ * Diagnostic 직렬화 가능한 형태로 변환한다.
20
+ * (Worker 스레드 structured clone 통신을 위해 순환 참조/함수를 제거)
21
21
  */
22
22
  export function serializeDiagnostic(diagnostic: ts.Diagnostic): SerializedDiagnostic {
23
- // If DiagnosticMessageChain, flatten entire chain to preserve all context info
23
+ // DiagnosticMessageChain 경우 모든 컨텍스트 정보를 보존하기 위해 전체 체인을 평탄화
24
24
  const messageText = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
25
25
 
26
26
  return {
@@ -38,22 +38,20 @@ export function serializeDiagnostic(diagnostic: ts.Diagnostic): SerializedDiagno
38
38
  }
39
39
 
40
40
  /**
41
- * Determine TypeScript ScriptKind from filename
41
+ * 파일명에서 TypeScript ScriptKind 결정한다.
42
42
  */
43
43
  function getScriptKind(fileName: string): ts.ScriptKind {
44
- if (fileName.endsWith(".tsx")) return ts.ScriptKind.TSX;
45
- if (fileName.endsWith(".jsx")) return ts.ScriptKind.JSX;
46
44
  if (fileName.endsWith(".js") || fileName.endsWith(".mjs") || fileName.endsWith(".cjs"))
47
45
  return ts.ScriptKind.JS;
48
46
  return ts.ScriptKind.TS;
49
47
  }
50
48
 
51
49
  /**
52
- * Restore SerializedDiagnostic to ts.Diagnostic
53
- * Reads actual file contents so source code context is displayed in formatDiagnosticsWithColorAndContext
54
- * @param serialized - Serialized diagnostic information
55
- * @param fileCache - File content cache (prevent duplicate reads of same file)
56
- * @returns Restored ts.Diagnostic object
50
+ * SerializedDiagnostic ts.Diagnostic으로 복원한다.
51
+ * formatDiagnosticsWithColorAndContext에서 소스 코드 컨텍스트가 표시되도록 실제 파일 내용을 읽는다.
52
+ * @param serialized - 직렬화된 진단 정보
53
+ * @param fileCache - 파일 내용 캐시 (같은 파일의 중복 읽기 방지)
54
+ * @returns 복원된 ts.Diagnostic 객체
57
55
  */
58
56
  export function deserializeDiagnostic(
59
57
  serialized: SerializedDiagnostic,
@@ -63,9 +61,9 @@ export function deserializeDiagnostic(
63
61
  if (serialized.file != null) {
64
62
  const fileName = serialized.file.fileName;
65
63
 
66
- // Get cached file content (read and cache if not present)
67
- // If file was deleted or inaccessible, treat as empty content
68
- // (source code context won't be displayed but diagnostic message is shown normally)
64
+ // 캐시된 파일 내용 가져오기 (없으면 읽어서 캐시)
65
+ // 파일이 삭제되었거나 접근 불가능하면 내용으로 처리
66
+ // (소스 코드 컨텍스트는 표시되지 않지만 진단 메시지는 정상 표시됨)
69
67
  if (!fileCache.has(fileName)) {
70
68
  fileCache.set(fileName, fsx.existsSync(fileName) ? fsx.readSync(fileName) : "");
71
69
  }