@simplysm/sd-cli 14.0.8 → 14.0.10

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 (254) hide show
  1. package/dist/angular/client-transform-stylesheet.d.ts.map +1 -1
  2. package/dist/angular/client-transform-stylesheet.js.map +1 -1
  3. package/dist/angular/vite-angular-plugin.d.ts.map +1 -1
  4. package/dist/angular/vite-angular-plugin.js +15 -8
  5. package/dist/angular/vite-angular-plugin.js.map +1 -1
  6. package/dist/angular/vite-postcss-inline-plugin.d.ts.map +1 -1
  7. package/dist/angular/vite-postcss-inline-plugin.js.map +1 -1
  8. package/dist/capacitor/capacitor.d.ts.map +1 -1
  9. package/dist/capacitor/capacitor.js +41 -41
  10. package/dist/capacitor/capacitor.js.map +1 -1
  11. package/dist/commands/build.d.ts.map +1 -1
  12. package/dist/commands/build.js.map +1 -1
  13. package/dist/commands/check.d.ts.map +1 -1
  14. package/dist/commands/check.js.map +1 -1
  15. package/dist/commands/dev.d.ts.map +1 -1
  16. package/dist/commands/dev.js.map +1 -1
  17. package/dist/commands/lint.d.ts.map +1 -1
  18. package/dist/commands/lint.js.map +1 -1
  19. package/dist/commands/publish.d.ts.map +1 -1
  20. package/dist/commands/publish.js.map +1 -1
  21. package/dist/commands/replace-deps.d.ts.map +1 -1
  22. package/dist/commands/replace-deps.js.map +1 -1
  23. package/dist/commands/typecheck.d.ts.map +1 -1
  24. package/dist/commands/typecheck.js +12 -12
  25. package/dist/commands/typecheck.js.map +1 -1
  26. package/dist/commands/watch.d.ts.map +1 -1
  27. package/dist/commands/watch.js.map +1 -1
  28. package/dist/electron/electron.d.ts.map +1 -1
  29. package/dist/electron/electron.js +26 -27
  30. package/dist/electron/electron.js.map +1 -1
  31. package/dist/engines/BaseEngine.d.ts +1 -5
  32. package/dist/engines/BaseEngine.d.ts.map +1 -1
  33. package/dist/engines/BaseEngine.js +7 -16
  34. package/dist/engines/BaseEngine.js.map +1 -1
  35. package/dist/engines/NgtscEngine.d.ts.map +1 -1
  36. package/dist/engines/NgtscEngine.js +10 -11
  37. package/dist/engines/NgtscEngine.js.map +1 -1
  38. package/dist/engines/ServerEsbuildEngine.d.ts.map +1 -1
  39. package/dist/engines/ServerEsbuildEngine.js +10 -11
  40. package/dist/engines/ServerEsbuildEngine.js.map +1 -1
  41. package/dist/engines/TscEngine.d.ts.map +1 -1
  42. package/dist/engines/TscEngine.js +10 -11
  43. package/dist/engines/TscEngine.js.map +1 -1
  44. package/dist/engines/ViteEngine.d.ts.map +1 -1
  45. package/dist/engines/ViteEngine.js +3 -13
  46. package/dist/engines/ViteEngine.js.map +1 -1
  47. package/dist/engines/index.d.ts.map +1 -1
  48. package/dist/engines/index.js.map +1 -1
  49. package/dist/engines/types.d.ts +3 -6
  50. package/dist/engines/types.d.ts.map +1 -1
  51. package/dist/engines/types.js.map +1 -1
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js.map +1 -1
  54. package/dist/infra/ResultCollector.d.ts +1 -1
  55. package/dist/infra/ResultCollector.d.ts.map +1 -1
  56. package/dist/infra/ResultCollector.js.map +1 -1
  57. package/dist/infra/SignalHandler.d.ts.map +1 -1
  58. package/dist/infra/SignalHandler.js.map +1 -1
  59. package/dist/infra/WorkerManager.d.ts.map +1 -1
  60. package/dist/infra/WorkerManager.js.map +1 -1
  61. package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
  62. package/dist/orchestrators/BuildOrchestrator.js +30 -61
  63. package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
  64. package/dist/orchestrators/DevWatchOrchestrator.d.ts +2 -0
  65. package/dist/orchestrators/DevWatchOrchestrator.d.ts.map +1 -1
  66. package/dist/orchestrators/DevWatchOrchestrator.js +40 -44
  67. package/dist/orchestrators/DevWatchOrchestrator.js.map +1 -1
  68. package/dist/sd-cli-entry.d.ts.map +1 -1
  69. package/dist/sd-cli-entry.js +2 -13
  70. package/dist/sd-cli-entry.js.map +1 -1
  71. package/dist/sd-cli.d.ts.map +1 -1
  72. package/dist/sd-cli.js.map +1 -1
  73. package/dist/sd-config.types.d.ts.map +1 -1
  74. package/dist/sd-config.types.js.map +1 -1
  75. package/dist/utils/SdCliReporter.d.ts +18 -0
  76. package/dist/utils/SdCliReporter.d.ts.map +1 -0
  77. package/dist/utils/SdCliReporter.js +144 -0
  78. package/dist/utils/SdCliReporter.js.map +1 -0
  79. package/dist/utils/angular-build.d.ts.map +1 -1
  80. package/dist/utils/angular-build.js.map +1 -1
  81. package/dist/utils/angular-compiler.d.ts.map +1 -1
  82. package/dist/utils/angular-compiler.js +11 -4
  83. package/dist/utils/angular-compiler.js.map +1 -1
  84. package/dist/utils/build-env.d.ts.map +1 -1
  85. package/dist/utils/build-env.js +2 -1
  86. package/dist/utils/build-env.js.map +1 -1
  87. package/dist/utils/concurrency.d.ts.map +1 -1
  88. package/dist/utils/concurrency.js.map +1 -1
  89. package/dist/utils/copy-public.d.ts.map +1 -1
  90. package/dist/utils/copy-public.js +21 -21
  91. package/dist/utils/copy-public.js.map +1 -1
  92. package/dist/utils/copy-src.d.ts.map +1 -1
  93. package/dist/utils/copy-src.js +12 -12
  94. package/dist/utils/copy-src.js.map +1 -1
  95. package/dist/utils/diagnostic-utils.d.ts.map +1 -1
  96. package/dist/utils/diagnostic-utils.js +3 -2
  97. package/dist/utils/diagnostic-utils.js.map +1 -1
  98. package/dist/utils/engine-stop.d.ts.map +1 -1
  99. package/dist/utils/engine-stop.js.map +1 -1
  100. package/dist/utils/esbuild-config.d.ts.map +1 -1
  101. package/dist/utils/esbuild-config.js +2 -0
  102. package/dist/utils/esbuild-config.js.map +1 -1
  103. package/dist/utils/generate-pwa-icons.d.ts.map +1 -1
  104. package/dist/utils/generate-pwa-icons.js.map +1 -1
  105. package/dist/utils/hmr-candidates.d.ts.map +1 -1
  106. package/dist/utils/hmr-candidates.js.map +1 -1
  107. package/dist/utils/lint-utils.d.ts.map +1 -1
  108. package/dist/utils/lint-utils.js.map +1 -1
  109. package/dist/utils/lint-with-program.d.ts.map +1 -1
  110. package/dist/utils/lint-with-program.js +7 -3
  111. package/dist/utils/lint-with-program.js.map +1 -1
  112. package/dist/utils/ngtsc-build-core.d.ts +2 -10
  113. package/dist/utils/ngtsc-build-core.d.ts.map +1 -1
  114. package/dist/utils/ngtsc-build-core.js +16 -15
  115. package/dist/utils/ngtsc-build-core.js.map +1 -1
  116. package/dist/utils/orchestrator-utils.d.ts.map +1 -1
  117. package/dist/utils/orchestrator-utils.js.map +1 -1
  118. package/dist/utils/output-path-rewriter.d.ts.map +1 -1
  119. package/dist/utils/output-path-rewriter.js +7 -7
  120. package/dist/utils/output-path-rewriter.js.map +1 -1
  121. package/dist/utils/output-utils.d.ts.map +1 -1
  122. package/dist/utils/output-utils.js +1 -1
  123. package/dist/utils/output-utils.js.map +1 -1
  124. package/dist/utils/package-utils.d.ts +4 -0
  125. package/dist/utils/package-utils.d.ts.map +1 -1
  126. package/dist/utils/package-utils.js +34 -13
  127. package/dist/utils/package-utils.js.map +1 -1
  128. package/dist/utils/rebuild-manager.d.ts +1 -1
  129. package/dist/utils/rebuild-manager.d.ts.map +1 -1
  130. package/dist/utils/rebuild-manager.js +3 -1
  131. package/dist/utils/rebuild-manager.js.map +1 -1
  132. package/dist/utils/replace-deps.d.ts.map +1 -1
  133. package/dist/utils/replace-deps.js +10 -10
  134. package/dist/utils/replace-deps.js.map +1 -1
  135. package/dist/utils/scss-compiler.d.ts.map +1 -1
  136. package/dist/utils/scss-compiler.js.map +1 -1
  137. package/dist/utils/sd-config.d.ts.map +1 -1
  138. package/dist/utils/sd-config.js +2 -3
  139. package/dist/utils/sd-config.js.map +1 -1
  140. package/dist/utils/tsc-build.d.ts +3 -1
  141. package/dist/utils/tsc-build.d.ts.map +1 -1
  142. package/dist/utils/tsc-build.js +7 -4
  143. package/dist/utils/tsc-build.js.map +1 -1
  144. package/dist/utils/tsconfig.d.ts.map +1 -1
  145. package/dist/utils/tsconfig.js.map +1 -1
  146. package/dist/utils/typecheck-non-package.d.ts.map +1 -1
  147. package/dist/utils/typecheck-non-package.js +10 -5
  148. package/dist/utils/typecheck-non-package.js.map +1 -1
  149. package/dist/utils/typecheck-serialization.d.ts.map +1 -1
  150. package/dist/utils/typecheck-serialization.js.map +1 -1
  151. package/dist/utils/vite-config.d.ts.map +1 -1
  152. package/dist/utils/vite-config.js +2 -1
  153. package/dist/utils/vite-config.js.map +1 -1
  154. package/dist/utils/vite-scope-watch-plugin.d.ts.map +1 -1
  155. package/dist/utils/vite-scope-watch-plugin.js.map +1 -1
  156. package/dist/utils/worker-events.d.ts +1 -1
  157. package/dist/utils/worker-events.d.ts.map +1 -1
  158. package/dist/utils/worker-events.js +1 -0
  159. package/dist/utils/worker-events.js.map +1 -1
  160. package/dist/utils/worker-utils.d.ts +1 -1
  161. package/dist/utils/worker-utils.d.ts.map +1 -1
  162. package/dist/utils/worker-utils.js +3 -1
  163. package/dist/utils/worker-utils.js.map +1 -1
  164. package/dist/vitest-plugin.d.ts.map +1 -1
  165. package/dist/vitest-plugin.js.map +1 -1
  166. package/dist/workers/client.worker.d.ts.map +1 -1
  167. package/dist/workers/client.worker.js +4 -0
  168. package/dist/workers/client.worker.js.map +1 -1
  169. package/dist/workers/library-build.worker.d.ts +2 -10
  170. package/dist/workers/library-build.worker.d.ts.map +1 -1
  171. package/dist/workers/library-build.worker.js +38 -14
  172. package/dist/workers/library-build.worker.js.map +1 -1
  173. package/dist/workers/lint.worker.d.ts.map +1 -1
  174. package/dist/workers/lint.worker.js.map +1 -1
  175. package/dist/workers/ngtsc-build.worker.d.ts.map +1 -1
  176. package/dist/workers/ngtsc-build.worker.js +40 -14
  177. package/dist/workers/ngtsc-build.worker.js.map +1 -1
  178. package/dist/workers/server-build.worker.d.ts +2 -10
  179. package/dist/workers/server-build.worker.d.ts.map +1 -1
  180. package/dist/workers/server-build.worker.js +28 -19
  181. package/dist/workers/server-build.worker.js.map +1 -1
  182. package/dist/workers/server-runtime.worker.d.ts.map +1 -1
  183. package/dist/workers/server-runtime.worker.js.map +1 -1
  184. package/package.json +4 -4
  185. package/src/angular/vite-angular-plugin.ts +18 -9
  186. package/src/capacitor/capacitor.ts +41 -41
  187. package/src/commands/typecheck.ts +12 -12
  188. package/src/electron/electron.ts +26 -27
  189. package/src/engines/BaseEngine.ts +8 -19
  190. package/src/engines/NgtscEngine.ts +11 -11
  191. package/src/engines/ServerEsbuildEngine.ts +11 -11
  192. package/src/engines/TscEngine.ts +11 -11
  193. package/src/engines/ViteEngine.ts +3 -14
  194. package/src/engines/types.ts +3 -6
  195. package/src/infra/ResultCollector.ts +1 -1
  196. package/src/orchestrators/BuildOrchestrator.ts +31 -62
  197. package/src/orchestrators/DevWatchOrchestrator.ts +41 -44
  198. package/src/sd-cli-entry.ts +2 -12
  199. package/src/utils/SdCliReporter.ts +177 -0
  200. package/src/utils/angular-compiler.ts +11 -4
  201. package/src/utils/build-env.ts +2 -1
  202. package/src/utils/copy-public.ts +21 -21
  203. package/src/utils/copy-src.ts +12 -12
  204. package/src/utils/diagnostic-utils.ts +3 -2
  205. package/src/utils/esbuild-config.ts +2 -0
  206. package/src/utils/lint-with-program.ts +7 -3
  207. package/src/utils/ngtsc-build-core.ts +18 -18
  208. package/src/utils/output-path-rewriter.ts +7 -7
  209. package/src/utils/output-utils.ts +1 -1
  210. package/src/utils/package-utils.ts +37 -13
  211. package/src/utils/rebuild-manager.ts +4 -2
  212. package/src/utils/replace-deps.ts +10 -10
  213. package/src/utils/sd-config.ts +2 -3
  214. package/src/utils/tsc-build.ts +9 -4
  215. package/src/utils/typecheck-non-package.ts +10 -5
  216. package/src/utils/vite-config.ts +2 -1
  217. package/src/utils/worker-events.ts +2 -1
  218. package/src/utils/worker-utils.ts +3 -1
  219. package/src/workers/client.worker.ts +4 -0
  220. package/src/workers/library-build.worker.ts +48 -18
  221. package/src/workers/ngtsc-build.worker.ts +48 -13
  222. package/src/workers/server-build.worker.ts +30 -23
  223. package/tests/angular/vite-angular-plugin-hmr-fallback.spec.ts +11 -7
  224. package/tests/angular/vite-angular-plugin-lint.spec.ts +6 -1
  225. package/tests/capacitor/capacitor-build.spec.ts +5 -0
  226. package/tests/capacitor/capacitor-icon.spec.ts +5 -0
  227. package/tests/capacitor/capacitor-init.spec.ts +5 -0
  228. package/tests/capacitor/capacitor-run.spec.ts +5 -0
  229. package/tests/capacitor/capacitor-workspace.spec.ts +5 -0
  230. package/tests/commands/typecheck.spec.ts +20 -31
  231. package/tests/electron/electron.spec.ts +5 -0
  232. package/tests/engines/base-engine.spec.ts +15 -21
  233. package/tests/engines/engine-lint-integration.spec.ts +5 -10
  234. package/tests/engines/ngtsc-engine.spec.ts +27 -41
  235. package/tests/engines/server-esbuild-engine.spec.ts +18 -29
  236. package/tests/engines/tsc-engine.spec.ts +14 -23
  237. package/tests/engines/vite-engine.spec.ts +10 -15
  238. package/tests/infra/result-collector.spec.ts +2 -2
  239. package/tests/orchestrators/build-orchestrator.spec.ts +19 -29
  240. package/tests/orchestrators/dev-watch-orchestrator.spec.ts +110 -95
  241. package/tests/utils/copy-src.spec.ts +25 -19
  242. package/tests/utils/diagnostic-utils.spec.ts +72 -0
  243. package/tests/utils/ngtsc-build-core-angular-compiler.spec.ts +2 -3
  244. package/tests/utils/output-path-rewriter.spec.ts +7 -6
  245. package/tests/utils/output-utils.spec.ts +5 -5
  246. package/tests/utils/rebuild-manager.spec.ts +1 -1
  247. package/tests/utils/sd-config.spec.ts +4 -0
  248. package/tests/utils/tsc-build.spec.ts +23 -5
  249. package/tests/workers/library-build-worker.spec.ts +113 -20
  250. package/tests/workers/ngtsc-build-lint.spec.ts +3 -6
  251. package/tests/workers/ngtsc-build-worker.spec.ts +17 -19
  252. package/tests/workers/server-build-lint.spec.ts +4 -1
  253. package/tests/workers/server-build-worker.spec.ts +19 -22
  254. package/tests/angular/migration-cleanup.spec.ts +0 -59
