@simplysm/sd-cli 14.0.42 → 14.0.43

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 (321) hide show
  1. package/dist/angular/angular-compiler.d.ts +0 -35
  2. package/dist/angular/angular-compiler.d.ts.map +1 -1
  3. package/dist/angular/angular-compiler.js +0 -374
  4. package/dist/angular/angular-compiler.js.map +1 -1
  5. package/dist/angular/hmr-candidates.d.ts +13 -0
  6. package/dist/angular/hmr-candidates.d.ts.map +1 -0
  7. package/dist/angular/hmr-candidates.js +230 -0
  8. package/dist/angular/hmr-candidates.js.map +1 -0
  9. package/dist/angular/ngtsc-build-core.d.ts +29 -34
  10. package/dist/angular/ngtsc-build-core.d.ts.map +1 -1
  11. package/dist/angular/ngtsc-build-core.js +90 -51
  12. package/dist/angular/ngtsc-build-core.js.map +1 -1
  13. package/dist/angular/vite-angular-plugin.d.ts +1 -1
  14. package/dist/angular/vite-angular-plugin.d.ts.map +1 -1
  15. package/dist/angular/vite-angular-plugin.js +63 -56
  16. package/dist/angular/vite-angular-plugin.js.map +1 -1
  17. package/dist/angular/web-worker-transformer.d.ts +9 -0
  18. package/dist/angular/web-worker-transformer.d.ts.map +1 -0
  19. package/dist/angular/web-worker-transformer.js +73 -0
  20. package/dist/angular/web-worker-transformer.js.map +1 -0
  21. package/dist/capacitor/capacitor.d.ts.map +1 -1
  22. package/dist/capacitor/capacitor.js +6 -4
  23. package/dist/capacitor/capacitor.js.map +1 -1
  24. package/dist/commands/check.d.ts +1 -1
  25. package/dist/commands/check.d.ts.map +1 -1
  26. package/dist/commands/check.js +15 -65
  27. package/dist/commands/check.js.map +1 -1
  28. package/dist/commands/publish/deployment-phase.d.ts.map +1 -1
  29. package/dist/commands/publish/deployment-phase.js +13 -5
  30. package/dist/commands/publish/deployment-phase.js.map +1 -1
  31. package/dist/commands/publish/npm-publisher.js +1 -1
  32. package/dist/commands/publish/npm-publisher.js.map +1 -1
  33. package/dist/commands/publish/publish-command.js +1 -1
  34. package/dist/commands/publish/publish-command.js.map +1 -1
  35. package/dist/commands/publish/version-upgrade.js +1 -1
  36. package/dist/commands/publish/version-upgrade.js.map +1 -1
  37. package/dist/commands/replace-deps.d.ts.map +1 -1
  38. package/dist/commands/replace-deps.js +2 -1
  39. package/dist/commands/replace-deps.js.map +1 -1
  40. package/dist/deps/replace-deps/collect-deps.d.ts.map +1 -1
  41. package/dist/deps/replace-deps/collect-deps.js +5 -2
  42. package/dist/deps/replace-deps/collect-deps.js.map +1 -1
  43. package/dist/deps/replace-deps/replace-deps.d.ts +21 -3
  44. package/dist/deps/replace-deps/replace-deps.d.ts.map +1 -1
  45. package/dist/deps/replace-deps/replace-deps.js +107 -62
  46. package/dist/deps/replace-deps/replace-deps.js.map +1 -1
  47. package/dist/electron/electron.js +7 -7
  48. package/dist/electron/electron.js.map +1 -1
  49. package/dist/engines/BaseEngine.d.ts.map +1 -1
  50. package/dist/engines/BaseEngine.js +2 -5
  51. package/dist/engines/BaseEngine.js.map +1 -1
  52. package/dist/engines/EsbuildClientEngine.d.ts.map +1 -1
  53. package/dist/engines/EsbuildClientEngine.js +16 -9
  54. package/dist/engines/EsbuildClientEngine.js.map +1 -1
  55. package/dist/engines/NgtscEngine.d.ts +4 -4
  56. package/dist/engines/NgtscEngine.d.ts.map +1 -1
  57. package/dist/engines/NgtscEngine.js +5 -5
  58. package/dist/engines/NgtscEngine.js.map +1 -1
  59. package/dist/engines/TscEngine.d.ts.map +1 -1
  60. package/dist/engines/TscEngine.js +0 -2
  61. package/dist/engines/TscEngine.js.map +1 -1
  62. package/dist/engines/types.d.ts +2 -0
  63. package/dist/engines/types.d.ts.map +1 -1
  64. package/dist/esbuild/esbuild-angular-compiler-plugin.d.ts +36 -0
  65. package/dist/esbuild/esbuild-angular-compiler-plugin.d.ts.map +1 -0
  66. package/dist/esbuild/esbuild-angular-compiler-plugin.js +464 -0
  67. package/dist/esbuild/esbuild-angular-compiler-plugin.js.map +1 -0
  68. package/dist/esbuild/esbuild-client-config.d.ts +8 -2
  69. package/dist/esbuild/esbuild-client-config.d.ts.map +1 -1
  70. package/dist/esbuild/esbuild-client-config.js +48 -33
  71. package/dist/esbuild/esbuild-client-config.js.map +1 -1
  72. package/dist/esbuild/esbuild-tsc-plugin.d.ts +4 -1
  73. package/dist/esbuild/esbuild-tsc-plugin.d.ts.map +1 -1
  74. package/dist/esbuild/esbuild-tsc-plugin.js +27 -23
  75. package/dist/esbuild/esbuild-tsc-plugin.js.map +1 -1
  76. package/dist/esbuild/file-reference-tracker.d.ts +24 -0
  77. package/dist/esbuild/file-reference-tracker.d.ts.map +1 -0
  78. package/dist/esbuild/file-reference-tracker.js +57 -0
  79. package/dist/esbuild/file-reference-tracker.js.map +1 -0
  80. package/dist/esbuild/lmdb-cache-store.d.ts +18 -0
  81. package/dist/esbuild/lmdb-cache-store.d.ts.map +1 -0
  82. package/dist/esbuild/lmdb-cache-store.js +41 -0
  83. package/dist/esbuild/lmdb-cache-store.js.map +1 -0
  84. package/dist/esbuild/load-result-cache.d.ts +17 -0
  85. package/dist/esbuild/load-result-cache.d.ts.map +1 -0
  86. package/dist/esbuild/load-result-cache.js +61 -0
  87. package/dist/esbuild/load-result-cache.js.map +1 -0
  88. package/dist/index.d.ts +3 -0
  89. package/dist/index.d.ts.map +1 -1
  90. package/dist/index.js +2 -0
  91. package/dist/index.js.map +1 -1
  92. package/dist/lint/lint-core.js +7 -7
  93. package/dist/lint/lint-core.js.map +1 -1
  94. package/dist/orchestrators/BaseOrchestrator.js +2 -2
  95. package/dist/orchestrators/BaseOrchestrator.js.map +1 -1
  96. package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
  97. package/dist/orchestrators/BuildOrchestrator.js +5 -19
  98. package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
  99. package/dist/orchestrators/DevOrchestrator.js +5 -5
  100. package/dist/orchestrators/DevOrchestrator.js.map +1 -1
  101. package/dist/orchestrators/WatchOrchestrator.js +6 -6
  102. package/dist/orchestrators/WatchOrchestrator.js.map +1 -1
  103. package/dist/runtime/ResultCollector.d.ts +1 -0
  104. package/dist/runtime/ResultCollector.d.ts.map +1 -1
  105. package/dist/runtime/ResultCollector.js.map +1 -1
  106. package/dist/runtime/engine-watch-events.d.ts.map +1 -1
  107. package/dist/runtime/engine-watch-events.js +3 -0
  108. package/dist/runtime/engine-watch-events.js.map +1 -1
  109. package/dist/runtime/rebuild-manager.js +1 -1
  110. package/dist/runtime/rebuild-manager.js.map +1 -1
  111. package/dist/runtime/worker-utils.js +1 -1
  112. package/dist/runtime/worker-utils.js.map +1 -1
  113. package/dist/sd-cli-entry.d.ts.map +1 -1
  114. package/dist/sd-cli-entry.js +4 -3
  115. package/dist/sd-cli-entry.js.map +1 -1
  116. package/dist/sd-cli.js +3 -3
  117. package/dist/sd-cli.js.map +1 -1
  118. package/dist/ts-compiler/SdTsCompiler.d.ts +39 -0
  119. package/dist/ts-compiler/SdTsCompiler.d.ts.map +1 -0
  120. package/dist/ts-compiler/SdTsCompiler.js +593 -0
  121. package/dist/ts-compiler/SdTsCompiler.js.map +1 -0
  122. package/dist/ts-compiler/sd-ts-compiler-options.d.ts +40 -0
  123. package/dist/ts-compiler/sd-ts-compiler-options.d.ts.map +1 -0
  124. package/dist/ts-compiler/sd-ts-compiler-options.js +2 -0
  125. package/dist/ts-compiler/sd-ts-compiler-options.js.map +1 -0
  126. package/dist/ts-compiler/sd-ts-compiler-result.d.ts +34 -0
  127. package/dist/ts-compiler/sd-ts-compiler-result.d.ts.map +1 -0
  128. package/dist/ts-compiler/sd-ts-compiler-result.js +2 -0
  129. package/dist/ts-compiler/sd-ts-compiler-result.js.map +1 -0
  130. package/dist/utils/copy-public.d.ts +6 -4
  131. package/dist/utils/copy-public.d.ts.map +1 -1
  132. package/dist/utils/copy-public.js +9 -7
  133. package/dist/utils/copy-public.js.map +1 -1
  134. package/dist/utils/diagnostic-utils.d.ts +2 -3
  135. package/dist/utils/diagnostic-utils.d.ts.map +1 -1
  136. package/dist/utils/diagnostic-utils.js +8 -9
  137. package/dist/utils/diagnostic-utils.js.map +1 -1
  138. package/dist/utils/output-utils.d.ts +8 -2
  139. package/dist/utils/output-utils.d.ts.map +1 -1
  140. package/dist/utils/output-utils.js +32 -8
  141. package/dist/utils/output-utils.js.map +1 -1
  142. package/dist/workers/client.worker.d.ts +1 -1
  143. package/dist/workers/client.worker.d.ts.map +1 -1
  144. package/dist/workers/client.worker.js +136 -110
  145. package/dist/workers/client.worker.js.map +1 -1
  146. package/dist/workers/library-build.worker.d.ts +0 -2
  147. package/dist/workers/library-build.worker.d.ts.map +1 -1
  148. package/dist/workers/library-build.worker.js +147 -70
  149. package/dist/workers/library-build.worker.js.map +1 -1
  150. package/dist/workers/server-build.worker.d.ts.map +1 -1
  151. package/dist/workers/server-build.worker.js +30 -57
  152. package/dist/workers/server-build.worker.js.map +1 -1
  153. package/dist/workers/server-esbuild-context.d.ts +7 -0
  154. package/dist/workers/server-esbuild-context.d.ts.map +1 -1
  155. package/dist/workers/server-esbuild-context.js +11 -2
  156. package/dist/workers/server-esbuild-context.js.map +1 -1
  157. package/package.json +5 -4
  158. package/src/angular/angular-compiler.ts +0 -502
  159. package/src/angular/hmr-candidates.ts +295 -0
  160. package/src/angular/ngtsc-build-core.ts +125 -92
  161. package/src/angular/vite-angular-plugin.ts +71 -65
  162. package/src/angular/web-worker-transformer.ts +117 -0
  163. package/src/capacitor/capacitor.ts +6 -4
  164. package/src/commands/check.ts +17 -76
  165. package/src/commands/publish/deployment-phase.ts +11 -7
  166. package/src/commands/publish/npm-publisher.ts +1 -1
  167. package/src/commands/publish/publish-command.ts +1 -1
  168. package/src/commands/publish/version-upgrade.ts +1 -1
  169. package/src/commands/replace-deps.ts +3 -1
  170. package/src/deps/replace-deps/collect-deps.ts +4 -2
  171. package/src/deps/replace-deps/replace-deps.ts +114 -66
  172. package/src/electron/electron.ts +7 -7
  173. package/src/engines/BaseEngine.ts +2 -6
  174. package/src/engines/EsbuildClientEngine.ts +16 -10
  175. package/src/engines/NgtscEngine.ts +7 -7
  176. package/src/engines/TscEngine.ts +0 -2
  177. package/src/engines/types.ts +2 -0
  178. package/src/esbuild/esbuild-angular-compiler-plugin.ts +647 -0
  179. package/src/esbuild/esbuild-client-config.ts +57 -41
  180. package/src/esbuild/esbuild-tsc-plugin.ts +33 -23
  181. package/src/esbuild/file-reference-tracker.ts +61 -0
  182. package/src/esbuild/lmdb-cache-store.ts +46 -0
  183. package/src/esbuild/load-result-cache.ts +85 -0
  184. package/src/index.ts +5 -0
  185. package/src/lint/lint-core.ts +7 -7
  186. package/src/orchestrators/BaseOrchestrator.ts +2 -2
  187. package/src/orchestrators/BuildOrchestrator.ts +5 -24
  188. package/src/orchestrators/DevOrchestrator.ts +5 -5
  189. package/src/orchestrators/WatchOrchestrator.ts +6 -6
  190. package/src/runtime/ResultCollector.ts +1 -0
  191. package/src/runtime/engine-watch-events.ts +3 -0
  192. package/src/runtime/rebuild-manager.ts +1 -1
  193. package/src/runtime/worker-utils.ts +1 -1
  194. package/src/sd-cli-entry.ts +5 -3
  195. package/src/sd-cli.ts +4 -4
  196. package/src/ts-compiler/SdTsCompiler.ts +815 -0
  197. package/src/ts-compiler/sd-ts-compiler-options.ts +46 -0
  198. package/src/ts-compiler/sd-ts-compiler-result.ts +34 -0
  199. package/src/utils/copy-public.ts +9 -6
  200. package/src/utils/diagnostic-utils.ts +8 -9
  201. package/src/utils/output-utils.ts +38 -8
  202. package/src/workers/client.worker.ts +160 -126
  203. package/src/workers/library-build.worker.ts +187 -75
  204. package/src/workers/server-build.worker.ts +31 -61
  205. package/src/workers/server-esbuild-context.ts +14 -2
  206. package/tests/angular/fixtures/packages/basic-app/dist/styles.css +3 -0
  207. package/tests/angular/fixtures/packages/basic-app/scss/styles.scss +5 -0
  208. package/tests/angular/vite-angular-plugin-sdtscompiler.verify.md +13 -0
  209. package/tests/angular/web-worker-transformer.spec.ts +154 -0
  210. package/tests/capacitor/capacitor-build.spec.ts +1 -1
  211. package/tests/capacitor/capacitor-icon.spec.ts +1 -1
  212. package/tests/capacitor/capacitor-init.spec.ts +1 -1
  213. package/tests/commands/check.spec.ts +90 -104
  214. package/tests/commands/publish.spec.ts +12 -4
  215. package/tests/commands/slice3-severity-cleanup.verify.md +12 -0
  216. package/tests/deps/replace-deps/collect-deps.acc.spec.ts +62 -0
  217. package/tests/deps/replace-deps/collect-deps.spec.ts +49 -0
  218. package/tests/deps/replace-deps/replace-deps-filter.spec.ts +103 -0
  219. package/tests/deps/replace-deps/replace-deps-setup.acc.spec.ts +156 -0
  220. package/tests/electron/electron.spec.ts +4 -1
  221. package/tests/engines/engine-adapter-isolation.spec.ts +5 -6
  222. package/tests/engines/engine-duplicate-output-removal.verify.md +10 -0
  223. package/tests/engines/esbuild-client-engine.acc.spec.ts +79 -0
  224. package/tests/engines/esbuild-client-engine.spec.ts +73 -3
  225. package/tests/esbuild/esbuild-angular-compiler-plugin-hmr.verify.md +23 -0
  226. package/tests/esbuild/esbuild-angular-compiler-plugin-onload.verify.md +21 -0
  227. package/tests/esbuild/esbuild-angular-compiler-plugin-onstart-extraction.verify.md +16 -0
  228. package/tests/esbuild/esbuild-angular-compiler-plugin-sdtscompiler.verify.md +15 -0
  229. package/tests/esbuild/esbuild-angular-compiler-plugin-stylesheet.verify.md +31 -0
  230. package/tests/esbuild/esbuild-angular-compiler-plugin-worker.verify.md +31 -0
  231. package/tests/esbuild/esbuild-angular-compiler-plugin.spec.ts +397 -0
  232. package/tests/esbuild/esbuild-angular-compiler-plugin.verify.md +21 -0
  233. package/tests/esbuild/esbuild-tsc-plugin-imports.verify.md +13 -0
  234. package/tests/esbuild/esbuild-tsc-plugin.acc.spec.ts +56 -111
  235. package/tests/esbuild/esbuild-tsc-plugin.spec.ts +116 -52
  236. package/tests/esbuild/file-reference-tracker.spec.ts +99 -0
  237. package/tests/esbuild/lmdb-cache-store.spec.ts +58 -0
  238. package/tests/esbuild/load-result-cache.acc.spec.ts +55 -0
  239. package/tests/esbuild/load-result-cache.spec.ts +133 -0
  240. package/tests/orchestrators/build-orchestrator.spec.ts +4 -3
  241. package/tests/orchestrators/dev-orchestrator.spec.ts +5 -5
  242. package/tests/orchestrators/slice1-stdout-to-consola.verify.md +10 -0
  243. package/tests/orchestrators/typecheck-orchestrator.spec.ts +1 -1
  244. package/tests/orchestrators/watch-orchestrator.spec.ts +7 -7
  245. package/tests/runtime/result-collector.spec.ts +64 -0
  246. package/tests/sd-cli-entry.spec.ts +3 -4
  247. package/tests/sd-cli-log-tag.verify.md +11 -0
  248. package/tests/ts-compiler/SdTsCompiler-affected-files.verify.md +8 -0
  249. package/tests/ts-compiler/SdTsCompiler-diagnostics.verify.md +12 -0
  250. package/tests/ts-compiler/SdTsCompiler-emit.verify.md +9 -0
  251. package/tests/ts-compiler/SdTsCompiler.acc.spec.ts +603 -0
  252. package/tests/ts-compiler/SdTsCompiler.spec.ts +265 -0
  253. package/tests/ts-compiler/SdTsCompiler.verify.md +41 -0
  254. package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck-browser.tsbuildinfo +1 -0
  255. package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck-node.tsbuildinfo +1 -0
  256. package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck.tsbuildinfo +1 -0
  257. package/tests/ts-compiler/fixtures/non-angular-pkg/dist/index.d.ts +2 -0
  258. package/tests/ts-compiler/fixtures/non-angular-pkg/dist/index.d.ts.map +1 -0
  259. package/tests/ts-compiler/fixtures/non-angular-pkg/dist/index.js +4 -0
  260. package/tests/ts-compiler/fixtures/non-angular-pkg/dist/index.js.map +1 -0
  261. package/tests/ts-compiler/fixtures/non-angular-pkg/dist/util.d.ts +2 -0
  262. package/tests/ts-compiler/fixtures/non-angular-pkg/dist/util.d.ts.map +1 -0
  263. package/tests/ts-compiler/fixtures/non-angular-pkg/dist/util.js +4 -0
  264. package/tests/ts-compiler/fixtures/non-angular-pkg/dist/util.js.map +1 -0
  265. package/tests/ts-compiler/fixtures/non-angular-pkg/src/index.ts +3 -0
  266. package/tests/ts-compiler/fixtures/non-angular-pkg/src/util.ts +3 -0
  267. package/tests/ts-compiler/fixtures/non-angular-pkg/tests/sample.test-file.ts +3 -0
  268. package/tests/ts-compiler/fixtures/non-angular-pkg/tsconfig.json +12 -0
  269. package/tests/ts-compiler/scss-lint-integration.verify.md +14 -0
  270. package/tests/utils/angular-build.spec.ts +1 -1
  271. package/tests/utils/copy-public-outdir.verify.md +8 -0
  272. package/tests/utils/copy-public.acc.spec.ts +52 -0
  273. package/tests/utils/copy-public.spec.ts +56 -0
  274. package/tests/utils/diagnostic-utils.spec.ts +24 -15
  275. package/tests/utils/engine-watch-events.acc.spec.ts +59 -0
  276. package/tests/utils/engine-watch-events.spec.ts +58 -0
  277. package/tests/utils/esbuild-client-config-integration.verify.md +9 -0
  278. package/tests/utils/esbuild-client-config.acc.spec.ts +45 -61
  279. package/tests/utils/esbuild-client-config.spec.ts +70 -52
  280. package/tests/utils/ngtsc-build-core-write-emit.spec.ts +12 -12
  281. package/tests/utils/ngtsc-build-core.spec.ts +1 -44
  282. package/tests/utils/output-utils.spec.ts +133 -13
  283. package/tests/utils/replace-deps-watch.acc.spec.ts +7 -1
  284. package/tests/utils/replace-deps-watch.spec.ts +57 -1
  285. package/tests/utils/worker-utils.spec.ts +8 -2
  286. package/tests/workers/client-worker-initial-build-error.verify.md +2 -3
  287. package/tests/workers/client-worker-initial-build-warnings.verify.md +7 -0
  288. package/tests/workers/client-worker-refactor.verify.md +22 -0
  289. package/tests/workers/client-worker-ts-cache-invalidation.verify.md +12 -0
  290. package/tests/workers/client-worker.acc.spec.ts +6 -3
  291. package/tests/workers/library-build-lint.spec.ts +40 -45
  292. package/tests/workers/library-build-worker.spec.ts +294 -40
  293. package/tests/workers/server-build-lint.spec.ts +59 -45
  294. package/tests/workers/server-build-worker.spec.ts +63 -24
  295. package/tests/workers/server-esbuild-context.acc.spec.ts +2 -0
  296. package/tests/workers/server-esbuild-context.spec.ts +2 -0
  297. package/tests/workers/server-runtime-worker.spec.ts +1 -1
  298. package/tests/workers/shared-worker-lifecycle.acc.spec.ts +1 -1
  299. package/dist/angular/angular-build-pipeline.d.ts +0 -97
  300. package/dist/angular/angular-build-pipeline.d.ts.map +0 -1
  301. package/dist/angular/angular-build-pipeline.js +0 -285
  302. package/dist/angular/angular-build-pipeline.js.map +0 -1
  303. package/dist/utils/tsc-build.d.ts +0 -51
  304. package/dist/utils/tsc-build.d.ts.map +0 -1
  305. package/dist/utils/tsc-build.js +0 -156
  306. package/dist/utils/tsc-build.js.map +0 -1
  307. package/dist/workers/ngtsc-build.worker.d.ts +0 -23
  308. package/dist/workers/ngtsc-build.worker.d.ts.map +0 -1
  309. package/dist/workers/ngtsc-build.worker.js +0 -267
  310. package/dist/workers/ngtsc-build.worker.js.map +0 -1
  311. package/src/angular/angular-build-pipeline.ts +0 -406
  312. package/src/utils/tsc-build.ts +0 -226
  313. package/src/workers/ngtsc-build.worker.ts +0 -351
  314. package/tests/angular/angular-build-pipeline.spec.ts +0 -247
  315. package/tests/angular/angular-compiler-aot.acc.spec.ts +0 -68
  316. package/tests/angular/angular-compiler-aot.spec.ts +0 -80
  317. package/tests/utils/angular-compiler-emit.spec.ts +0 -666
  318. package/tests/utils/angular-compiler.spec.ts +0 -707
  319. package/tests/utils/tsc-build.spec.ts +0 -527
  320. package/tests/workers/ngtsc-build-lint.spec.ts +0 -141
  321. package/tests/workers/ngtsc-build-worker.spec.ts +0 -199
