@simplysm/sd-cli 14.0.42 → 14.0.44

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 (338) 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 +41 -37
  10. package/dist/angular/ngtsc-build-core.d.ts.map +1 -1
  11. package/dist/angular/ngtsc-build-core.js +155 -52
  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.d.ts.map +1 -1
  36. package/dist/commands/publish/version-upgrade.js +16 -13
  37. package/dist/commands/publish/version-upgrade.js.map +1 -1
  38. package/dist/commands/replace-deps.d.ts.map +1 -1
  39. package/dist/commands/replace-deps.js +2 -1
  40. package/dist/commands/replace-deps.js.map +1 -1
  41. package/dist/deps/replace-deps/collect-deps.d.ts.map +1 -1
  42. package/dist/deps/replace-deps/collect-deps.js +5 -2
  43. package/dist/deps/replace-deps/collect-deps.js.map +1 -1
  44. package/dist/deps/replace-deps/replace-deps-resolve.d.ts.map +1 -1
  45. package/dist/deps/replace-deps/replace-deps-resolve.js +6 -7
  46. package/dist/deps/replace-deps/replace-deps-resolve.js.map +1 -1
  47. package/dist/deps/replace-deps/replace-deps.d.ts +21 -3
  48. package/dist/deps/replace-deps/replace-deps.d.ts.map +1 -1
  49. package/dist/deps/replace-deps/replace-deps.js +175 -66
  50. package/dist/deps/replace-deps/replace-deps.js.map +1 -1
  51. package/dist/electron/electron.js +7 -7
  52. package/dist/electron/electron.js.map +1 -1
  53. package/dist/engines/BaseEngine.d.ts.map +1 -1
  54. package/dist/engines/BaseEngine.js +2 -5
  55. package/dist/engines/BaseEngine.js.map +1 -1
  56. package/dist/engines/EsbuildClientEngine.d.ts.map +1 -1
  57. package/dist/engines/EsbuildClientEngine.js +16 -9
  58. package/dist/engines/EsbuildClientEngine.js.map +1 -1
  59. package/dist/engines/NgtscEngine.d.ts +4 -4
  60. package/dist/engines/NgtscEngine.d.ts.map +1 -1
  61. package/dist/engines/NgtscEngine.js +5 -5
  62. package/dist/engines/NgtscEngine.js.map +1 -1
  63. package/dist/engines/TscEngine.d.ts.map +1 -1
  64. package/dist/engines/TscEngine.js +0 -2
  65. package/dist/engines/TscEngine.js.map +1 -1
  66. package/dist/engines/types.d.ts +2 -0
  67. package/dist/engines/types.d.ts.map +1 -1
  68. package/dist/esbuild/esbuild-angular-compiler-plugin.d.ts +36 -0
  69. package/dist/esbuild/esbuild-angular-compiler-plugin.d.ts.map +1 -0
  70. package/dist/esbuild/esbuild-angular-compiler-plugin.js +464 -0
  71. package/dist/esbuild/esbuild-angular-compiler-plugin.js.map +1 -0
  72. package/dist/esbuild/esbuild-client-config.d.ts +8 -2
  73. package/dist/esbuild/esbuild-client-config.d.ts.map +1 -1
  74. package/dist/esbuild/esbuild-client-config.js +48 -33
  75. package/dist/esbuild/esbuild-client-config.js.map +1 -1
  76. package/dist/esbuild/esbuild-postcss-plugin.d.ts.map +1 -1
  77. package/dist/esbuild/esbuild-postcss-plugin.js +9 -6
  78. package/dist/esbuild/esbuild-postcss-plugin.js.map +1 -1
  79. package/dist/esbuild/esbuild-tsc-plugin.d.ts +4 -1
  80. package/dist/esbuild/esbuild-tsc-plugin.d.ts.map +1 -1
  81. package/dist/esbuild/esbuild-tsc-plugin.js +27 -23
  82. package/dist/esbuild/esbuild-tsc-plugin.js.map +1 -1
  83. package/dist/esbuild/file-reference-tracker.d.ts +24 -0
  84. package/dist/esbuild/file-reference-tracker.d.ts.map +1 -0
  85. package/dist/esbuild/file-reference-tracker.js +57 -0
  86. package/dist/esbuild/file-reference-tracker.js.map +1 -0
  87. package/dist/esbuild/lmdb-cache-store.d.ts +18 -0
  88. package/dist/esbuild/lmdb-cache-store.d.ts.map +1 -0
  89. package/dist/esbuild/lmdb-cache-store.js +41 -0
  90. package/dist/esbuild/lmdb-cache-store.js.map +1 -0
  91. package/dist/esbuild/load-result-cache.d.ts +17 -0
  92. package/dist/esbuild/load-result-cache.d.ts.map +1 -0
  93. package/dist/esbuild/load-result-cache.js +61 -0
  94. package/dist/esbuild/load-result-cache.js.map +1 -0
  95. package/dist/index.d.ts +3 -0
  96. package/dist/index.d.ts.map +1 -1
  97. package/dist/index.js +2 -0
  98. package/dist/index.js.map +1 -1
  99. package/dist/lint/lint-core.js +7 -7
  100. package/dist/lint/lint-core.js.map +1 -1
  101. package/dist/orchestrators/BaseOrchestrator.js +2 -2
  102. package/dist/orchestrators/BaseOrchestrator.js.map +1 -1
  103. package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
  104. package/dist/orchestrators/BuildOrchestrator.js +5 -19
  105. package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
  106. package/dist/orchestrators/DevOrchestrator.js +5 -5
  107. package/dist/orchestrators/DevOrchestrator.js.map +1 -1
  108. package/dist/orchestrators/WatchOrchestrator.js +6 -6
  109. package/dist/orchestrators/WatchOrchestrator.js.map +1 -1
  110. package/dist/runtime/ResultCollector.d.ts +1 -0
  111. package/dist/runtime/ResultCollector.d.ts.map +1 -1
  112. package/dist/runtime/ResultCollector.js.map +1 -1
  113. package/dist/runtime/engine-watch-events.d.ts.map +1 -1
  114. package/dist/runtime/engine-watch-events.js +3 -0
  115. package/dist/runtime/engine-watch-events.js.map +1 -1
  116. package/dist/runtime/rebuild-manager.js +1 -1
  117. package/dist/runtime/rebuild-manager.js.map +1 -1
  118. package/dist/runtime/worker-utils.js +1 -1
  119. package/dist/runtime/worker-utils.js.map +1 -1
  120. package/dist/sd-cli-entry.d.ts.map +1 -1
  121. package/dist/sd-cli-entry.js +4 -3
  122. package/dist/sd-cli-entry.js.map +1 -1
  123. package/dist/sd-cli.js +3 -3
  124. package/dist/sd-cli.js.map +1 -1
  125. package/dist/ts-compiler/SdTsCompiler.d.ts +39 -0
  126. package/dist/ts-compiler/SdTsCompiler.d.ts.map +1 -0
  127. package/dist/ts-compiler/SdTsCompiler.js +593 -0
  128. package/dist/ts-compiler/SdTsCompiler.js.map +1 -0
  129. package/dist/ts-compiler/sd-ts-compiler-options.d.ts +40 -0
  130. package/dist/ts-compiler/sd-ts-compiler-options.d.ts.map +1 -0
  131. package/dist/ts-compiler/sd-ts-compiler-options.js +2 -0
  132. package/dist/ts-compiler/sd-ts-compiler-options.js.map +1 -0
  133. package/dist/ts-compiler/sd-ts-compiler-result.d.ts +34 -0
  134. package/dist/ts-compiler/sd-ts-compiler-result.d.ts.map +1 -0
  135. package/dist/ts-compiler/sd-ts-compiler-result.js +2 -0
  136. package/dist/ts-compiler/sd-ts-compiler-result.js.map +1 -0
  137. package/dist/utils/copy-public.d.ts +6 -4
  138. package/dist/utils/copy-public.d.ts.map +1 -1
  139. package/dist/utils/copy-public.js +9 -7
  140. package/dist/utils/copy-public.js.map +1 -1
  141. package/dist/utils/diagnostic-utils.d.ts +2 -3
  142. package/dist/utils/diagnostic-utils.d.ts.map +1 -1
  143. package/dist/utils/diagnostic-utils.js +8 -9
  144. package/dist/utils/diagnostic-utils.js.map +1 -1
  145. package/dist/utils/output-utils.d.ts +8 -2
  146. package/dist/utils/output-utils.d.ts.map +1 -1
  147. package/dist/utils/output-utils.js +32 -8
  148. package/dist/utils/output-utils.js.map +1 -1
  149. package/dist/workers/client.worker.d.ts +1 -1
  150. package/dist/workers/client.worker.d.ts.map +1 -1
  151. package/dist/workers/client.worker.js +115 -110
  152. package/dist/workers/client.worker.js.map +1 -1
  153. package/dist/workers/incremental-mtime-tracker.d.ts +13 -0
  154. package/dist/workers/incremental-mtime-tracker.d.ts.map +1 -0
  155. package/dist/workers/incremental-mtime-tracker.js +65 -0
  156. package/dist/workers/incremental-mtime-tracker.js.map +1 -0
  157. package/dist/workers/library-build.worker.d.ts +0 -2
  158. package/dist/workers/library-build.worker.d.ts.map +1 -1
  159. package/dist/workers/library-build.worker.js +169 -70
  160. package/dist/workers/library-build.worker.js.map +1 -1
  161. package/dist/workers/server-build.worker.d.ts.map +1 -1
  162. package/dist/workers/server-build.worker.js +30 -57
  163. package/dist/workers/server-build.worker.js.map +1 -1
  164. package/dist/workers/server-esbuild-context.d.ts +7 -0
  165. package/dist/workers/server-esbuild-context.d.ts.map +1 -1
  166. package/dist/workers/server-esbuild-context.js +11 -2
  167. package/dist/workers/server-esbuild-context.js.map +1 -1
  168. package/package.json +5 -4
  169. package/src/angular/angular-compiler.ts +0 -502
  170. package/src/angular/hmr-candidates.ts +295 -0
  171. package/src/angular/ngtsc-build-core.ts +192 -91
  172. package/src/angular/vite-angular-plugin.ts +71 -65
  173. package/src/angular/web-worker-transformer.ts +117 -0
  174. package/src/capacitor/capacitor.ts +6 -4
  175. package/src/commands/check.ts +17 -76
  176. package/src/commands/publish/deployment-phase.ts +11 -7
  177. package/src/commands/publish/npm-publisher.ts +1 -1
  178. package/src/commands/publish/publish-command.ts +1 -1
  179. package/src/commands/publish/version-upgrade.ts +44 -35
  180. package/src/commands/replace-deps.ts +3 -1
  181. package/src/deps/replace-deps/collect-deps.ts +4 -2
  182. package/src/deps/replace-deps/replace-deps-resolve.ts +12 -7
  183. package/src/deps/replace-deps/replace-deps.ts +191 -69
  184. package/src/electron/electron.ts +7 -7
  185. package/src/engines/BaseEngine.ts +2 -6
  186. package/src/engines/EsbuildClientEngine.ts +16 -10
  187. package/src/engines/NgtscEngine.ts +7 -7
  188. package/src/engines/TscEngine.ts +0 -2
  189. package/src/engines/types.ts +2 -0
  190. package/src/esbuild/esbuild-angular-compiler-plugin.ts +647 -0
  191. package/src/esbuild/esbuild-client-config.ts +57 -41
  192. package/src/esbuild/esbuild-postcss-plugin.ts +9 -6
  193. package/src/esbuild/esbuild-tsc-plugin.ts +33 -23
  194. package/src/esbuild/file-reference-tracker.ts +61 -0
  195. package/src/esbuild/lmdb-cache-store.ts +46 -0
  196. package/src/esbuild/load-result-cache.ts +85 -0
  197. package/src/index.ts +5 -0
  198. package/src/lint/lint-core.ts +7 -7
  199. package/src/orchestrators/BaseOrchestrator.ts +2 -2
  200. package/src/orchestrators/BuildOrchestrator.ts +5 -24
  201. package/src/orchestrators/DevOrchestrator.ts +5 -5
  202. package/src/orchestrators/WatchOrchestrator.ts +6 -6
  203. package/src/runtime/ResultCollector.ts +1 -0
  204. package/src/runtime/engine-watch-events.ts +3 -0
  205. package/src/runtime/rebuild-manager.ts +1 -1
  206. package/src/runtime/worker-utils.ts +1 -1
  207. package/src/sd-cli-entry.ts +5 -3
  208. package/src/sd-cli.ts +4 -4
  209. package/src/ts-compiler/SdTsCompiler.ts +815 -0
  210. package/src/ts-compiler/sd-ts-compiler-options.ts +46 -0
  211. package/src/ts-compiler/sd-ts-compiler-result.ts +34 -0
  212. package/src/utils/copy-public.ts +9 -6
  213. package/src/utils/diagnostic-utils.ts +8 -9
  214. package/src/utils/output-utils.ts +38 -8
  215. package/src/workers/client.worker.ts +141 -126
  216. package/src/workers/incremental-mtime-tracker.ts +68 -0
  217. package/src/workers/library-build.worker.ts +214 -75
  218. package/src/workers/server-build.worker.ts +31 -61
  219. package/src/workers/server-esbuild-context.ts +14 -2
  220. package/tests/angular/fixtures/packages/basic-app/dist/styles.css +3 -0
  221. package/tests/angular/fixtures/packages/basic-app/scss/styles.scss +5 -0
  222. package/tests/angular/ngtsc-build-core.acc.spec.ts +210 -0
  223. package/tests/angular/ngtsc-build-core.spec.ts +52 -0
  224. package/tests/angular/vite-angular-plugin-sdtscompiler.verify.md +13 -0
  225. package/tests/angular/web-worker-transformer.spec.ts +154 -0
  226. package/tests/capacitor/capacitor-build.spec.ts +1 -1
  227. package/tests/capacitor/capacitor-icon.spec.ts +1 -1
  228. package/tests/capacitor/capacitor-init.spec.ts +1 -1
  229. package/tests/commands/check.spec.ts +90 -104
  230. package/tests/commands/publish.spec.ts +12 -4
  231. package/tests/commands/slice3-severity-cleanup.verify.md +12 -0
  232. package/tests/commands/version-upgrade.acc.spec.ts +210 -0
  233. package/tests/commands/version-upgrade.spec.ts +148 -0
  234. package/tests/deps/replace-deps/collect-deps.acc.spec.ts +62 -0
  235. package/tests/deps/replace-deps/collect-deps.spec.ts +49 -0
  236. package/tests/deps/replace-deps/replace-deps-filter.spec.ts +103 -0
  237. package/tests/deps/replace-deps/replace-deps-perf.verify.md +15 -0
  238. package/tests/deps/replace-deps/replace-deps-resolve.acc.spec.ts +124 -0
  239. package/tests/deps/replace-deps/replace-deps-setup.acc.spec.ts +156 -0
  240. package/tests/electron/electron.spec.ts +4 -1
  241. package/tests/engines/engine-adapter-isolation.spec.ts +5 -6
  242. package/tests/engines/engine-duplicate-output-removal.verify.md +10 -0
  243. package/tests/engines/esbuild-client-engine.acc.spec.ts +79 -0
  244. package/tests/engines/esbuild-client-engine.spec.ts +73 -3
  245. package/tests/esbuild/esbuild-angular-compiler-plugin-hmr.verify.md +23 -0
  246. package/tests/esbuild/esbuild-angular-compiler-plugin-onload.verify.md +21 -0
  247. package/tests/esbuild/esbuild-angular-compiler-plugin-onstart-extraction.verify.md +16 -0
  248. package/tests/esbuild/esbuild-angular-compiler-plugin-sdtscompiler.verify.md +15 -0
  249. package/tests/esbuild/esbuild-angular-compiler-plugin-stylesheet.verify.md +31 -0
  250. package/tests/esbuild/esbuild-angular-compiler-plugin-worker.verify.md +31 -0
  251. package/tests/esbuild/esbuild-angular-compiler-plugin.spec.ts +397 -0
  252. package/tests/esbuild/esbuild-angular-compiler-plugin.verify.md +21 -0
  253. package/tests/esbuild/esbuild-postcss-plugin-chunking.verify.md +17 -0
  254. package/tests/esbuild/esbuild-postcss-plugin.acc.spec.ts +152 -0
  255. package/tests/esbuild/esbuild-tsc-plugin-imports.verify.md +13 -0
  256. package/tests/esbuild/esbuild-tsc-plugin.acc.spec.ts +56 -111
  257. package/tests/esbuild/esbuild-tsc-plugin.spec.ts +116 -52
  258. package/tests/esbuild/file-reference-tracker.spec.ts +99 -0
  259. package/tests/esbuild/lmdb-cache-store.spec.ts +58 -0
  260. package/tests/esbuild/load-result-cache.acc.spec.ts +55 -0
  261. package/tests/esbuild/load-result-cache.spec.ts +133 -0
  262. package/tests/orchestrators/build-orchestrator.spec.ts +4 -3
  263. package/tests/orchestrators/dev-orchestrator.spec.ts +5 -5
  264. package/tests/orchestrators/slice1-stdout-to-consola.verify.md +10 -0
  265. package/tests/orchestrators/typecheck-orchestrator.spec.ts +1 -1
  266. package/tests/orchestrators/watch-orchestrator.spec.ts +7 -7
  267. package/tests/runtime/result-collector.spec.ts +64 -0
  268. package/tests/sd-cli-entry.spec.ts +3 -4
  269. package/tests/sd-cli-log-tag.verify.md +11 -0
  270. package/tests/ts-compiler/SdTsCompiler-affected-files.verify.md +8 -0
  271. package/tests/ts-compiler/SdTsCompiler-diagnostics.verify.md +12 -0
  272. package/tests/ts-compiler/SdTsCompiler-emit.verify.md +9 -0
  273. package/tests/ts-compiler/SdTsCompiler.acc.spec.ts +603 -0
  274. package/tests/ts-compiler/SdTsCompiler.spec.ts +265 -0
  275. package/tests/ts-compiler/SdTsCompiler.verify.md +41 -0
  276. package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck-browser.tsbuildinfo +1 -0
  277. package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck-node.tsbuildinfo +1 -0
  278. package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck.tsbuildinfo +1 -0
  279. package/tests/ts-compiler/fixtures/non-angular-pkg/src/index.ts +3 -0
  280. package/tests/ts-compiler/fixtures/non-angular-pkg/src/util.ts +3 -0
  281. package/tests/ts-compiler/fixtures/non-angular-pkg/tests/sample.test-file.ts +3 -0
  282. package/tests/ts-compiler/fixtures/non-angular-pkg/tsconfig.json +12 -0
  283. package/tests/ts-compiler/scss-lint-integration.verify.md +14 -0
  284. package/tests/utils/angular-build.spec.ts +1 -1
  285. package/tests/utils/copy-public-outdir.verify.md +8 -0
  286. package/tests/utils/copy-public.acc.spec.ts +52 -0
  287. package/tests/utils/copy-public.spec.ts +56 -0
  288. package/tests/utils/diagnostic-utils.spec.ts +24 -15
  289. package/tests/utils/engine-watch-events.acc.spec.ts +59 -0
  290. package/tests/utils/engine-watch-events.spec.ts +58 -0
  291. package/tests/utils/esbuild-client-config-integration.verify.md +9 -0
  292. package/tests/utils/esbuild-client-config.acc.spec.ts +45 -61
  293. package/tests/utils/esbuild-client-config.spec.ts +70 -52
  294. package/tests/utils/ngtsc-build-core-write-emit.spec.ts +136 -12
  295. package/tests/utils/ngtsc-build-core.spec.ts +1 -44
  296. package/tests/utils/output-utils.spec.ts +133 -13
  297. package/tests/utils/replace-deps-watch.acc.spec.ts +7 -1
  298. package/tests/utils/replace-deps-watch.spec.ts +57 -1
  299. package/tests/utils/worker-utils.spec.ts +8 -2
  300. package/tests/workers/client-worker-initial-build-error.verify.md +2 -3
  301. package/tests/workers/client-worker-initial-build-warnings.verify.md +7 -0
  302. package/tests/workers/client-worker-mtime-incremental.verify.md +10 -0
  303. package/tests/workers/client-worker-refactor.verify.md +22 -0
  304. package/tests/workers/client-worker-ts-cache-invalidation.verify.md +12 -0
  305. package/tests/workers/client-worker.acc.spec.ts +6 -3
  306. package/tests/workers/incremental-mtime-tracker.acc.spec.ts +144 -0
  307. package/tests/workers/incremental-mtime-tracker.spec.ts +102 -0
  308. package/tests/workers/library-build-lint.spec.ts +40 -45
  309. package/tests/workers/library-build-worker.spec.ts +298 -40
  310. package/tests/workers/server-build-lint.spec.ts +59 -45
  311. package/tests/workers/server-build-worker.spec.ts +63 -24
  312. package/tests/workers/server-esbuild-context.acc.spec.ts +2 -0
  313. package/tests/workers/server-esbuild-context.spec.ts +2 -0
  314. package/tests/workers/server-runtime-worker.spec.ts +1 -1
  315. package/tests/workers/shared-worker-lifecycle.acc.spec.ts +1 -1
  316. package/dist/angular/angular-build-pipeline.d.ts +0 -97
  317. package/dist/angular/angular-build-pipeline.d.ts.map +0 -1
  318. package/dist/angular/angular-build-pipeline.js +0 -285
  319. package/dist/angular/angular-build-pipeline.js.map +0 -1
  320. package/dist/utils/tsc-build.d.ts +0 -51
  321. package/dist/utils/tsc-build.d.ts.map +0 -1
  322. package/dist/utils/tsc-build.js +0 -156
  323. package/dist/utils/tsc-build.js.map +0 -1
  324. package/dist/workers/ngtsc-build.worker.d.ts +0 -23
  325. package/dist/workers/ngtsc-build.worker.d.ts.map +0 -1
  326. package/dist/workers/ngtsc-build.worker.js +0 -267
  327. package/dist/workers/ngtsc-build.worker.js.map +0 -1
  328. package/src/angular/angular-build-pipeline.ts +0 -406
  329. package/src/utils/tsc-build.ts +0 -226
  330. package/src/workers/ngtsc-build.worker.ts +0 -351
  331. package/tests/angular/angular-build-pipeline.spec.ts +0 -247
  332. package/tests/angular/angular-compiler-aot.acc.spec.ts +0 -68
  333. package/tests/angular/angular-compiler-aot.spec.ts +0 -80
  334. package/tests/utils/angular-compiler-emit.spec.ts +0 -666
  335. package/tests/utils/angular-compiler.spec.ts +0 -707
  336. package/tests/utils/tsc-build.spec.ts +0 -527
  337. package/tests/workers/ngtsc-build-lint.spec.ts +0 -141
  338. package/tests/workers/ngtsc-build-worker.spec.ts +0 -199