@@ -2,6 +2,7 @@ import path from "path";
2
2
  import fs from "fs";
3
3
  import ts from "typescript";
4
4
  import { err as errNs } from "@simplysm/core-common";
5
+ import { pathx } from "@simplysm/core-node";
5
6
  import { consola } from "consola";
6
7
 
7
8
  const logger = consola.withTag("sd:cli:ngtsc-build");
@@ -12,6 +13,7 @@ import type { LintWithProgramResult } from "./lint-with-program";
12
13
  import {
13
14
  parseTsconfig,
14
15
  getPackageSourceFiles,
16
+ getPackageFiles,
15
17
  getCompilerOptionsForEnv,
16
18
  type TypecheckEnv,
17
19
  } from "./tsconfig";
@@ -34,8 +36,7 @@ export interface NgtscBuildInfo {
34
36
  }
35
37
 
36
38
  export interface NgtscBuildResult {
37
- js: { success: boolean; errors?: string[]; warnings?: string[] };
38
- dts: { success: boolean; errors?: string[]; diagnostics: SerializedDiagnostic[] };
39
+ build: { success: boolean; errors?: string[]; warnings?: string[]; diagnostics: SerializedDiagnostic[] };
39
40
  lint?: LintWithProgramResult;
40
41
  }
41
42
 