@@ -16,24 +16,17 @@ vi.mock("esbuild", () => ({
16
16
  },
17
17
  }));
18
18
 
19
- const mockSourceFileCache = {
20
- loadResultCache: { name: "mockLoadResultCache" },
21
- invalidate: vi.fn(),
22
- modifiedFiles: new Set<string>(),
23
- };
19
+ const mockAngularPlugin = { name: "sd-angular-compiler" };
24
20
 
25
- const mockAngularPlugin = { name: "angular-compiler" };
21
+ vi.mock("../../src/esbuild/esbuild-angular-compiler-plugin", () => ({
22
+ createAngularCompilerPlugin: vi.fn(() => mockAngularPlugin),
23
+ }));
26
24
 
27
- vi.mock("@angular/build/private", () => {
28
- // vi.fn()의 arrow function은 new로 호출 불가 — 일반 function 사용
29
- function MockSourceFileCache() {
30
- return mockSourceFileCache;
31
- }
32
- return {
33
- createCompilerPlugin: vi.fn(() => mockAngularPlugin),
34
- SourceFileCache: vi.fn(MockSourceFileCache),
35
- };
36
- });
25
+ const mockTransformStylesheet = vi.fn();
26
+
27
+ vi.mock("../../src/angular/client-transform-stylesheet", () => ({
28
+ createClientTransformStylesheet: vi.fn(() => mockTransformStylesheet),
29
+ }));
37
30
 