@@ -1,10 +1,21 @@
1
1
  import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { consola } from "consola";
3
+
4
+ const mockLogger = {
5
+ debug: vi.fn(),
6
+ info: vi.fn(),
7
+ warn: vi.fn(),
8
+ error: vi.fn(),
9
+ start: vi.fn(),
10
+ success: vi.fn(),
11
+ };
12
+
13
+ vi.spyOn(consola, "withTag").mockReturnValue(mockLogger as any);
2
14
 
3
15
  const mocks = vi.hoisted(() => ({
4
16
  executeTypecheck: vi.fn(),
5
17
  executeLint: vi.fn(),
6
18
  runLintInWorker: vi.fn(),
7
- execa: vi.fn(),
8
19
  loadSdConfig: vi.fn(),
9
20
  discoverWorkspacePackages: vi.fn(),
10
21
  }));
@@ -25,13 +36,6 @@ vi.mock("../../src/utils/sd-config", () => ({
25
36
  loadSdConfig: mocks.loadSdConfig,
26
37
  }));
27
38
 
28
- vi.mock("@simplysm/core-node", () => ({
29
- cpx: {
30
- spawn: mocks.execa,
31
- spawnSync: vi.fn().mockReturnValue({ stdout: "", stderr: "", exitCode: 0 }),
32
- },
33
- }));
34
-
35
39
  vi.mock("../../src/utils/package-utils", async (importOriginal) => {
36
40
  const actual = await importOriginal<typeof import("../../src/utils/package-utils")>();
37
41
  return {
@@ -42,20 +46,21 @@ vi.mock("../../src/utils/package-utils", async (importOriginal) => {
42
46
 
43
47
  const { runCheck } = await import("../../src/commands/check");
44
48
 
49
+ /**
50
+ * Collects all calls to the given mock function's first argument into an array,
51
+ * preserving call order for sequential assertions.
52
+ */
53
+ function collectArgs(fn: ReturnType<typeof vi.fn>): string[] {
54
+ return fn.mock.calls.map((call) => String(call[0]));
55
+ }
56
+
45
57
  describe("runCheck", () => {
46
58
  let savedExitCode: typeof process.exitCode;
47
- let writeSpy: ReturnType<typeof vi.spyOn>;
48
- let stdoutOutput: string;
49
59
 
50
60
  beforeEach(() => {
51
61
  vi.clearAllMocks();
52
62
  savedExitCode = process.exitCode;
53
63
  process.exitCode = undefined;
54
- stdoutOutput = "";
55
- writeSpy = vi.spyOn(process.stdout, "write").mockImplementation((chunk: unknown) => {
56
- stdoutOutput += String(chunk);
57
- return true;
58
- });
59
64
 
60
65
  // Default: workspace packages
61
66
  mocks.discoverWorkspacePackages.mockReturnValue(
@@ -89,41 +94,22 @@ describe("runCheck", () => {
89
94
  mocks.runLintInWorker.mockResolvedValue({
90
95
  success: true, errorCount: 0, warningCount: 0, formattedOutput: "",
91
96
  });
92
- mocks.execa.mockResolvedValue({
93
- stdout: "Tests 1 passed", stderr: "", exitCode: 0,
94
- });
95
97
  });
96
98
 
97
99
  afterEach(() => {
98
100
  process.exitCode = savedExitCode;
99
- writeSpy.mockRestore();
100
101
  });
101
102
 
102
- it("runs typecheck+lint and test", async () => {
103
- await runCheck({ targets: [], types: ["typecheck", "lint", "test"], fix: false });
104
-
105
- expect(stdoutOutput).toContain("TYPECHECK");
106
- expect(stdoutOutput).toContain("TEST");
107
- });
103
+ it("outputs success sections in TYPECHECK → LINT order via logger.success", async () => {
104
+ await runCheck({ targets: [], types: ["typecheck", "lint"], fix: false });
108
105
 
109
- it("outputs results in TYPECHECK → LINT → TEST → 요약 order", async () => {
110
- await runCheck({ targets: [], types: ["typecheck", "lint", "test"], fix: false });
111
-
112
- const tcIdx = stdoutOutput.indexOf("TYPECHECK");
113
- const lintIdx = stdoutOutput.indexOf("LINT");
114
- const testIdx = stdoutOutput.indexOf("TEST");
115
- const summaryIdx = stdoutOutput.indexOf("요약");
106
+ const successArgs = collectArgs(mockLogger.success);
107
+ const tcIdx = successArgs.findIndex((a) => a.includes("TYPECHECK"));
108
+ const lintIdx = successArgs.findIndex((a) => a.includes("LINT"));
116
109
 
110
+ expect(tcIdx).toBeGreaterThanOrEqual(0);
111
+ expect(lintIdx).toBeGreaterThanOrEqual(0);
117
112
  expect(tcIdx).toBeLessThan(lintIdx);
118
- expect(lintIdx).toBeLessThan(testIdx);
119
- expect(testIdx).toBeLessThan(summaryIdx);
120
- });
121
-
122
- it("runs only specified check types", async () => {
123
- await runCheck({ targets: [], types: ["test"], fix: false });
124
-
125
- expect(stdoutOutput).not.toContain("TYPECHECK");
126
- expect(stdoutOutput).toContain("TEST");
127
113
  });
128
114
 
129
115
  it("sets exitCode 1 when typecheck fails", async () => {
@@ -133,35 +119,52 @@ describe("runCheck", () => {
133
119
  scriptsPackagePaths: [],
134
120
  });
135
121
 
136
- await runCheck({ targets: [], types: ["typecheck", "lint", "test"], fix: false });
122
+ await runCheck({ targets: [], types: ["typecheck", "lint"], fix: false });
137
123
 
138
124
  expect(process.exitCode).toBe(1);
139
125
  });
140
126
 
141
- it("sets exitCode to 1 when lint fails", async () => {
142
- mocks.executeLint.mockResolvedValue({
143
- success: false, errorCount: 1, warningCount: 0, formattedOutput: "lint errors",
127
+ it("outputs failed section via logger.error with formattedOutput", async () => {
128
+ mocks.executeTypecheck.mockResolvedValue({
129
+ success: false, errorCount: 2, warningCount: 0, formattedOutput: "type errors",
130
+ lint: { success: true, errorCount: 0, warningCount: 0, formattedOutput: "" },
131
+ scriptsPackagePaths: [],
144
132
  });
145
133
 
146
- await runCheck({ targets: [], types: ["lint"], fix: false });
134
+ await runCheck({ targets: [], types: ["typecheck", "lint"], fix: false });
147
135
 
148
- expect(process.exitCode).toBe(1);
136
+ const errorArgs = collectArgs(mockLogger.error);
137
+ expect(errorArgs.some((a) => a.includes("TYPECHECK"))).toBe(true);
138
+ expect(errorArgs.some((a) => a.includes("type errors"))).toBe(true);
139
+ });
140
+
141
+ it("outputs success summary via logger.success when all pass", async () => {
142
+ await runCheck({ targets: [], types: ["typecheck", "lint"], fix: false });
143
+
144
+ const successArgs = collectArgs(mockLogger.success);
145
+ expect(successArgs.some((a) => a.includes("전체 통과"))).toBe(true);
149
146
  });
150
147
 
151
- it("sets exitCode 1 when test fails", async () => {
152
- mocks.execa.mockResolvedValue({
153
- stdout: "3 tests failed", stderr: "", exitCode: 1,
148
+ it("outputs failure summary via logger.error when any fails", async () => {
149
+ mocks.executeTypecheck.mockResolvedValue({
150
+ success: false, errorCount: 1, warningCount: 0, formattedOutput: "err",
151
+ lint: { success: true, errorCount: 0, warningCount: 0, formattedOutput: "" },
152
+ scriptsPackagePaths: [],
154
153
  });
155
154
 
156
- await runCheck({ targets: [], types: ["test"], fix: false });
155
+ await runCheck({ targets: [], types: ["typecheck", "lint"], fix: false });
157
156
 
158
- expect(process.exitCode).toBe(1);
157
+ const errorArgs = collectArgs(mockLogger.error);
158
+ expect(errorArgs.some((a) => a.includes("실패"))).toBe(true);
159
+ expect(errorArgs.some((a) => a.includes("합계"))).toBe(true);
159
160
  });
160
161
 
161
- it("handles vitest execution error gracefully", async () => {
162
- mocks.execa.mockRejectedValue(new Error("vitest not found"));
162
+ it("sets exitCode to 1 when lint fails", async () => {
163
+ mocks.executeLint.mockResolvedValue({
164
+ success: false, errorCount: 1, warningCount: 0, formattedOutput: "lint errors",
165
+ });
163
166
 
164
- await runCheck({ targets: [], types: ["test"], fix: false });
167
+ await runCheck({ targets: [], types: ["lint"], fix: false });
165
168
 
166
169
  expect(process.exitCode).toBe(1);
167
170
  });
@@ -179,51 +182,45 @@ describe("runCheck", () => {
179
182
  it("resolves package target to packages/ path", async () => {
180
183
  await runCheck({ targets: ["core-node"], types: ["typecheck"], fix: false });
181
184
 
182
- expect(stdoutOutput).toContain("TYPECHECK");
185
+ const successArgs = collectArgs(mockLogger.success);
186
+ expect(successArgs.some((a) => a.includes("TYPECHECK"))).toBe(true);
183
187
  expect(process.exitCode).toBeUndefined();
184
188
  });
185
189
 
186
190
  it("resolves test directory target to tests/ path", async () => {
187
191
  await runCheck({ targets: ["orm"], types: ["typecheck"], fix: false });
188
192
 
189
- expect(stdoutOutput).toContain("TYPECHECK");
193
+ const successArgs = collectArgs(mockLogger.success);
194
+ expect(successArgs.some((a) => a.includes("TYPECHECK"))).toBe(true);
190
195
  expect(process.exitCode).toBeUndefined();
191
196
  });
192
197
 
193
198
  it("resolves mixed targets to correct paths", async () => {
194
199
  await runCheck({ targets: ["core-node", "orm"], types: ["typecheck"], fix: false });
195
200
 
196
- expect(stdoutOutput).toContain("TYPECHECK");
201
+ const successArgs = collectArgs(mockLogger.success);
202
+ expect(successArgs.some((a) => a.includes("TYPECHECK"))).toBe(true);
197
203
  expect(process.exitCode).toBeUndefined();
198
204
  });
199
205
 
200
206
  it("resolves lint target to correct path", async () => {
201
207
  await runCheck({ targets: ["orm"], types: ["lint"], fix: false });
202
208
 
203
- expect(stdoutOutput).toContain("LINT");
209
+ const successArgs = collectArgs(mockLogger.success);
210
+ expect(successArgs.some((a) => a.includes("LINT"))).toBe(true);
204
211
  expect(process.exitCode).toBeUndefined();
205
212
  });
206
213
 
207
- it("passes resolved paths to vitest", async () => {
208
- await runCheck({ targets: ["orm"], types: ["test"], fix: false });
209
-
210
- expect(mocks.execa).toHaveBeenCalledWith(
211
- "pnpm",
212
- ["vitest", "tests/orm", "--run"],
213
- expect.any(Object),
214
- );
215
- });
216
-
217
214
  it("passes empty targets for all when no targets specified", async () => {
218
215
  await runCheck({ targets: [], types: ["typecheck"], fix: false });
219
216
 
220
- expect(stdoutOutput).toContain("TYPECHECK");
217
+ const successArgs = collectArgs(mockLogger.success);
218
+ expect(successArgs.some((a) => a.includes("TYPECHECK"))).toBe(true);
221
219
  expect(process.exitCode).toBeUndefined();
222
220
  });
223
221
 
224
222
  describe("lint via engine integration", () => {
225
223
  beforeEach(() => {
226
- // Default: executeTypecheck returns lint result and scriptsPackagePaths
227
224
  mocks.executeTypecheck.mockResolvedValue({
228
225
  success: true, errorCount: 0, warningCount: 0, formattedOutput: "",
229
226
  lint: { success: true, errorCount: 0, warningCount: 0, formattedOutput: "" },
@@ -231,15 +228,14 @@ describe("runCheck", () => {
231
228
  });
232
229
  });
233
230
 
234
- // Scenario: typecheck+lint 요청 시 TYPECHECK과 LINT 섹션이 출력된다
235
231
  it("outputs TYPECHECK and LINT sections when both are requested", async () => {
236
232
  await runCheck({ targets: [], types: ["typecheck", "lint"], fix: false });
237
233
 
238
- expect(stdoutOutput).toContain("TYPECHECK");
239
- expect(stdoutOutput).toContain("LINT");
234
+ const successArgs = collectArgs(mockLogger.success);
235
+ expect(successArgs.some((a) => a.includes("TYPECHECK"))).toBe(true);
236
+ expect(successArgs.some((a) => a.includes("LINT"))).toBe(true);
240
237
  });
241
238
 
242
- // Scenario: lint 실패 시 exitCode 설정
243
239
  it("sets exitCode 1 when engine lint fails", async () => {
244
240
  mocks.executeTypecheck.mockResolvedValue({
245
241
  success: true, errorCount: 0, warningCount: 0, formattedOutput: "",
@@ -252,7 +248,6 @@ describe("runCheck", () => {
252
248
  expect(process.exitCode).toBe(1);
253
249
  });
254
250
 
255
- // Scenario: scripts 패키지 포함 시 lint가 성공한다
256
251
  it("succeeds when scriptsPackagePaths is non-empty", async () => {
257
252
  mocks.executeTypecheck.mockResolvedValue({
258
253
  success: true, errorCount: 0, warningCount: 0, formattedOutput: "",
@@ -265,69 +260,62 @@ describe("runCheck", () => {
265
260
 
266
261
  await runCheck({ targets: [], types: ["typecheck", "lint"], fix: false });
267
262
 
268
- expect(stdoutOutput).toContain("LINT");
263
+ const successArgs = collectArgs(mockLogger.success);
264
+ expect(successArgs.some((a) => a.includes("LINT"))).toBe(true);
269
265
  expect(process.exitCode).toBeUndefined();
270
266
  });
271
267
  });
272
268
 
273
269
  describe("lint-only path", () => {
274
- // Scenario: lint만 요청 시 LINT 섹션만 출력된다
275
270
  it("outputs LINT section when only lint type is requested", async () => {
276
271
  await runCheck({ targets: [], types: ["lint"], fix: false });
277
272
 
278
- expect(stdoutOutput).toContain("LINT");
279
- expect(stdoutOutput).not.toContain("TYPECHECK");
273
+ const successArgs = collectArgs(mockLogger.success);
274
+ expect(successArgs.some((a) => a.includes("LINT"))).toBe(true);
275
+ const allArgs = [...collectArgs(mockLogger.success), ...collectArgs(mockLogger.error)];
276
+ expect(allArgs.some((a) => a.includes("TYPECHECK"))).toBe(false);
280
277
  });
281
278
 
282
- // Scenario: lint,test 요청 시 LINT과 TEST 섹션 출력 (TYPECHECK 없음)
283
- it("outputs LINT and TEST sections when lint,test are requested", async () => {
284
- await runCheck({ targets: [], types: ["lint", "test"], fix: false });
285
-
286
- expect(stdoutOutput).toContain("LINT");
287
- expect(stdoutOutput).toContain("TEST");
288
- expect(stdoutOutput).not.toContain("TYPECHECK");
289
- });
290
-
291
- // Scenario: scripts 패키지 포함 전체 lint
292
279
  it("handles all packages via lint including scripts", async () => {
293
280
  mocks.discoverWorkspacePackages.mockReturnValue(
294
281
  new Map([
295
282
  ["core-common", "packages/core-common"],
296
- ["sd-claude", "packages/sd-claude"], // scripts package
283
+ ["sd-claude", "packages/sd-claude"],
297
284
  ]),
298
285
  );
299
286
 
300
287
  await runCheck({ targets: [], types: ["lint"], fix: false });
301
288
 
302
- expect(stdoutOutput).toContain("LINT");
303
- expect(stdoutOutput).not.toContain("TYPECHECK");
289
+ const successArgs = collectArgs(mockLogger.success);
290
+ expect(successArgs.some((a) => a.includes("LINT"))).toBe(true);
291
+ const allArgs = [...collectArgs(mockLogger.success), ...collectArgs(mockLogger.error)];
292
+ expect(allArgs.some((a) => a.includes("TYPECHECK"))).toBe(false);
304
293
  });
305
294
 
306
- // Scenario: 특정 타겟 지정 lint
307
295
  it("succeeds with normalized target paths for lint", async () => {
308
296
  await runCheck({ targets: ["core-common"], types: ["lint"], fix: false });
309
297
 
310
- expect(stdoutOutput).toContain("LINT");
298
+ const successArgs = collectArgs(mockLogger.success);
299
+ expect(successArgs.some((a) => a.includes("LINT"))).toBe(true);
311
300
  expect(process.exitCode).toBeUndefined();
312
301
  });
313
302
 
314
- // Scenario: --fix 옵션으로 자동 수정
315
303
  it("succeeds when --fix is specified", async () => {
316
304
  await runCheck({ targets: [], types: ["lint"], fix: true });
317
305
 
318
- expect(stdoutOutput).toContain("LINT");
306
+ const successArgs = collectArgs(mockLogger.success);
307
+ expect(successArgs.some((a) => a.includes("LINT"))).toBe(true);
319
308
  expect(process.exitCode).toBeUndefined();
320
309
  });
321
310
 
322
- // Scenario: --fix 없이 실행
323
311
  it("succeeds when --fix is not specified", async () => {
324
312
  await runCheck({ targets: [], types: ["lint"], fix: false });
325
313
 
326
- expect(stdoutOutput).toContain("LINT");
314
+ const successArgs = collectArgs(mockLogger.success);
315
+ expect(successArgs.some((a) => a.includes("LINT"))).toBe(true);
327
316
  expect(process.exitCode).toBeUndefined();
328
317
  });
329
318
 
330
- // Scenario: lint 에러 없음
331
319
  it("does not set exitCode when lint passes", async () => {
332
320
  mocks.executeLint.mockResolvedValue({
333
321
  success: true, errorCount: 0, warningCount: 0, formattedOutput: "",
@@ -338,7 +326,6 @@ describe("runCheck", () => {
338
326
  expect(process.exitCode).toBeUndefined();
339
327
  });
340
328
 
341
- // Scenario: lint 에러 발생
342
329
  it("sets exitCode 1 when lint has errors", async () => {
343
330
  mocks.executeLint.mockResolvedValue({
344
331
  success: false, errorCount: 3, warningCount: 2, formattedOutput: "lint errors",
@@ -349,12 +336,11 @@ describe("runCheck", () => {
349
336
  expect(process.exitCode).toBe(1);
350
337
  });
351
338
 
352
- // typecheck 관련 로그 메시지가 출력되지 않는다
353
339
  it("does not output typecheck-related sections when only lint is requested", async () => {
354
340
  await runCheck({ targets: [], types: ["lint"], fix: false });
355
341
 
356
- expect(stdoutOutput).not.toContain("TYPECHECK");
342
+ const allArgs = [...collectArgs(mockLogger.success), ...collectArgs(mockLogger.error)];
343
+ expect(allArgs.some((a) => a.includes("TYPECHECK"))).toBe(false);
357
344
  });
358
345
  });
359
-
360
346
  });
@@ -298,8 +298,16 @@ describe("runPublish", () => {
298
298
  },
299
299
  });
300
300
 
301
- const writeSpy = vi.spyOn(process.stdout, "write").mockReturnValue(true);
301
+ const { consola } = await import("consola");
302
+ const infoSpy = vi.fn();
303
+ const origWithTag = consola.withTag.bind(consola);
304
+ const withTagSpy = vi.spyOn(consola, "withTag").mockImplementation((tag: string) => {
305
+ const logger = origWithTag(tag);
306
+ logger.info = infoSpy as any;
307
+ return logger;
308
+ });
302
309
 
310
+ // Re-import to pick up the spy (module already loaded, but logger is created at call time)
303
311
  await runPublish({
304
312
  targets: [],
305
313
  noBuild: false,
@@ -307,9 +315,9 @@ describe("runPublish", () => {
307
315
  options: [],
308
316
  });
309
317
 
310
- const output = writeSpy.mock.calls.map((c) => String(c[0])).join("");
311
- expect(output).toContain("배포할 패키지가 없습니다");
312
- writeSpy.mockRestore();
318
+ const infoArgs = infoSpy.mock.calls.map((c: unknown[]) => String(c[0]));
319
+ expect(infoArgs.some((a: string) => a.includes("배포할 패키지가 없습니다"))).toBe(true);
320
+ withTagSpy.mockRestore();
313
321
  });
314
322
  });
315
323
 
@@ -0,0 +1,12 @@
1
+ # Slice 3: severity 정리 — LLM 검증
2
+
3
+ ## 검증 항목
4
+
5
+ - [x] replace-deps.ts:5 — `const logger = consola.withTag("sd:cli:replace-deps")` 모듈-레벨 로거 추가 확인
6
+ - [x] replace-deps.ts:24 — `consola.warn(...)` → `logger.warn(...)` 변경 확인
7
+ - [x] deployment-phase.ts:66-70 — DRY-RUN 성공 메시지 `debug` → `info` 전환 확인: `dryRun ? logger.info("[DRY-RUN] ...") : logger.debug(...)`
8
+ - [x] deployment-phase.ts:76-80 — DRY-RUN 재시도 메시지 `debug` → `info` 전환 확인: 동일 패턴
9
+ - [x] deployment-phase.ts:102 — `logger.fail(...)` → `logger.error(...)` 전환 확인
10
+ - [x] BuildOrchestrator.ts:251 — `this._logger.success("빌드 실행 완료")` 행 제거 확인: 250행 뒤에 바로 `return` 문
11
+ - [x] BuildOrchestrator.ts:477 — `this._logger.info("빌드 완료")` → `this._logger.success("빌드 완료")` 전환 확인
12
+ - [x] BuildOrchestrator.ts:232-233 — `this._logger.start("빌드 실행 중...")` 유지 확인: start(232)/success(477) 쌍 정상화
@@ -0,0 +1,210 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
+ import fs from "fs";
3
+ import path from "path";
4
+ import os from "os";
5
+ import { upgradeVersion, computePublishLevels } from "../../src/commands/publish/version-upgrade";
6
+
7
+ function createTempDir(): string {
8
+ return fs.mkdtempSync(path.join(os.tmpdir(), "sd-cli-version-upgrade-"));
9
+ }
10
+
11
+ function writeJson(filePath: string, data: unknown): void {
12
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
13
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + "\n", "utf-8");
14
+ }
15
+
16
+ function readJson<T>(filePath: string): T {
17
+ return JSON.parse(fs.readFileSync(filePath, "utf-8")) as T;
18
+ }
19
+
20
+ describe("upgradeVersion", () => {
21
+ let tmpDir: string;
22
+
23
+ beforeEach(() => {
24
+ tmpDir = createTempDir();
25
+ });
26
+
27
+ afterEach(() => {
28
+ fs.rmSync(tmpDir, { recursive: true, force: true });
29
+ });
30
+
31
+ it("복수 패키지의 package.json을 병렬 업데이트한다", async () => {
32
+ // Given: allPkgPaths에 5개 패키지 경로가 있다
33
+ writeJson(path.join(tmpDir, "package.json"), {
34
+ name: "@simplysm/root",
35
+ version: "14.0.0",
36
+ });
37
+
38
+ const pkgNames = ["pkg-a", "pkg-b", "pkg-c", "pkg-d", "pkg-e"];
39
+ const allPkgPaths = pkgNames.map((name) => {
40
+ const pkgDir = path.join(tmpDir, "packages", name);
41
+ writeJson(path.join(pkgDir, "package.json"), {
42
+ name: `@simplysm/${name}`,
43
+ version: "14.0.0",
44
+ });
45
+ return pkgDir;
46
+ });
47
+
48
+ // sd-cli/templates 디렉토리 생성 (glob 대상이 없도록)
49
+ fs.mkdirSync(path.join(tmpDir, "packages", "sd-cli", "templates"), {
50
+ recursive: true,
51
+ });
52
+
53
+ // When
54
+ const result = await upgradeVersion(tmpDir, allPkgPaths, false);
55
+
56
+ // Then: 5개 패키지의 package.json이 모두 newVersion으로 업데이트된다
57
+ expect(result.version).toBe("14.0.1");
58
+ for (const pkgDir of allPkgPaths) {
59
+ const pkg = readJson<{ version: string }>(path.join(pkgDir, "package.json"));
60
+ expect(pkg.version).toBe("14.0.1");
61
+ }
62
+
63
+ // And: changedFiles에 5개 패키지 경로가 모두 포함된다
64
+ for (const pkgDir of allPkgPaths) {
65
+ expect(result.changedFiles).toContain(path.resolve(pkgDir, "package.json"));
66
+ }
67
+ });
68
+
69
+ it("패키지가 없으면 루트 package.json만 changedFiles에 포함된다", async () => {
70
+ // Given: allPkgPaths가 빈 배열이다
71
+ writeJson(path.join(tmpDir, "package.json"), {
72
+ name: "@simplysm/root",
73
+ version: "14.0.0",
74
+ });
75
+ fs.mkdirSync(path.join(tmpDir, "packages", "sd-cli", "templates"), {
76
+ recursive: true,
77
+ });
78
+
79
+ // When
80
+ const result = await upgradeVersion(tmpDir, [], false);
81
+
82
+ // Then: 루트 package.json만 changedFiles에 포함된다
83
+ expect(result.changedFiles).toHaveLength(1);
84
+ expect(result.changedFiles[0]).toBe(path.resolve(tmpDir, "package.json"));
85
+ });
86
+
87
+ it("복수 템플릿 파일을 병렬 업데이트한다", async () => {
88
+ // Given: 템플릿 3개 중 2개에 @simplysm 버전이 포함되어 있다
89
+ writeJson(path.join(tmpDir, "package.json"), {
90
+ name: "@simplysm/root",
91
+ version: "14.0.0",
92
+ });
93
+
94
+ const templatesDir = path.join(tmpDir, "packages", "sd-cli", "templates");
95
+ fs.mkdirSync(templatesDir, { recursive: true });
96
+
97
+ // 템플릿 1: @simplysm 버전 포함
98
+ fs.writeFileSync(
99
+ path.join(templatesDir, "a.hbs"),
100
+ `"@simplysm/core-common": "~14.0.0"`,
101
+ "utf-8",
102
+ );
103
+ // 템플릿 2: @simplysm 버전 포함
104
+ fs.writeFileSync(
105
+ path.join(templatesDir, "b.hbs"),
106
+ `"@simplysm/angular": "~14.0.0"`,
107
+ "utf-8",
108
+ );
109
+ // 템플릿 3: @simplysm 버전 미포함
110
+ fs.writeFileSync(path.join(templatesDir, "c.hbs"), `no version here`, "utf-8");
111
+
112
+ // When
113
+ const result = await upgradeVersion(tmpDir, [], false);
114
+
115
+ // Then: 2개 파일만 수정되고 changedFiles에 추가된다
116
+ const templateChanges = result.changedFiles.filter((f) => f.endsWith(".hbs"));
117
+ expect(templateChanges).toHaveLength(2);
118
+
119
+ // 수정된 파일들의 내용 확인
120
+ expect(fs.readFileSync(path.join(templatesDir, "a.hbs"), "utf-8")).toContain("~14.0.1");
121
+ expect(fs.readFileSync(path.join(templatesDir, "b.hbs"), "utf-8")).toContain("~14.0.1");
122
+ // 수정되지 않은 파일
123
+ expect(fs.readFileSync(path.join(templatesDir, "c.hbs"), "utf-8")).toBe("no version here");
124
+ });
125
+
126
+ it("템플릿이 없으면 템플릿 관련 쓰기 없이 완료된다", async () => {
127
+ // Given: glob 결과가 빈 배열이다 (templates 디렉토리에 .hbs 파일 없음)
128
+ writeJson(path.join(tmpDir, "package.json"), {
129
+ name: "@simplysm/root",
130
+ version: "14.0.0",
131
+ });
132
+ fs.mkdirSync(path.join(tmpDir, "packages", "sd-cli", "templates"), {
133
+ recursive: true,
134
+ });
135
+
136
+ // When
137
+ const result = await upgradeVersion(tmpDir, [], false);
138
+
139
+ // Then
140
+ const templateChanges = result.changedFiles.filter((f) => f.endsWith(".hbs"));
141
+ expect(templateChanges).toHaveLength(0);
142
+ });
143
+
144
+ it("changedFiles[0]이 프로젝트 루트 package.json 경로이다", async () => {
145
+ // Given: allPkgPaths에 3개 패키지가 있다
146
+ writeJson(path.join(tmpDir, "package.json"), {
147
+ name: "@simplysm/root",
148
+ version: "14.0.0",
149
+ });
150
+
151
+ const allPkgPaths = ["pkg-a", "pkg-b", "pkg-c"].map((name) => {
152
+ const pkgDir = path.join(tmpDir, "packages", name);
153
+ writeJson(path.join(pkgDir, "package.json"), {
154
+ name: `@simplysm/${name}`,
155
+ version: "14.0.0",
156
+ });
157
+ return pkgDir;
158
+ });
159
+
160
+ fs.mkdirSync(path.join(tmpDir, "packages", "sd-cli", "templates"), {
161
+ recursive: true,
162
+ });
163
+
164
+ // When
165
+ const result = await upgradeVersion(tmpDir, allPkgPaths, false);
166
+
167
+ // Then: changedFiles[0]이 프로젝트 루트 package.json 경로이다
168
+ expect(result.changedFiles[0]).toBe(path.resolve(tmpDir, "package.json"));
169
+ });
170
+ });
171
+
172
+ describe("computePublishLevels", () => {
173
+ let tmpDir: string;
174
+
175
+ beforeEach(() => {
176
+ tmpDir = createTempDir();
177
+ });
178
+
179
+ afterEach(() => {
180
+ fs.rmSync(tmpDir, { recursive: true, force: true });
181
+ });
182
+
183
+ it("의존 관계가 있는 패키지들의 레벨을 올바르게 계산한다", async () => {
184
+ // Given: A(의존 없음), B(A 의존), C(B 의존)
185
+ const pkgs = [
186
+ { name: "pkg-a", deps: {} },
187
+ { name: "pkg-b", deps: { "@simplysm/pkg-a": "~14.0.0" } },
188
+ { name: "pkg-c", deps: { "@simplysm/pkg-b": "~14.0.0" } },
189
+ ];
190
+
191
+ const publishPkgs = pkgs.map((p) => {
192
+ const pkgDir = path.join(tmpDir, "packages", p.name);
193
+ writeJson(path.join(pkgDir, "package.json"), {
194
+ name: `@simplysm/${p.name}`,
195
+ version: "14.0.0",
196
+ dependencies: p.deps,
197
+ });
198
+ return { name: p.name, path: pkgDir };
199
+ });
200
+
201
+ // When
202
+ const levels = await computePublishLevels(publishPkgs);
203
+
204
+ // Then: 레벨은 [[A], [B], [C]]
205
+ expect(levels).toHaveLength(3);
206
+ expect(levels[0].map((p) => p.name)).toEqual(["pkg-a"]);
207
+ expect(levels[1].map((p) => p.name)).toEqual(["pkg-b"]);
208
+ expect(levels[2].map((p) => p.name)).toEqual(["pkg-c"]);
209
+ });
210
+ });