@@ -45,8 +46,7 @@ export interface NgtscBuildInternalResult extends NgtscBuildResult {
45
46
  }
46
47
 
47
48
  export interface NgtscCombinedBuildEvent {
48
- js: { success: boolean; errors?: string[]; warnings?: string[] };
49
- dts: { success: boolean; errors?: string[] };
49
+ build: { success: boolean; errors?: string[]; warnings?: string[] };
50
50
  lint?: LintWithProgramResult;
51
51
  }
52
52
 
@@ -192,6 +192,7 @@ export function writeEmitResults(
192
192
  pkgDir: string,
193
193
  scss?: SideEffectScssOptions,
194
194
  ): void {
195
+ logger.debug("emit 결과 파일 쓰기 시작");
195
196
  const rewritePath = createOutputPathRewriter(pkgDir);
196
197
  for (const { filename, contents, sourceFileName } of emitResults) {
197
198
  const rewrite = rewritePath(filename, contents);
@@ -241,6 +242,7 @@ export function writeEmitResults(
241
242
  fs.mkdirSync(path.dirname(newPath), { recursive: true });
242
243
  fs.writeFileSync(newPath, newContent, "utf-8");
243
244
  }
245
+ logger.debug("emit 결과 파일 쓰기 완료");
244
246
  }
245
247
 
246
248
  //#region Side-effect SCSS
@@ -256,6 +258,7 @@ export function compileSideEffectScss(
256
258
  scssErrors: string[],
257
259
  scssDependencies: Map<string, Set<string>>,
258
260
  ): void {
261
+ logger.debug(`side-effect SCSS 컴파일 시작 (${registry.size}개)`);
259
262
  for (const entry of registry.values()) {
260
263
  try {
261
264
  const result = compileScssFile(entry.scssAbsPath, loadPaths);
@@ -266,6 +269,7 @@ export function compileSideEffectScss(
266
269
  scssErrors.push(formatScssError(err, entry.scssAbsPath));
267
270
  }
268
271
  }
272
+ logger.debug("side-effect SCSS 컴파일 완료");
269
273
  }
270
274
 
271
275
  //#endregion
@@ -278,6 +282,7 @@ export function compileGlobalScss(
278
282
  ): string[] {
279
283
  const stylesPath = path.join(pkgDir, "scss", "styles.scss");
280
284
  if (!fs.existsSync(stylesPath)) return [];
285
+ logger.debug("global SCSS 컴파일 시작");
281
286
 
282
287
  const errors: string[] = [];
283
288
  try {
@@ -288,6 +293,7 @@ export function compileGlobalScss(
288
293
  } catch (err) {
289
294
  errors.push(`Global SCSS error: ${errNs.message(err)}`);
290
295
  }
296
+ logger.debug("global SCSS 컴파일 완료");
291
297
  return errors;
292
298
  }
293
299
 
@@ -302,7 +308,9 @@ export async function runNgtscBuild(info: NgtscBuildInfo): Promise<NgtscBuildInt
302
308
  logger.debug(`[${info.name}] ngtsc 빌드 시작 (env: ${info.env ?? "none"}, js: ${info.output.js}, dts: ${info.output.dts})`);
303
309
 
304
310
  const parsedConfig = parseTsconfig(info.pkgDir);
305
- const sourceFiles = getPackageSourceFiles(info.pkgDir, parsedConfig);
311
+ const sourceFiles = info.output.includeTests === true
312
+ ? getPackageFiles(info.pkgDir, parsedConfig)
313
+ : getPackageSourceFiles(info.pkgDir, parsedConfig);
306
314
  logger.debug(`[${info.name}] rootNames: ${sourceFiles.length}개 파일`);
307
315
 
308
316
  const baseOptions =
@@ -311,12 +319,9 @@ export async function runNgtscBuild(info: NgtscBuildInfo): Promise<NgtscBuildInt
311
319
  : parsedConfig.options;
312
320
  const compilerOptions = buildCompilerOptions(baseOptions, info.pkgDir, info.output);
313
321
  const pkgSrcDir = path.join(info.pkgDir, "src");
314
- const normalizedSrcDir = pkgSrcDir.replace(/\\/g, "/");
322
+ const normalizedSrcDir = pathx.posix(pkgSrcDir);
315
323
 
316
- // Read angularCompilerOptions from root tsconfig
317
- const rootTsconfigPath = path.join(info.cwd, "tsconfig.json");
318
- const rootRawConfig = ts.readConfigFile(rootTsconfigPath, ts.sys.readFile);
319
- const angularOptions = rootRawConfig.config?.angularCompilerOptions ?? {};
324
+ const angularOptions = (parsedConfig.raw?.angularCompilerOptions ?? {}) as Record<string, unknown>;
320
325
 
321
326
  // SCSS closure variables
322
327
  const scssErrors: string[] = [];
@@ -355,7 +360,7 @@ export async function runNgtscBuild(info: NgtscBuildInfo): Promise<NgtscBuildInt
355
360
  // Emit via AngularCompiler + output-path-rewriting
356
361
  const emitResults = compiler.emitAffectedFiles({
357
362
  sourceFilter: (fileName: string) =>
358
- fileName.replace(/\\/g, "/").startsWith(normalizedSrcDir + "/"),
363
+ pathx.posix(fileName).startsWith(normalizedSrcDir + "/"),
359
364
  });
360
365
  writeEmitResults(emitResults, info.pkgDir, {
361
366
  loadPaths,
@@ -372,14 +377,10 @@ export async function runNgtscBuild(info: NgtscBuildInfo): Promise<NgtscBuildInt
372
377
  const buildSuccess = errorCount === 0 && scssErrors.length === 0 && globalScssErrors.length === 0;
373
378
 
374
379
  return {
375
- js: {
380
+ build: {
376
381
  success: buildSuccess,
377
382
  errors: allErrors.length > 0 ? allErrors : undefined,
378
383
  warnings: undefined,
379
- },
380
- dts: {
381
- success: buildSuccess,
382
- errors: allErrors.length > 0 ? allErrors : undefined,
383
384
  diagnostics: serialized,
384
385
  },
385
386
  program: compiler.getTsProgram(),
@@ -392,8 +393,7 @@ export async function runNgtscBuild(info: NgtscBuildInfo): Promise<NgtscBuildInt
392
393
  logger.debug(`[${info.name}] 스택 트레이스:\n${stack}`);
393
394
  }
394
395
  return {
395
- js: { success: false, errors: [message] },
396
- dts: { success: false, errors: [message], diagnostics: [] },
396
+ build: { success: false, errors: [message], diagnostics: [] },
397
397
  };
398
398
  }
399
399
  }
@@ -46,7 +46,7 @@ export function adjustMapSources(content: string, originalDir: string, newDir: s
46
46
  if (Array.isArray(map.sources)) {
47
47
  map.sources = map.sources.map((source) => {
48
48
  const absoluteSource = path.resolve(originalDir, source);
49
- return path.relative(newDir, absoluteSource);
49
+ return pathx.posix(path.relative(newDir, absoluteSource));
50
50
  });
51
51
  }
52
52
  return JSON.stringify(map);
@@ -69,19 +69,19 @@ export function createOutputPathRewriter(
69
69
  pkgDir: string,
70
70
  ): (fileName: string, content: string) => [string, string] | null {
71
71
  const pkgName = path.basename(pkgDir);
72
- const distDir = pathx.norm(path.join(pkgDir, "dist"));
73
- const distPrefix = distDir + path.sep;
72
+ const distDir = pathx.posixResolve(pkgDir, "dist");
73
+ const distPrefix = distDir + "/";
74
74
  // Nested structure prefix for this package: dist/{pkgName}/src/
75
- const ownNestedPrefix = pathx.norm(path.join(distDir, pkgName, "src")) + path.sep;
75
+ const ownNestedPrefix = pathx.posixResolve(distDir, pkgName, "src") + "/";
76
76
 
77
77
  return (fileName, content) => {
78
- fileName = pathx.norm(fileName);
78
+ fileName = pathx.posixResolve(fileName);
79
79
 
80
80
  if (!fileName.startsWith(distPrefix)) return null;
81
81
 
82
82
  if (fileName.startsWith(ownNestedPrefix)) {
83
83
  // Rewrite nested path to flat: dist/{pkgName}/src/... → dist/...
84
- const flatPath = path.join(distDir, fileName.slice(ownNestedPrefix.length));
84
+ const flatPath = pathx.posixResolve(distDir, fileName.slice(ownNestedPrefix.length));
85
85
  if (fileName.endsWith(".d.ts.map") || fileName.endsWith(".js.map")) {
86
86
  content = adjustMapSources(content, path.dirname(fileName), path.dirname(flatPath));
87
87
  }
@@ -90,7 +90,7 @@ export function createOutputPathRewriter(
90
90
 
91
91
  // Nested output from other packages (dist/{otherPkg}/src/...) → ignore
92
92
  const relFromDist = fileName.slice(distPrefix.length);
93
- const segments = relFromDist.split(path.sep);
93
+ const segments = relFromDist.split("/");
94
94
  if (segments.length >= 3 && segments[1] === "src") {
95
95
  return null;
96
96
  }
@@ -21,7 +21,7 @@ export function formatBuildMessages(name: string, label: string, messages: strin
21
21
  export function printErrors(results: Map<string, BuildResult>): void {
22
22
  for (const result of results.values()) {
23
23
  if (result.status === "error") {
24
- const typeLabel = result.type === "dts" ? "dts" : result.type === "lint" ? "lint" : result.target;
24
+ const typeLabel = result.type === "lint" ? "lint" : result.target;
25
25
  if (result.message != null && result.message !== "") {
26
26
  consola.error(formatBuildMessages(result.name, typeLabel, [result.message]));
27
27
  } else {
@@ -2,6 +2,7 @@ import path from "path";
2
2
  import fs from "fs";
3
3
  import { consola } from "consola";
4
4
  import { SdError } from "@simplysm/core-common";
5
+ import { pathx } from "@simplysm/core-node";
5
6
  import type {
6
7
  BuildTarget,
7
8
  SdBuildPackageConfig,
@@ -36,8 +37,8 @@ export function iteratePackages(
36
37
  */
37
38
  export function findPackageRoot(startDir: string): string {
38
39
  let dir = startDir;
39
- while (!fs.existsSync(path.join(dir, "package.json"))) {
40
- const parent = path.dirname(dir);
40
+ while (!fs.existsSync(pathx.posix(path.join(dir, "package.json")))) {
41
+ const parent = pathx.posix(path.dirname(dir));
41
42
  if (parent === dir) throw new Error("package.json not found");
42
43
  dir = parent;
43
44
  }
@@ -49,13 +50,14 @@ export function findPackageRoot(startDir: string): string {
49
50
  * Returns a map of directory name → relative path (e.g., "orm" → "tests/orm").
50
51
  */
51
52
  export function discoverWorkspacePackages(cwd: string): Map<string, string> {
53
+ logger.debug("워크스페이스 패키지 탐색 시작");
52
54
  const map = new Map<string, string>();
53
55
  for (const dir of ["packages", "tests"]) {
54
- const baseDir = path.join(cwd, dir);
56
+ const baseDir = pathx.posix(path.join(cwd, dir));
55
57
  if (!fs.existsSync(baseDir)) continue;
56
58
  for (const entry of fs.readdirSync(baseDir, { withFileTypes: true })) {
57
59
  if (!entry.isDirectory()) continue;
58
- if (!fs.existsSync(path.join(baseDir, entry.name, "package.json"))) continue;
60
+ if (!fs.existsSync(pathx.posix(path.join(baseDir, entry.name, "package.json")))) continue;
59
61
  if (map.has(entry.name)) {
60
62
  throw new SdError(
61
63
  `Duplicate workspace package name: ${entry.name} (${map.get(entry.name)} and ${dir}/${entry.name})`,
@@ -64,6 +66,7 @@ export function discoverWorkspacePackages(cwd: string): Map<string, string> {
64
66
  map.set(entry.name, `${dir}/${entry.name}`);
65
67
  }
66
68
  }
69
+ logger.debug(`워크스페이스 패키지 탐색 완료 (${map.size}개)`);
67
70
  return map;
68
71
  }
69
72
 
@@ -73,10 +76,24 @@ export function discoverWorkspacePackages(cwd: string): Map<string, string> {
73
76
  * Also builds a pathMap (name → relative path) for all packages.
74
77
  * Throws SdError if a tests package name collides with an sd.config.ts package name.
75
78
  */
79
+ /**
80
+ * Build pathMap from sd.config.ts packages only (without tests packages).
81
+ */
82
+ export function buildPathMapFromConfig(
83
+ configPackages: Record<string, SdPackageConfig | undefined>,
84
+ ): Map<string, string> {
85
+ const pathMap = new Map<string, string>();
86
+ for (const name of Object.keys(configPackages)) {
87
+ pathMap.set(name, `packages/${name}`);
88
+ }
89
+ return pathMap;
90
+ }
91
+
76
92
  export function mergeTestsPackagesIntoConfig(
77
93
  configPackages: Record<string, SdPackageConfig | undefined>,
78
94
  workspacePackages: Map<string, string>,
79
95
  ): { merged: Record<string, SdPackageConfig | undefined>; pathMap: Map<string, string> } {
96
+ logger.debug("tests 패키지 병합 시작");
80
97
  const pathMap = new Map<string, string>();
81
98
  const merged: Record<string, SdPackageConfig | undefined> = { ...configPackages };
82
99
 
@@ -99,6 +116,7 @@ export function mergeTestsPackagesIntoConfig(
99
116
  pathMap.set(name, relPath);
100
117
  }
101
118
 
119
+ logger.debug(`tests 패키지 병합 완료 (총 ${Object.keys(merged).length}개)`);
102
120
  return { merged, pathMap };
103
121
  }
104
122
 
@@ -114,7 +132,7 @@ export function collectDeps(
114
132
  ): DepsResult {
115
133
  const startTime = performance.now();
116
134
  logger.debug("의존성 수집 시작");
117
- const rootPkgJsonPath = path.join(cwd, "package.json");
135
+ const rootPkgJsonPath = pathx.posix(path.join(cwd, "package.json"));
118
136
  const rootPkgJson = JSON.parse(fs.readFileSync(rootPkgJsonPath, "utf-8")) as { name: string };
119
137
  const scopeMatch = rootPkgJson.name.match(/^(@[^/]+)\//);
120
138
  const workspaceScope = scopeMatch != null ? scopeMatch[1] : undefined;
@@ -132,7 +150,7 @@ export function collectDeps(
132
150
  const visited = new Set<string>();
133
151
 
134
152
  function traverse(dir: string): void {
135
- const pkgJsonPath = path.join(dir, "package.json");
153
+ const pkgJsonPath = pathx.posix(path.join(dir, "package.json"));
136
154
  if (!fs.existsSync(pkgJsonPath)) return;
137
155
 
138
156
  const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8")) as {
@@ -147,8 +165,8 @@ export function collectDeps(
147
165
  // Check for workspace package
148
166
  if (workspaceScope != null && dep.startsWith(workspaceScope + "/")) {
149
167
  const dirName = dep.slice(workspaceScope.length + 1);
150
- const depDir = path.join(cwd, "packages", dirName);
151
- if (fs.existsSync(path.join(depDir, "package.json"))) {
168
+ const depDir = pathx.posix(path.join(cwd, "packages", dirName));
169
+ if (fs.existsSync(pathx.posix(path.join(depDir, "package.json")))) {
152
170
  workspaceDeps.push(dirName);
153
171
  traverse(depDir);
154
172
  continue;
@@ -159,8 +177,8 @@ export function collectDeps(
159
177
  const matched = replaceDepsPatterns.find((p) => p.regex.test(dep));
160
178
  if (matched != null) {
161
179
  replaceDeps.push(dep);
162
- const depNodeModulesDir = path.join(cwd, "node_modules", ...dep.split("/"));
163
- if (fs.existsSync(path.join(depNodeModulesDir, "package.json"))) {
180
+ const depNodeModulesDir = pathx.posix(path.join(cwd, "node_modules", ...dep.split("/")));
181
+ if (fs.existsSync(pathx.posix(path.join(depNodeModulesDir, "package.json")))) {
164
182
  traverse(depNodeModulesDir);
165
183
  }
166
184
  continue;
@@ -180,7 +198,7 @@ export function collectDeps(
180
198
  * in dependencies or peerDependencies.
181
199
  */
182
200
  export function hasAngularCoreDependency(pkgDir: string): boolean {
183
- const pkgJsonPath = path.join(pkgDir, "package.json");
201
+ const pkgJsonPath = pathx.posix(path.join(pkgDir, "package.json"));
184
202
  if (!fs.existsSync(pkgJsonPath)) return false;
185
203
  try {
186
204
  const content = fs.readFileSync(pkgJsonPath, "utf-8");
@@ -226,6 +244,7 @@ export function filterPackagesByTargets(
226
244
  packages: Record<string, SdPackageConfig | undefined>,
227
245
  targets: string[],
228
246
  ): Record<string, SdPackageConfig> {
247
+ logger.debug(`패키지 필터링 시작 (targets: ${targets.length > 0 ? targets.join(", ") : "전체"})`);
229
248
  const result: Record<string, SdPackageConfig> = {};
230
249
 
231
250
  for (const [name, config] of Object.entries(packages)) {
@@ -246,6 +265,7 @@ export function filterPackagesByTargets(
246
265
  }
247
266
  }
248
267
 
268
+ logger.debug(`패키지 필터링 완료 (${Object.keys(result).length}개)`);
249
269
  return result;
250
270
  }
251
271
 
@@ -268,12 +288,13 @@ export function classifyWatchPackages(
268
288
  cwd: string,
269
289
  pathMap: Map<string, string>,
270
290
  ): WatchClassifiedPackages {
291
+ logger.debug("watch 패키지 분류 시작");
271
292
  const libraryPackages: WatchClassifiedPackages["libraryPackages"] = [];
272
293
  const watchHookPackages: WatchClassifiedPackages["watchHookPackages"] = [];
273
294
 
274
295
  for (const { name, config } of iteratePackages(allPackages, [])) {
275
296
  const relPath = pathMap.get(name) ?? `packages/${name}`;
276
- const pkgDir = path.join(cwd, relPath);
297
+ const pkgDir = pathx.posix(path.join(cwd, relPath));
277
298
  if (isLibraryTarget(config.target)) {
278
299
  const buildConfig = config as SdBuildPackageConfig;
279
300
  libraryPackages.push({ name, dir: pkgDir, config: buildConfig });
@@ -289,6 +310,7 @@ export function classifyWatchPackages(
289
310
  }
290
311
  }
291
312
 
313
+ logger.debug(`watch 패키지 분류 완료 (library: ${libraryPackages.length}, watchHook: ${watchHookPackages.length})`);
292
314
  return { libraryPackages, watchHookPackages };
293
315
  }
294
316
 
@@ -307,6 +329,7 @@ export function classifyDevPackages(
307
329
  cwd: string,
308
330
  pathMap: Map<string, string>,
309
331
  ): DevClassifiedPackages {
332
+ logger.debug("dev 패키지 분류 시작");
310
333
  const serverPackages: DevClassifiedPackages["serverPackages"] = [];
311
334
  const clientPackages: DevClassifiedPackages["clientPackages"] = [];
312
335
  const serverClientsMap = new Map<string, string[]>();
@@ -324,7 +347,7 @@ export function classifyDevPackages(
324
347
  // Second pass: classify all packages
325
348
  for (const { name, config } of entries) {
326
349
  const relPath = pathMap.get(name) ?? `packages/${name}`;
327
- const pkgDir = path.join(cwd, relPath);
350
+ const pkgDir = pathx.posix(path.join(cwd, relPath));
328
351
  if (config.target === "server") {
329
352
  serverPackages.push({
330
353
  name,
@@ -355,6 +378,7 @@ export function classifyDevPackages(
355
378
  // Library and scripts packages are excluded from dev mode
356
379
  }
357
380
 
381
+ logger.debug(`dev 패키지 분류 완료 (server: ${serverPackages.length}, client: ${clientPackages.length})`);
358
382
  return { serverPackages, clientPackages, serverClientsMap };
359
383
  }
360
384
 
@@ -2,7 +2,7 @@ import { EventEmitter } from "node:events";
2
2
  import { consola } from "consola";
3
3
 
4
4
  interface RebuildManagerEvents {
5
- batchComplete: [];
5
+ batchComplete: [completedKeys: string[]];
6
6
  }
7
7
 
8
8
  export class RebuildManager extends EventEmitter<RebuildManagerEvents> {
@@ -19,6 +19,7 @@ export class RebuildManager extends EventEmitter<RebuildManagerEvents> {
19
19
  }
20
20
 
21
21
  registerBuild(key: string, title: string): () => void {
22
+ this._logger.debug(`빌드 등록: ${key} (${title})`);
22
23
  let resolver!: () => void;
23
24
  const promise = new Promise<void>((resolve) => {
24
25
  resolver = resolve;
@@ -35,6 +36,7 @@ export class RebuildManager extends EventEmitter<RebuildManagerEvents> {
35
36
 
36
37
  private async _runBatch(): Promise<void> {
37
38
  if (this._isRunning || this._pendingBuilds.size === 0) {
39
+ this._logger.debug(`배치 건너뜀 (running: ${String(this._isRunning)}, pending: ${this._pendingBuilds.size})`);
38
40
  return;
39
41
  }
40
42
 
@@ -60,7 +62,7 @@ export class RebuildManager extends EventEmitter<RebuildManagerEvents> {
60
62
 
61
63
  this._logger.success(`리빌드 실행 완료 (${titles})`);
62
64
 
63
- this.emit("batchComplete");
65
+ this.emit("batchComplete", Array.from(batchBuilds.keys()));
64
66
 
65
67
  this._isRunning = false;
66
68
 
@@ -133,7 +133,7 @@ export interface WatchReplaceDepResult {
133
133
  async function collectSearchRoots(projectRoot: string): Promise<string[]> {
134
134
  const searchRoots = [projectRoot];
135
135
 
136
- const workspaceYamlPath = path.join(projectRoot, "pnpm-workspace.yaml");
136
+ const workspaceYamlPath = pathx.posix(path.join(projectRoot, "pnpm-workspace.yaml"));
137
137
  try {
138
138
  const yamlContent = await fs.promises.readFile(workspaceYamlPath, "utf-8");
139
139
  const workspaceGlobs = parseWorkspaceGlobs(yamlContent);
@@ -171,7 +171,7 @@ async function resolveAllReplaceDepEntries(
171
171
  const searchRoots = await collectSearchRoots(projectRoot);
172
172
 
173
173
  for (const searchRoot of searchRoots) {
174
- const nodeModulesDir = path.join(searchRoot, "node_modules");
174
+ const nodeModulesDir = pathx.posix(path.join(searchRoot, "node_modules"));
175
175
 
176
176
  try {
177
177
  await fs.promises.access(nodeModulesDir);
@@ -192,8 +192,8 @@ async function resolveAllReplaceDepEntries(
192
192
  const matchedEntries = resolveReplaceDepEntries(replaceDeps, targetNames);
193
193
 
194
194
  for (const { targetName, sourcePath } of matchedEntries) {
195
- const targetPath = path.join(nodeModulesDir, targetName);
196
- const resolvedSourcePath = path.resolve(projectRoot, sourcePath);
195
+ const targetPath = pathx.posix(path.join(nodeModulesDir, targetName));
196
+ const resolvedSourcePath = pathx.posixResolve(projectRoot, sourcePath);
197
197
 
198
198
  // Verify source path exists
199
199
  try {
@@ -208,7 +208,7 @@ async function resolveAllReplaceDepEntries(
208
208
  try {
209
209
  const stat = await fs.promises.lstat(targetPath);
210
210
  if (stat.isSymbolicLink()) {
211
- actualTargetPath = await fs.promises.realpath(targetPath);
211
+ actualTargetPath = pathx.posix(await fs.promises.realpath(targetPath));
212
212
  }
213
213
  } catch {
214
214
  // If targetPath doesn't exist, use as-is
@@ -263,7 +263,7 @@ export async function setupReplaceDeps(
263
263
 
264
264
  // Run postinstall scripts from replaced packages
265
265
  for (const { targetName, resolvedSourcePath, actualTargetPath } of entries) {
266
- const sourcePkgJsonPath = path.join(resolvedSourcePath, "package.json");
266
+ const sourcePkgJsonPath = pathx.posix(path.join(resolvedSourcePath, "package.json"));
267
267
  try {
268
268
  const pkgJson = JSON.parse(await fs.promises.readFile(sourcePkgJsonPath, "utf-8"));
269
269
  const postinstall = pkgJson.scripts?.postinstall as string | undefined;
@@ -312,7 +312,7 @@ export async function watchReplaceDeps(
312
312
  watchedSources.add(entry.resolvedSourcePath);
313
313
 
314
314
  const excludedPaths = [...EXCLUDED_NAMES].map((name) =>
315
- path.join(entry.resolvedSourcePath, name),
315
+ pathx.posix(path.join(entry.resolvedSourcePath, name)),
316
316
  );
317
317
 
318
318
  const watcher = await FsWatcher.watch([entry.resolvedSourcePath], { followSymlinks: false });
@@ -331,8 +331,8 @@ export async function watchReplaceDeps(
331
331
  if (e.resolvedSourcePath !== entry.resolvedSourcePath) continue;
332
332
 
333
333
  // Calculate relative path from source
334
- const relativePath = path.relative(e.resolvedSourcePath, changedPath);
335
- const destPath = path.join(e.actualTargetPath, relativePath);
334
+ const relativePath = pathx.posix(path.relative(e.resolvedSourcePath, changedPath));
335
+ const destPath = pathx.posix(path.join(e.actualTargetPath, relativePath));
336
336
 
337
337
  try {
338
338
  // Check if source exists
@@ -350,7 +350,7 @@ export async function watchReplaceDeps(
350
350
  if (stat.isDirectory()) {
351
351
  await fsx.mkdir(destPath);
352
352
  } else {
353
- await fsx.mkdir(path.dirname(destPath));
353
+ await fsx.mkdir(pathx.posix(path.dirname(destPath)));
354
354
  await fsx.copy(changedPath, destPath, replaceDepsCopyFilter);
355
355
  }
356
356
  } else {
@@ -1,7 +1,6 @@
1
- import path from "path";
2
1
  import { createJiti } from "jiti";
3
2
  import { SdError } from "@simplysm/core-common";
4
- import { fsx } from "@simplysm/core-node";
3
+ import { fsx, pathx } from "@simplysm/core-node";
5
4
  import { consola } from "consola";
6
5
  import type { SdConfig, SdConfigParams } from "../sd-config.types";
7
6
 
@@ -13,7 +12,7 @@ const logger = consola.withTag("sd:cli:sd-config");
13
12
  * @throws if sd.config.ts is missing or format is incorrect
14
13
  */
15
14
  export async function loadSdConfig(params: SdConfigParams): Promise<SdConfig> {
16
- const sdConfigPath = path.resolve(params.cwd, "sd.config.ts");
15
+ const sdConfigPath = pathx.posixResolve(params.cwd, "sd.config.ts");
17
16
  logger.debug(`sd.config.ts 로드 중: ${sdConfigPath}`);
18
17
 
19
18
  if (!(await fsx.exists(sdConfigPath))) {
@@ -4,6 +4,7 @@ import { err as errNs } from "@simplysm/core-common";
4
4
  import { consola } from "consola";
5
5
 
6
6
  const logger = consola.withTag("sd:cli:tsc-build");
7
+ import { pathx } from "@simplysm/core-node";
7
8
  import {
8
9
  parseTsconfig,
9
10
  getPackageSourceFiles,
@@ -27,6 +28,8 @@ export interface TscPackageBuildOptions {
27
28
  parsedConfig?: ts.ParsedCommandLine;
28
29
  /** Typecheck environment. When set, adjusts compilerOptions via getCompilerOptionsForEnv(). */
29
30
  env?: TypecheckEnv;
31
+ /** Include tests/ files in typecheck-only mode. Defaults to false. */
32
+ includeTests?: boolean;
30
33
  }
31
34
 
32
35
  /**
@@ -49,7 +52,7 @@ export interface TscPackageBuildResult {
49
52
  * Run TypeScript incremental build for a package.
50
53
  *
51
54
  * - output.js || output.dts: emit mode (src files only, generates output files)
52
- * - neither: typecheck only (src + test files, no output)
55
+ * - neither: typecheck only (src files only by default, src + test files when includeTests=true)
53
56
  *
54
57
  * Uses tsBuildInfoFile for incremental compilation across runs.
55
58
  */
@@ -68,7 +71,7 @@ export function runTscPackageBuild(options: TscPackageBuildOptions): TscPackageB
68
71
 
69
72
  let rootFiles: string[];
70
73
 
71
- if (needsEmit) {
74
+ if (needsEmit || !options.includeTests) {
72
75
  rootFiles = getPackageSourceFiles(pkgDir, parsedConfig);
73
76
  } else {
74
77
  rootFiles = getPackageFiles(pkgDir, parsedConfig);
@@ -79,7 +82,9 @@ export function runTscPackageBuild(options: TscPackageBuildOptions): TscPackageB
79
82
  const tsBuildInfoFile = path.join(
80
83
  pkgDir,
81
84
  ".cache",
82
- needsEmit ? "build.tsbuildinfo" : `typecheck${envSuffix}.tsbuildinfo`,
85
+ needsEmit
86
+ ? `build${output.dts ? "" : "-no-dts"}${envSuffix}.tsbuildinfo`
87
+ : `typecheck${envSuffix}.tsbuildinfo`,
83
88
  );
84
89
 
85
90
  const compilerOptions: ts.CompilerOptions = {
@@ -148,7 +153,7 @@ export function runTscPackageBuild(options: TscPackageBuildOptions): TscPackageB
148
153
  const result = builderProgram.getSemanticDiagnosticsOfNextAffectedFile();
149
154
  if (result == null) break;
150
155
  if ("fileName" in result.affected) {
151
- affectedFiles?.add(result.affected.fileName.replace(/\\/g, "/"));
156
+ affectedFiles?.add(pathx.posix(result.affected.fileName));
152
157
  } else {
153
158
  // ts.Program returned — global change, treat as full rebuild
154
159
  affectedFiles = undefined;
@@ -1,6 +1,7 @@
1
1
  import path from "path";
2
2
  import ts from "typescript";
3
3
  import { consola } from "consola";
4
+ import { pathx } from "@simplysm/core-node";
4
5
  import { parseTsconfig } from "./tsconfig";
5
6
  import { serializeDiagnostic, type SerializedDiagnostic } from "./typecheck-serialization";
6
7
 
@@ -28,15 +29,15 @@ export function typecheckNonPackageFiles(cwd: string): NonPackageTypecheckResult
28
29
  const packagesDir = path.join(cwd, "packages");
29
30
 
30
31
  const isNonPackageFile = (fileName: string): boolean => {
31
- const normalized = path.resolve(fileName);
32
- const normalizedPkgDir = path.resolve(packagesDir);
32
+ const normalized = pathx.posixResolve(fileName);
33
+ const normalizedPkgDir = pathx.posixResolve(packagesDir);
33
34
 
34
35
  // Files outside packages/ directory
35
- if (!normalized.startsWith(normalizedPkgDir + path.sep)) return true;
36
+ if (!normalized.startsWith(normalizedPkgDir + "/")) return true;
36
37
 
37
38
  // Files directly in package root (e.g., packages/{pkg}/file.ts — depth 2)
38
- const relative = path.relative(normalizedPkgDir, normalized);
39
- return relative.split(path.sep).length === 2;
39
+ const relative = pathx.posix(path.relative(normalizedPkgDir, normalized));
40
+ return relative.split("/").length === 2;
40
41
  };
41
42
 
42
43
  const rootFiles = parsedConfig.fileNames.filter(isNonPackageFile);
@@ -54,14 +55,18 @@ export function typecheckNonPackageFiles(cwd: string): NonPackageTypecheckResult
54
55
  declarationMap: false,
55
56
  };
56
57
 
58
+ logger.debug("incremental 프로그램 생성 시작");
57
59
  const host = ts.createIncrementalCompilerHost(options);
58
60
  const program = ts.createIncrementalProgram({
59
61
  rootNames: rootFiles,
60
62
  options,
61
63
  host,
62
64
  });
65
+ logger.debug("incremental 프로그램 생성 완료");
63
66
 
67
+ logger.debug("emit 시작");
64
68
  program.emit();
69
+ logger.debug("emit 완료");
65
70
 
66
71
  const allDiagnostics = [
67
72
  ...program.getConfigFileParsingDiagnostics(),
@@ -1,5 +1,6 @@
1
1
  import type { InlineConfig, PluginOption } from "vite";
2
2
  import path from "path";
3
+ import { pathx } from "@simplysm/core-node";
3
4
  import tsconfigPaths from "vite-tsconfig-paths";
4
5
  import browserslistToEsbuild from "browserslist-to-esbuild";
5
6
  import { sdAngularPlugin } from "../angular/vite-angular-plugin.js";
@@ -227,7 +228,7 @@ export async function createClientViteConfig(
227
228
  if (!code.includes("import.meta")) return;
228
229
 
229
230
  // id(파일 경로)를 Vite 서빙 URL로 변환
230
- const relative = path.relative(pkgDir, id).replace(/\\/g, "/");
231
+ const relative = pathx.posix(path.relative(pkgDir, id));
231
232
  const moduleUrl = id.startsWith("/") || id.startsWith("\0")
232
233
  ? id // 가상 모듈(/@vite/client 등)은 그대로 사용
233
234
  : base + relative;
@@ -51,7 +51,7 @@ export interface BaseWorkerInfo<TEvents extends Record<string, unknown> = Record
51
51
  export interface WorkerEventHandlerOptions {
52
52
  resultKey: string;
53
53
  listrTitle: string;
54
- resultType: "build" | "dts";
54
+ resultType: "build";
55
55
  }
56
56
 
57
57
  /**
@@ -77,6 +77,7 @@ export function registerWorkerEventHandlers(
77
77
  results: Map<string, BuildResult>,
78
78
  rebuildManager: RebuildManager,
79
79
  ): (result: BuildResult) => void {
80
+ workerEventsLogger.debug(`[${workerInfo.name}] 이벤트 핸들러 등록 (${opts.resultType})`);
80
81
  const completeTask = (result: BuildResult): void => {
81
82
  results.set(opts.resultKey, result);
82
83
  workerInfo.buildResolver?.();
@@ -1,13 +1,15 @@
1
1
  import consola, { type ConsolaInstance, LogLevels } from "consola";
2
+ import { SdCliReporter } from "./SdCliReporter";
2
3
 
3
4
  /**
4
- * Apply debug log level in worker threads
5
+ * Apply sd-cli reporter and debug log level in worker threads
5
6
  *
6
7
  * Checks the SD_DEBUG environment variable (set by --debug flag in main process)
7
8
  * and applies debug log level to consola in the current worker thread.
8
9
  * Must be called at worker module top level.
9
10
  */
10
11
  export function applyDebugLevel(): void {
12
+ consola.options.reporters = [new SdCliReporter()];
11
13
  if (process.env["SD_DEBUG"] === "true") {
12
14
  consola.level = LogLevels.debug;
13
15
  }