38
31
  vi.mock("browserslist-to-esbuild", () => ({
39
32
  default: vi.fn(() => ["chrome61"]),
@@ -54,11 +47,16 @@ vi.mock("module", async (importOriginal) => {
54
47
 
55
48
  // --- Imports (after mocks) ---
56
49
 
57
- const { createClientEsbuildContext } = await import(
50
+ const { createClientEsbuildContext, ClientSourceFileCache } = await import(
58
51
  "../../src/esbuild/esbuild-client-config"
59
52
  );
60
53
  const esbuild = (await import("esbuild")).default;
61
- const { createCompilerPlugin, SourceFileCache } = await import("@angular/build/private");
54
+ const { createAngularCompilerPlugin } = await import(
55
+ "../../src/esbuild/esbuild-angular-compiler-plugin"
56
+ );
57
+ const { createClientTransformStylesheet } = await import(
58
+ "../../src/angular/client-transform-stylesheet"
59
+ );
62
60
  const browserslistToEsbuild = (await import("browserslist-to-esbuild")).default;
63
61
 
64
62
  // --- Helpers ---
@@ -140,43 +138,55 @@ describe("createClientEsbuildContext — define 생성", () => {
140
138
  describe("createClientEsbuildContext — 소스맵 설정", () => {
141
139
  beforeEach(() => vi.clearAllMocks());
142
140
 
143
- it("dev 모드: esbuild sourcemap=linked, CompilerPlugin sourcemap=true, StyleOptions sourcemap=linked", async () => {
141
+ it("dev 모드: esbuild sourcemap=linked, AngularCompilerPlugin sourcemap=true", async () => {
144
142
  await createClientEsbuildContext(baseDev);
145
143
  const opts = vi.mocked(esbuild.context).mock.calls[0][0];
146
144
  expect(opts.sourcemap).toBe("linked");
147
145
 
148
- const [pluginOpts, styleOpts] = vi.mocked(createCompilerPlugin).mock.calls[0];
146
+ const pluginOpts = vi.mocked(createAngularCompilerPlugin).mock.calls[0][0];
149
147
  expect(pluginOpts.sourcemap).toBe(true);
150
- expect(styleOpts.sourcemap).toBe("linked");
151
148
  });
152
149
 
153
- it("build 모드: esbuild sourcemap=false, CompilerPlugin sourcemap=false, StyleOptions sourcemap=false", async () => {
150
+ it("build 모드: esbuild sourcemap=false, AngularCompilerPlugin sourcemap=false", async () => {
154
151
  await createClientEsbuildContext(baseBuild);
155
152
  const opts = vi.mocked(esbuild.context).mock.calls[0][0];
156
153
  expect(opts.sourcemap).toBe(false);
157
154
 
158
- const [pluginOpts, styleOpts] = vi.mocked(createCompilerPlugin).mock.calls[0];
155
+ const pluginOpts = vi.mocked(createAngularCompilerPlugin).mock.calls[0][0];
159
156
  expect(pluginOpts.sourcemap).toBe(false);
160
- expect(styleOpts.sourcemap).toBe(false);
161
157
  });
162
158
  });
163
159
 
164
- describe("createClientEsbuildContext — PostCSS 설정", () => {
160
+ describe("createClientEsbuildContext — transformStylesheet 설정", () => {
165
161
  beforeEach(() => vi.clearAllMocks());
166
162
 
167
- it("postcssPlugins 미전달 postcssConfiguration이 undefined", async () => {
163
+ it("transformStylesheet 콜백이 createAngularCompilerPlugin에 전달된다", async () => {
164
+ await createClientEsbuildContext(baseBuild);
165
+ const pluginOpts = vi.mocked(createAngularCompilerPlugin).mock.calls[0][0];
166
+ expect(pluginOpts.transformStylesheet).toBe(mockTransformStylesheet);
167
+ });
168
+
169
+ it("stylesheetDependencies와 stylesheetErrors가 createAngularCompilerPlugin에 전달된다", async () => {
168
170
  await createClientEsbuildContext(baseBuild);
169
- const [, styleOpts] = vi.mocked(createCompilerPlugin).mock.calls[0];
170
- expect(styleOpts.postcssConfiguration).toBeUndefined();
171
+ const pluginOpts = vi.mocked(createAngularCompilerPlugin).mock.calls[0][0];
172
+ expect(pluginOpts.stylesheetDependencies).toBeInstanceOf(Map);
173
+ expect(pluginOpts.stylesheetErrors).toBeInstanceOf(Array);
171
174
  });
172
175
 
173
- it("postcssPlugins 전달해도 postcssConfiguration은 항상 undefined", async () => {
176
+ it("postcssPlugins createClientTransformStylesheet에 전달된다", async () => {
174
177
  await createClientEsbuildContext({
175
178
  ...baseBuild,
176
179
  postcssPlugins: [["autoprefixer"]],
177
180
  });
178
- const [, styleOpts] = vi.mocked(createCompilerPlugin).mock.calls[0];
179
- expect(styleOpts.postcssConfiguration).toBeUndefined();
181
+ const transformOpts = vi.mocked(createClientTransformStylesheet).mock.calls[0][0];
182
+ expect(transformOpts.postcssPlugins).toBeDefined();
183
+ expect(transformOpts.postcssPlugins).toHaveLength(1);
184
+ });
185
+
186
+ it("postcssPlugins 미전달 시 createClientTransformStylesheet에 postcssPlugins가 undefined", async () => {
187
+ await createClientEsbuildContext(baseBuild);
188
+ const transformOpts = vi.mocked(createClientTransformStylesheet).mock.calls[0][0];
189
+ expect(transformOpts.postcssPlugins).toBeUndefined();
180
190
  });
181
191
  });
182
192
 
@@ -232,21 +242,28 @@ describe("createClientEsbuildContext — PostCSS 플러그인 통합", () => {
232
242
  });
233
243
  });
234
244
 
235
- describe("createClientEsbuildContext — SourceFileCache", () => {
245
+ describe("createClientEsbuildContext — ClientSourceFileCache", () => {
236
246
  beforeEach(() => vi.clearAllMocks());
237
247
 
238
- it("SourceFileCache.angular/cache 경로로 생성됨", async () => {
239
- await createClientEsbuildContext(baseDev);
240
- expect(SourceFileCache).toHaveBeenCalledWith(
241
- path.join("/workspace/packages/my-app", ".angular", "cache"),
242
- );
248
+ it("반환된 sourceFileCacheClientSourceFileCache 인스턴스", async () => {
249
+ const result = await createClientEsbuildContext(baseDev);
250
+ expect(result.sourceFileCache).toBeInstanceOf(ClientSourceFileCache);
251
+ });
252
+
253
+ it("sourceFileCache의 typeScriptFileCache와 loadResultCache가 AngularCompilerPlugin에 전달됨", async () => {
254
+ const result = await createClientEsbuildContext(baseDev);
255
+ const pluginOpts = vi.mocked(createAngularCompilerPlugin).mock.calls[0][0];
256
+ expect(pluginOpts.sourceFileCache).toBe(result.sourceFileCache);
257
+ expect(pluginOpts.typeScriptFileCache).toBe(result.sourceFileCache.typeScriptFileCache);
258
+ expect(pluginOpts.loadResultCache).toBe(result.sourceFileCache.loadResultCache);
243
259
  });
244
260
 
245
- it("sourceFileCache와 loadResultCacheCompilerPluginOptions에 전달됨", async () => {
261
+ it("persistentCachePath.angular/cache 경로로 전달됨", async () => {
246
262
  await createClientEsbuildContext(baseDev);
247
- const [pluginOpts] = vi.mocked(createCompilerPlugin).mock.calls[0];
248
- expect(pluginOpts.sourceFileCache).toBe(mockSourceFileCache);
249
- expect(pluginOpts.loadResultCache).toBe(mockSourceFileCache.loadResultCache);
263
+ const pluginOpts = vi.mocked(createAngularCompilerPlugin).mock.calls[0][0];
264
+ expect(pluginOpts.persistentCachePath).toBe(
265
+ path.join("/workspace/packages/my-app", ".angular", "cache"),
266
+ );
250
267
  });
251
268
  });
252
269
 
@@ -258,7 +275,7 @@ describe("createClientEsbuildContext — 추가 옵션", () => {
258
275
  ...baseDev,
259
276
  tsconfig: "/workspace/packages/my-app/tsconfig.build.json",
260
277
  });
261
- const [pluginOpts] = vi.mocked(createCompilerPlugin).mock.calls[0];
278
+ const pluginOpts = vi.mocked(createAngularCompilerPlugin).mock.calls[0][0];
262
279
  expect(pluginOpts.tsconfig).toBe(
263
280
  "/workspace/packages/my-app/tsconfig.build.json",
264
281
  );
@@ -283,13 +300,13 @@ describe("createClientEsbuildContext — 추가 옵션", () => {
283
300
  expect(opts.plugins).toContainEqual(customPlugin);
284
301
  });
285
302
 
286
- it("templateUpdates가 CompilerPluginOptions에 전달됨", async () => {
303
+ it("templateUpdates가 AngularCompilerPluginOptions에 전달됨", async () => {
287
304
  const updates = new Map([["comp1", "template1"]]);
288
305
  await createClientEsbuildContext({
289
306
  ...baseDev,
290
307
  templateUpdates: updates,
291
308
  });
292
- const [pluginOpts] = vi.mocked(createCompilerPlugin).mock.calls[0];
309
+ const pluginOpts = vi.mocked(createAngularCompilerPlugin).mock.calls[0][0];
293
310
  expect(pluginOpts.templateUpdates).toBe(updates);
294
311
  });
295
312
  });
@@ -303,10 +320,13 @@ describe("createClientEsbuildContext — browserslist → target 변환", () =>
303
320
  expect(opts.target).toEqual(["es2022"]);
304
321
  });
305
322
 
306
- it("browserslist 미설정 시 BundleStylesheetOptions.target이 [es2022]", async () => {
323
+ it("browserslist 미설정 시 createClientTransformStylesheet의 loadPaths가 설정됨", async () => {
307
324
  await createClientEsbuildContext(baseDev);
308
- const [, styleOpts] = vi.mocked(createCompilerPlugin).mock.calls[0];
309
- expect(styleOpts.target).toEqual(["es2022"]);
325
+ const transformOpts = vi.mocked(createClientTransformStylesheet).mock.calls[0][0];
326
+ expect(transformOpts.loadPaths).toEqual([
327
+ path.join("/workspace/packages/my-app", "node_modules"),
328
+ path.join("/workspace", "node_modules"),
329
+ ]);
310
330
  });
311
331
 
312
332
  it("browserslist 문자열은 배열로 변환하여 browserslistToEsbuild에 전달", async () => {
@@ -324,16 +344,14 @@ describe("createClientEsbuildContext — browserslist → target 변환", () =>
324
344
  expect(browserslistToEsbuild).toHaveBeenCalledWith(["Chrome 61", "Firefox 60"]);
325
345
  });
326
346
 
327
- it("browserslistToEsbuild 결과가 esbuild target과 styleOptions.target동일하게 적용", async () => {
347
+ it("browserslistToEsbuild 결과가 esbuild target에 적용", async () => {
328
348
  vi.mocked(browserslistToEsbuild).mockReturnValueOnce(["chrome61", "firefox60"]);
329
349
  await createClientEsbuildContext({
330
350
  ...baseDev,
331
351
  browserslist: ["Chrome 61", "Firefox 60"],
332
352
  });
333
353
  const opts = vi.mocked(esbuild.context).mock.calls[0][0];
334
- const [, styleOpts] = vi.mocked(createCompilerPlugin).mock.calls[0];
335
354
  expect(opts.target).toEqual(["chrome61", "firefox60"]);
336
- expect(styleOpts.target).toEqual(["chrome61", "firefox60"]);
337
355
  });
338
356
  });
339
357
 
@@ -448,7 +466,7 @@ describe("createClientEsbuildContext — onEnd 플러그인", () => {
448
466
  const opts = vi.mocked(esbuild.context).mock.calls[0][0];
449
467
  const pluginNames = opts.plugins!.map((p: any) => p.name);
450
468
  const customIdx = pluginNames.indexOf("custom");
451
- const angularIdx = pluginNames.indexOf("angular-compiler");
469
+ const angularIdx = pluginNames.indexOf("sd-angular-compiler");
452
470
  expect(customIdx).toBeLessThan(angularIdx);
453
471
  });
454
472
  });
@@ -493,7 +511,7 @@ describe("createClientEsbuildContext — SCSS 플러그인 통합", () => {
493
511
  const opts = vi.mocked(esbuild.context).mock.calls[0][0];
494
512
  const pluginNames = opts.plugins!.map((p: any) => p.name);
495
513
 
496
- const angularIdx = pluginNames.indexOf("angular-compiler");
514
+ const angularIdx = pluginNames.indexOf("sd-angular-compiler");
497
515
  const scssIdx = pluginNames.indexOf("sd-scss");
498
516
 
499
517
  expect(scssIdx).toBe(angularIdx + 1);
@@ -22,7 +22,7 @@ describe("writeEmitResults", () => {
22
22
  });
23
23
 
24
24
  it("emitResults를 output-path-rewriting 적용하여 파일로 쓴다", async () => {
25
- const { writeEmitResults } = await import("../../src/angular/angular-build-pipeline");
25
+ const { writeEmitResults } = await import("../../src/angular/ngtsc-build-core");
26
26
 
27
27
  const distDir = path.join(pkgDir, "dist");
28
28
  // Simulate nested output: dist/my-pkg/src/index.js
@@ -40,7 +40,7 @@ describe("writeEmitResults", () => {
40
40
  });
41
41
 
42
42
  it("output-path-rewriter가 null을 반환하면 파일을 쓰지 않는다", async () => {
43
- const { writeEmitResults } = await import("../../src/angular/angular-build-pipeline");
43
+ const { writeEmitResults } = await import("../../src/angular/ngtsc-build-core");
44
44
 
45
45
  const distDir = path.join(pkgDir, "dist");
46
46
  // Nested output from OTHER package: dist/other-pkg/src/index.js
@@ -59,7 +59,7 @@ describe("writeEmitResults", () => {
59
59
  });
60
60
 
61
61
  it("이미 flat 구조인 경로는 그대로 쓴다", async () => {
62
- const { writeEmitResults } = await import("../../src/angular/angular-build-pipeline");
62
+ const { writeEmitResults } = await import("../../src/angular/ngtsc-build-core");
63
63
 
64
64
  const distDir = path.join(pkgDir, "dist");
65
65
  const flatPath = path.join(distDir, "index.js");
@@ -74,7 +74,7 @@ describe("writeEmitResults", () => {
74
74
  });
75
75
 
76
76
  it("디렉��리가 없으면 ��동 생성한다", async () => {
77
- const { writeEmitResults } = await import("../../src/angular/angular-build-pipeline");
77
+ const { writeEmitResults } = await import("../../src/angular/ngtsc-build-core");
78
78
 
79
79
  const distDir = path.join(pkgDir, "dist");
80
80
  // Nested path under new subdirectory
@@ -109,7 +109,7 @@ describe("writeEmitResults with side-effect SCSS", () => {
109
109
  });
110
110
 
111
111
  it("compiles side-effect SCSS to CSS and rewrites import path in JS", async () => {
112
- const { writeEmitResults } = await import("../../src/angular/angular-build-pipeline");
112
+ const { writeEmitResults } = await import("../../src/angular/ngtsc-build-core");
113
113
 
114
114
  // Create source SCSS file
115
115
  const scssPath = path.join(srcDir, "ui", "layout", "sd-flex.scss");
@@ -149,7 +149,7 @@ describe("writeEmitResults with side-effect SCSS", () => {
149
149
 
150
150
  // Acceptance: Scenario "SCSS @use 의존성 해석"
151
151
  it("resolves SCSS @use dependencies via loadPaths", async () => {
152
- const { writeEmitResults } = await import("../../src/angular/angular-build-pipeline");
152
+ const { writeEmitResults } = await import("../../src/angular/ngtsc-build-core");
153
153
 
154
154
  // Create SCSS load path with a shared variables file
155
155
  const scssLoadDir = path.join(pkgDir, "scss");
@@ -194,7 +194,7 @@ describe("writeEmitResults with side-effect SCSS", () => {
194
194
 
195
195
  // Acceptance: Scenario "SCSS 컴파일 에러"
196
196
  it("reports SCSS compilation error in scssErrors", async () => {
197
- const { writeEmitResults } = await import("../../src/angular/angular-build-pipeline");
197
+ const { writeEmitResults } = await import("../../src/angular/ngtsc-build-core");
198
198
 
199
199
  // Create SCSS file with syntax error
200
200
  const scssPath = path.join(srcDir, "ui", "layout", "broken.scss");
@@ -224,7 +224,7 @@ describe("writeEmitResults with side-effect SCSS", () => {
224
224
 
225
225
  // Acceptance: Scenario "참조하는 SCSS 파일이 존재하지 않음"
226
226
  it("reports error when referenced SCSS file does not exist", async () => {
227
- const { writeEmitResults } = await import("../../src/angular/angular-build-pipeline");
227
+ const { writeEmitResults } = await import("../../src/angular/ngtsc-build-core");
228
228
 
229
229
  const distDir = path.join(pkgDir, "dist");
230
230
  const jsPath = path.join(distDir, "my-pkg", "src", "ui", "layout", "missing.directive.js");
@@ -267,7 +267,7 @@ describe("writeEmitResults with registry", () => {
267
267
  });
268
268
 
269
269
  it("registers side-effect SCSS entries in registry when provided", async () => {
270
- const { writeEmitResults } = await import("../../src/angular/angular-build-pipeline");
270
+ const { writeEmitResults } = await import("../../src/angular/ngtsc-build-core");
271
271
 
272
272
  // Create source SCSS file
273
273
  const scssPath = path.join(srcDir, "ui", "layout", "sd-flex.scss");
@@ -304,7 +304,7 @@ describe("writeEmitResults with registry", () => {
304
304
  });
305
305
 
306
306
  it("clears stale registry entries for re-emitted source file before registering new ones", async () => {
307
- const { writeEmitResults } = await import("../../src/angular/angular-build-pipeline");
307
+ const { writeEmitResults } = await import("../../src/angular/ngtsc-build-core");
308
308
 
309
309
  const scssPath = path.join(srcDir, "ui", "layout", "sd-flex.scss");
310
310
  fs.writeFileSync(scssPath, ".sd-flex { display: flex; }", "utf-8");
@@ -345,7 +345,7 @@ describe("writeEmitResults with registry", () => {
345
345
  });
346
346
 
347
347
  it("removes registry entry when source file is re-emitted without SCSS imports", async () => {
348
- const { writeEmitResults } = await import("../../src/angular/angular-build-pipeline");
348
+ const { writeEmitResults } = await import("../../src/angular/ngtsc-build-core");
349
349
 
350
350
  const distDir = path.join(pkgDir, "dist");
351
351
  const sourceFileName = path.join(srcDir, "ui", "layout", "sd-flex.directive.ts");
@@ -382,7 +382,7 @@ describe("writeEmitResults with registry", () => {
382
382
  });
383
383
 
384
384
  it("preserves registry entries for non-emitted source files", async () => {
385
- const { writeEmitResults } = await import("../../src/angular/angular-build-pipeline");
385
+ const { writeEmitResults } = await import("../../src/angular/ngtsc-build-core");
386
386
 
387
387
  const distDir = path.join(pkgDir, "dist");
388
388
  const sourceFileA = path.join(srcDir, "ui", "layout", "sd-flex.directive.ts");
@@ -87,17 +87,10 @@ vi.mock("../../src/angular/angular-build", () => {
87
87
  };
88
88
  });
89
89
 
90
- const {
91
- buildScssLoadPaths,
92
- } = await import("../../src/angular/ngtsc-build-core");
93
90
  const {
94
91
  createLibraryTransformStylesheet,
95
- } = await import("../../src/angular/angular-build-pipeline");
96
-
97
- import { join } from "node:path";
92
+ } = await import("../../src/angular/ngtsc-build-core");
98
93
 
99
- const fakeCwd = "/workspace";
100
- const fakePkgDir = "/workspace/packages/my-angular-lib";
101
94
 
102
95
  // ─── createLibraryTransformStylesheet ───
103
96
 
@@ -193,39 +186,3 @@ describe("createLibraryTransformStylesheet", () => {
193
186
  });
194
187
  });
195
188
 
196
- // ─── buildScssLoadPaths ───
197
-
198
- describe("buildScssLoadPaths", () => {
199
- it("returns [pkgDir/scss, cwd/node_modules] for given NgtscBuildInfo", () => {
200
- const info = {
201
- name: "my-angular-lib",
202
- cwd: fakeCwd,
203
- pkgDir: fakePkgDir,
204
- output: { js: true, dts: false },
205
- };
206
-
207
- const result = buildScssLoadPaths(info);
208
-
209
- expect(result).toEqual([
210
- join(fakePkgDir, "scss"),
211
- join(fakeCwd, "node_modules"),
212
- ]);
213
- });
214
-
215
- it("uses cwd from info to construct node_modules path", () => {
216
- const customCwd = "/custom/workspace";
217
- const customPkgDir = "/custom/workspace/packages/my-pkg";
218
-
219
- const result = buildScssLoadPaths({
220
- name: "test",
221
- cwd: customCwd,
222
- pkgDir: customPkgDir,
223
- output: { js: true, dts: false },
224
- });
225
-
226
- expect(result).toEqual([
227
- join(customPkgDir, "scss"),
228
- join(customCwd, "node_modules"),
229
- ]);
230
- });
231
- });
@@ -1,32 +1,112 @@
1
1
  import { describe, it, expect, vi, beforeEach } from "vitest";
2
2
  import { consola } from "consola";
3
- import { formatBuildMessages, printErrors, printServers } from "../../src/utils/output-utils";
4
3
  import type { BuildResult } from "../../src/runtime/ResultCollector";
4
+ import type { PartialMessage } from "esbuild";
5
+
6
+ // output-utils.ts가 모듈 로드 시 consola.withTag("sd:cli:output")로 로거를 생성하므로,
7
+ // withTag가 consola 자체를 반환하도록 하여 기존 스파이가 태그 로거 호출을 캡처하게 한다.
8
+ vi.mock("consola", async (importOriginal) => {
9
+ const mod = await importOriginal<typeof import("consola")>();
10
+ const orig = mod.consola;
11
+ vi.spyOn(orig, "withTag").mockReturnValue(orig);
12
+ return { consola: orig };
13
+ });
14
+
15
+ const { formatBuildMessages, formatEsbuildMessages, printDiagnostics, printServers } =
16
+ await import("../../src/utils/output-utils");
5
17
 
6
18
  vi.spyOn(consola, "error").mockImplementation(() => {});
19
+ vi.spyOn(consola, "warn").mockImplementation(() => {});
7
20
  vi.spyOn(consola, "info").mockImplementation(() => {});
8
21
 
9
22
  describe("formatBuildMessages", () => {
10
23
  it("formats name, label, and messages into indented lines", () => {
11
24
  const result = formatBuildMessages("core", "node", ["error in file.ts"]);
12
- expect(result).toBe("core (node)\n error in file.ts");
25
+ expect(result).toBe("core (node)\n error in file.ts");
13
26
  });
14
27
 
15
28
  it("splits multiline messages into separate indented lines", () => {
16
29
  const result = formatBuildMessages("core", "node", ["line1\nline2"]);
17
- expect(result).toContain("line1");
18
- expect(result).toContain("line2");
30
+ expect(result).toContain(" line1");
31
+ expect(result).toContain(" line2");
19
32
  });
20
33
 
21
34
  it("handles multiple messages", () => {
22
35
  const result = formatBuildMessages("core", "node", ["err1", "err2"]);
23
36
  expect(result).toContain("core (node)");
24
- expect(result).toContain("err1");
25
- expect(result).toContain("err2");
37
+ expect(result).toContain(" err1");
38
+ expect(result).toContain(" err2");
39
+ });
40
+
41
+ it("preserves empty lines without arrow prefix", () => {
42
+ const result = formatBuildMessages("core", "node", ["line1\n\nline3"]);
43
+ const lines = result.split("\n");
44
+ expect(lines[0]).toBe("core (node)");
45
+ expect(lines[1]).toBe(" line1");
46
+ expect(lines[2]).toBe("");
47
+ expect(lines[3]).toBe(" line3");
26
48
  });
27
49
  });
28
50
 
29
- describe("printErrors", () => {
51
+ describe("formatEsbuildMessages", () => {
52
+ it("빈 배열이면 빈 배열을 반환한다", () => {
53
+ expect(formatEsbuildMessages([], "error")).toEqual([]);
54
+ });
55
+
56
+ it("location이 없는 에러 메시지를 포맷한다", () => {
57
+ const msgs: PartialMessage[] = [{ text: "Some global error" }];
58
+ const result = formatEsbuildMessages(msgs, "error");
59
+ expect(result).toHaveLength(1);
60
+ expect(result[0]).toContain("Some global error");
61
+ expect(result[0]).not.toContain("[ERROR]");
62
+ });
63
+
64
+ it("location이 있으면 파일 경로와 코드 컨텍스트를 포함한다", () => {
65
+ const msgs: PartialMessage[] = [{
66
+ text: "Property 'id' does not exist",
67
+ location: {
68
+ file: "src/app/page.ts",
69
+ line: 10,
70
+ column: 4,
71
+ length: 2,
72
+ lineText: " item.id;",
73
+ },
74
+ }];
75
+ const result = formatEsbuildMessages(msgs, "error");
76
+ expect(result).toHaveLength(1);
77
+ expect(result[0]).toContain("src/app/page.ts");
78
+ expect(result[0]).toContain("Property 'id' does not exist");
79
+ });
80
+
81
+ it("notes를 포함한다", () => {
82
+ const msgs: PartialMessage[] = [{
83
+ text: "Build failed",
84
+ notes: [{ text: "hint message" }],
85
+ }];
86
+ const result = formatEsbuildMessages(msgs, "error");
87
+ expect(result[0]).toContain("hint message");
88
+ });
89
+
90
+ it("warning kind에서 [WARNING] 접두사를 제거한다", () => {
91
+ const msgs: PartialMessage[] = [{ text: "Unused variable" }];
92
+ const result = formatEsbuildMessages(msgs, "warning");
93
+ expect(result[0]).not.toContain("[WARNING]");
94
+ expect(result[0]).toContain("Unused variable");
95
+ });
96
+
97
+ it("여러 메시지를 각각 포맷한다", () => {
98
+ const msgs: PartialMessage[] = [
99
+ { text: "Error A" },
100
+ { text: "Error B" },
101
+ ];
102
+ const result = formatEsbuildMessages(msgs, "error");
103
+ expect(result).toHaveLength(2);
104
+ expect(result[0]).toContain("Error A");
105
+ expect(result[1]).toContain("Error B");
106
+ });
107
+ });
108
+
109
+ describe("printDiagnostics", () => {
30
110
  beforeEach(() => {
31
111
  vi.clearAllMocks();
32
112
  });
@@ -35,7 +115,7 @@ describe("printErrors", () => {
35
115
  const results = new Map<string, BuildResult>([
36
116
  ["core:build", { name: "core", target: "node", type: "build", status: "error", message: "failed" }],
37
117
  ]);
38
- printErrors(results);
118
+ printDiagnostics(results);
39
119
  expect(consola.error).toHaveBeenCalledOnce();
40
120
  });
41
121
 
@@ -43,7 +123,7 @@ describe("printErrors", () => {
43
123
  const results = new Map<string, BuildResult>([
44
124
  ["core:build", { name: "core", target: "node", type: "build", status: "error" }],
45
125
  ]);
46
- printErrors(results);
126
+ printDiagnostics(results);
47
127
  expect(consola.error).toHaveBeenCalledOnce();
48
128
  });
49
129
 
@@ -51,7 +131,7 @@ describe("printErrors", () => {
51
131
  const results = new Map<string, BuildResult>([
52
132
  ["core:build", { name: "core", target: "node", type: "build", status: "success" }],
53
133
  ]);
54
- printErrors(results);
134
+ printDiagnostics(results);
55
135
  expect(consola.error).not.toHaveBeenCalled();
56
136
  });
57
137
 
@@ -61,7 +141,7 @@ describe("printErrors", () => {
61
141
  const results = new Map<string, BuildResult>([
62
142
  ["my-server:lint", { name: "my-server", target: "server", type: "lint", status: "error", message: "no-unused-vars" }],
63
143
  ]);
64
- printErrors(results);
144
+ printDiagnostics(results);
65
145
  const callArg = vi.mocked(consola.error).mock.calls[0][0] as string;
66
146
  expect(callArg).toContain("my-server (lint)");
67
147
  });
@@ -70,7 +150,7 @@ describe("printErrors", () => {
70
150
  const results = new Map<string, BuildResult>([
71
151
  ["core:build", { name: "core-common", target: "node", type: "build", status: "error", message: "build err" }],
72
152
  ]);
73
- printErrors(results);
153
+ printDiagnostics(results);
74
154
  const callArg = vi.mocked(consola.error).mock.calls[0][0] as string;
75
155
  expect(callArg).toContain("core-common (node)");
76
156
  });
@@ -79,8 +159,48 @@ describe("printErrors", () => {
79
159
  const results = new Map<string, BuildResult>([
80
160
  ["core:lint", { name: "core-common", target: "node", type: "lint", status: "success" }],
81
161
  ]);
82
- printErrors(results);
162
+ printDiagnostics(results);
163
+ expect(consola.error).not.toHaveBeenCalled();
164
+ });
165
+
166
+ //#endregion
167
+
168
+ //#region Feature 1.1 Slice 2: printDiagnostics() 경고 출력 확장
169
+
170
+ it("prints warnings with consola.warn", () => {
171
+ const results = new Map<string, BuildResult>([
172
+ ["core:build", { name: "core", target: "node", type: "build", status: "success", warnings: "unused var" }],
173
+ ]);
174
+ printDiagnostics(results);
175
+ expect(consola.error).not.toHaveBeenCalled();
176
+ expect(consola.warn).toHaveBeenCalledOnce();
177
+ const callArg = vi.mocked(consola.warn).mock.calls[0][0] as string;
178
+ expect(callArg).toContain("core (node)");
179
+ expect(callArg).toContain("unused var");
180
+ });
181
+
182
+ it("prints errors before warnings", () => {
183
+ const results = new Map<string, BuildResult>([
184
+ ["core:build", { name: "core", target: "node", type: "build", status: "error", message: "type error" }],
185
+ ["lib:build", { name: "lib", target: "browser", type: "build", status: "success", warnings: "deprecation" }],
186
+ ]);
187
+ printDiagnostics(results);
188
+ expect(consola.error).toHaveBeenCalledOnce();
189
+ expect(consola.warn).toHaveBeenCalledOnce();
190
+
191
+ // error가 warn보다 먼저 호출되었는지 확인
192
+ const errorOrder = vi.mocked(consola.error).mock.invocationCallOrder[0];
193
+ const warnOrder = vi.mocked(consola.warn).mock.invocationCallOrder[0];
194
+ expect(errorOrder).toBeLessThan(warnOrder);
195
+ });
196
+
197
+ it("does not print warnings when there are none", () => {
198
+ const results = new Map<string, BuildResult>([
199
+ ["core:build", { name: "core", target: "node", type: "build", status: "success" }],
200
+ ]);
201
+ printDiagnostics(results);
83
202
  expect(consola.error).not.toHaveBeenCalled();
203
+ expect(consola.warn).not.toHaveBeenCalled();
84
204
  });
85
205
 
86
206
  //#endregion
@@ -32,7 +32,13 @@ describe("watchReplaceDeps onChanged 콜백", () => {
32
32
  tmpDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), "sd-replace-deps-"));
33
33
 
34
34
  // 소스 패키지 생성
35
- const sourceDir = path.join(tmpDir, "source-pkg", "src");
35
+ const sourcePkg = path.join(tmpDir, "source-pkg");
36
+ await fs.promises.mkdir(sourcePkg, { recursive: true });
37
+ await fs.promises.writeFile(
38
+ path.join(sourcePkg, "package.json"),
39
+ JSON.stringify({ name: "@test/pkg", files: ["src"] }),
40
+ );
41
+ const sourceDir = path.join(sourcePkg, "src");
36
42
  await fs.promises.mkdir(sourceDir, { recursive: true });
37
43
  await fs.promises.writeFile(path.join(sourceDir, "index.ts"), "export const a = 1;");
38
44