@simplysm/sd-cli 13.0.100 → 14.0.1

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 (409) hide show
  1. package/dist/commands/build.js +29 -19
  2. package/dist/commands/build.js.map +1 -6
  3. package/dist/commands/check.d.ts +1 -0
  4. package/dist/commands/check.d.ts.map +1 -1
  5. package/dist/commands/check.js +130 -115
  6. package/dist/commands/check.js.map +1 -6
  7. package/dist/commands/dev.d.ts +6 -7
  8. package/dist/commands/dev.d.ts.map +1 -1
  9. package/dist/commands/dev.js +24 -14
  10. package/dist/commands/dev.js.map +1 -6
  11. package/dist/commands/lint.d.ts +1 -1
  12. package/dist/commands/lint.js +158 -116
  13. package/dist/commands/lint.js.map +1 -6
  14. package/dist/commands/publish.d.ts.map +1 -1
  15. package/dist/commands/publish.js +637 -510
  16. package/dist/commands/publish.js.map +1 -6
  17. package/dist/commands/replace-deps.js +12 -12
  18. package/dist/commands/replace-deps.js.map +1 -6
  19. package/dist/commands/typecheck.d.ts +5 -30
  20. package/dist/commands/typecheck.d.ts.map +1 -1
  21. package/dist/commands/typecheck.js +144 -207
  22. package/dist/commands/typecheck.js.map +1 -6
  23. package/dist/commands/watch.d.ts +6 -4
  24. package/dist/commands/watch.d.ts.map +1 -1
  25. package/dist/commands/watch.js +25 -16
  26. package/dist/commands/watch.js.map +1 -6
  27. package/dist/engines/NgtscEngine.d.ts +47 -0
  28. package/dist/engines/NgtscEngine.d.ts.map +1 -0
  29. package/dist/engines/NgtscEngine.js +151 -0
  30. package/dist/engines/NgtscEngine.js.map +1 -0
  31. package/dist/engines/ServerEsbuildEngine.d.ts +47 -0
  32. package/dist/engines/ServerEsbuildEngine.d.ts.map +1 -0
  33. package/dist/engines/ServerEsbuildEngine.js +159 -0
  34. package/dist/engines/ServerEsbuildEngine.js.map +1 -0
  35. package/dist/engines/TscEngine.d.ts +47 -0
  36. package/dist/engines/TscEngine.d.ts.map +1 -0
  37. package/dist/engines/TscEngine.js +153 -0
  38. package/dist/engines/TscEngine.js.map +1 -0
  39. package/dist/engines/ViteEngine.d.ts +49 -0
  40. package/dist/engines/ViteEngine.d.ts.map +1 -0
  41. package/dist/engines/ViteEngine.js +161 -0
  42. package/dist/engines/ViteEngine.js.map +1 -0
  43. package/dist/engines/index.d.ts +26 -0
  44. package/dist/engines/index.d.ts.map +1 -0
  45. package/dist/engines/index.js +30 -0
  46. package/dist/engines/index.js.map +1 -0
  47. package/dist/engines/types.d.ts +77 -0
  48. package/dist/engines/types.d.ts.map +1 -0
  49. package/dist/engines/types.js +2 -0
  50. package/dist/engines/types.js.map +1 -0
  51. package/dist/index.d.ts +0 -1
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js +2 -2
  54. package/dist/index.js.map +1 -6
  55. package/dist/infra/ResultCollector.d.ts +1 -1
  56. package/dist/infra/ResultCollector.d.ts.map +1 -1
  57. package/dist/infra/ResultCollector.js +30 -27
  58. package/dist/infra/ResultCollector.js.map +1 -6
  59. package/dist/infra/SignalHandler.js +45 -42
  60. package/dist/infra/SignalHandler.js.map +1 -6
  61. package/dist/infra/WorkerManager.js +56 -53
  62. package/dist/infra/WorkerManager.js.map +1 -6
  63. package/dist/orchestrators/BuildOrchestrator.d.ts +33 -1
  64. package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
  65. package/dist/orchestrators/BuildOrchestrator.js +314 -309
  66. package/dist/orchestrators/BuildOrchestrator.js.map +1 -6
  67. package/dist/orchestrators/DevWatchOrchestrator.d.ts +60 -0
  68. package/dist/orchestrators/DevWatchOrchestrator.d.ts.map +1 -0
  69. package/dist/orchestrators/DevWatchOrchestrator.js +465 -0
  70. package/dist/orchestrators/DevWatchOrchestrator.js.map +1 -0
  71. package/dist/sd-cli-entry.d.ts.map +1 -1
  72. package/dist/sd-cli-entry.js +190 -266
  73. package/dist/sd-cli-entry.js.map +1 -6
  74. package/dist/sd-cli.js +77 -49
  75. package/dist/sd-cli.js.map +1 -6
  76. package/dist/sd-config.types.d.ts +2 -0
  77. package/dist/sd-config.types.d.ts.map +1 -1
  78. package/dist/sd-config.types.js +2 -1
  79. package/dist/sd-config.types.js.map +1 -6
  80. package/dist/utils/angular-build.d.ts +77 -0
  81. package/dist/utils/angular-build.d.ts.map +1 -0
  82. package/dist/utils/angular-build.js +84 -0
  83. package/dist/utils/angular-build.js.map +1 -0
  84. package/dist/utils/build-env.js +9 -9
  85. package/dist/utils/build-env.js.map +1 -6
  86. package/dist/utils/concurrency.d.ts +15 -0
  87. package/dist/utils/concurrency.d.ts.map +1 -0
  88. package/dist/utils/concurrency.js +38 -0
  89. package/dist/utils/concurrency.js.map +1 -0
  90. package/dist/utils/copy-public.js +104 -87
  91. package/dist/utils/copy-public.js.map +1 -6
  92. package/dist/utils/copy-src.js +49 -35
  93. package/dist/utils/copy-src.js.map +1 -6
  94. package/dist/utils/esbuild-config.d.ts +0 -29
  95. package/dist/utils/esbuild-config.d.ts.map +1 -1
  96. package/dist/utils/esbuild-config.js +151 -218
  97. package/dist/utils/esbuild-config.js.map +1 -6
  98. package/dist/utils/ngtsc-build-core.d.ts +49 -0
  99. package/dist/utils/ngtsc-build-core.d.ts.map +1 -0
  100. package/dist/utils/ngtsc-build-core.js +250 -0
  101. package/dist/utils/ngtsc-build-core.js.map +1 -0
  102. package/dist/utils/output-path-rewriter.d.ts +23 -0
  103. package/dist/utils/output-path-rewriter.d.ts.map +1 -0
  104. package/dist/utils/output-path-rewriter.js +74 -0
  105. package/dist/utils/output-path-rewriter.js.map +1 -0
  106. package/dist/utils/output-utils.js +55 -40
  107. package/dist/utils/output-utils.js.map +1 -6
  108. package/dist/utils/package-utils.d.ts +8 -0
  109. package/dist/utils/package-utils.d.ts.map +1 -1
  110. package/dist/utils/package-utils.js +103 -73
  111. package/dist/utils/package-utils.js.map +1 -6
  112. package/dist/utils/rebuild-manager.js +41 -44
  113. package/dist/utils/rebuild-manager.js.map +1 -6
  114. package/dist/utils/replace-deps.js +283 -184
  115. package/dist/utils/replace-deps.js.map +1 -6
  116. package/dist/utils/scss-compiler.d.ts +10 -0
  117. package/dist/utils/scss-compiler.d.ts.map +1 -0
  118. package/dist/utils/scss-compiler.js +36 -0
  119. package/dist/utils/scss-compiler.js.map +1 -0
  120. package/dist/utils/sd-config.js +29 -19
  121. package/dist/utils/sd-config.js.map +1 -6
  122. package/dist/utils/tsc-build.d.ts +36 -0
  123. package/dist/utils/tsc-build.d.ts.map +1 -0
  124. package/dist/utils/tsc-build.js +130 -0
  125. package/dist/utils/tsc-build.js.map +1 -0
  126. package/dist/utils/tsconfig.d.ts +7 -26
  127. package/dist/utils/tsconfig.d.ts.map +1 -1
  128. package/dist/utils/tsconfig.js +39 -64
  129. package/dist/utils/tsconfig.js.map +1 -6
  130. package/dist/utils/typecheck-non-package.d.ts +18 -0
  131. package/dist/utils/typecheck-non-package.d.ts.map +1 -0
  132. package/dist/utils/typecheck-non-package.js +64 -0
  133. package/dist/utils/typecheck-non-package.js.map +1 -0
  134. package/dist/utils/typecheck-serialization.js +58 -40
  135. package/dist/utils/typecheck-serialization.js.map +1 -6
  136. package/dist/utils/worker-events.js +48 -40
  137. package/dist/utils/worker-events.js.map +1 -6
  138. package/dist/utils/worker-utils.js +48 -28
  139. package/dist/utils/worker-utils.js.map +1 -6
  140. package/dist/vitest-plugin.d.ts +9 -0
  141. package/dist/vitest-plugin.d.ts.map +1 -0
  142. package/dist/vitest-plugin.js +85 -0
  143. package/dist/vitest-plugin.js.map +1 -0
  144. package/dist/workers/library-build.worker.d.ts +54 -0
  145. package/dist/workers/library-build.worker.d.ts.map +1 -0
  146. package/dist/workers/library-build.worker.js +97 -0
  147. package/dist/workers/library-build.worker.js.map +1 -0
  148. package/dist/workers/lint.worker.js +9 -6
  149. package/dist/workers/lint.worker.js.map +1 -6
  150. package/dist/workers/ngtsc-build.worker.d.ts +23 -0
  151. package/dist/workers/ngtsc-build.worker.d.ts.map +1 -0
  152. package/dist/workers/ngtsc-build.worker.js +98 -0
  153. package/dist/workers/ngtsc-build.worker.js.map +1 -0
  154. package/dist/workers/{server.worker.d.ts → server-build.worker.d.ts} +39 -29
  155. package/dist/workers/server-build.worker.d.ts.map +1 -0
  156. package/dist/workers/server-build.worker.js +399 -0
  157. package/dist/workers/server-build.worker.js.map +1 -0
  158. package/dist/workers/server-runtime.worker.d.ts +3 -2
  159. package/dist/workers/server-runtime.worker.d.ts.map +1 -1
  160. package/dist/workers/server-runtime.worker.js +100 -95
  161. package/dist/workers/server-runtime.worker.js.map +1 -6
  162. package/dist/workers/vite-build.worker.d.ts +56 -0
  163. package/dist/workers/vite-build.worker.d.ts.map +1 -0
  164. package/dist/workers/vite-build.worker.js +167 -0
  165. package/dist/workers/vite-build.worker.js.map +1 -0
  166. package/package.json +10 -16
  167. package/src/commands/check.ts +21 -3
  168. package/src/commands/dev.ts +10 -8
  169. package/src/commands/lint.ts +1 -1
  170. package/src/commands/publish.ts +4 -0
  171. package/src/commands/typecheck.ts +89 -256
  172. package/src/commands/watch.ts +9 -8
  173. package/src/engines/NgtscEngine.ts +190 -0
  174. package/src/engines/ServerEsbuildEngine.ts +195 -0
  175. package/src/engines/TscEngine.ts +189 -0
  176. package/src/engines/ViteEngine.ts +203 -0
  177. package/src/engines/index.ts +49 -0
  178. package/src/engines/types.ts +79 -0
  179. package/src/index.ts +0 -3
  180. package/src/infra/ResultCollector.ts +1 -1
  181. package/src/orchestrators/BuildOrchestrator.ts +87 -157
  182. package/src/orchestrators/DevWatchOrchestrator.ts +573 -0
  183. package/src/sd-cli-entry.ts +13 -116
  184. package/src/sd-config.types.ts +2 -0
  185. package/src/utils/angular-build.ts +157 -0
  186. package/src/utils/concurrency.ts +43 -0
  187. package/src/utils/esbuild-config.ts +1 -122
  188. package/src/utils/ngtsc-build-core.ts +379 -0
  189. package/src/utils/output-path-rewriter.ts +82 -0
  190. package/src/utils/package-utils.ts +20 -0
  191. package/src/utils/scss-compiler.ts +58 -0
  192. package/src/utils/tsc-build.ts +175 -0
  193. package/src/utils/tsconfig.ts +27 -95
  194. package/src/utils/typecheck-non-package.ts +87 -0
  195. package/src/vitest-plugin.ts +118 -0
  196. package/src/workers/library-build.worker.ts +153 -0
  197. package/src/workers/ngtsc-build.worker.ts +146 -0
  198. package/src/workers/server-build.worker.ts +565 -0
  199. package/src/workers/server-runtime.worker.ts +17 -26
  200. package/src/workers/vite-build.worker.ts +252 -0
  201. package/tests/commands/check.spec.ts +276 -0
  202. package/tests/commands/dev.spec.ts +53 -0
  203. package/tests/commands/lint.spec.ts +243 -0
  204. package/tests/commands/publish.spec.ts +1159 -0
  205. package/tests/commands/typecheck.spec.ts +294 -0
  206. package/tests/commands/watch.spec.ts +53 -0
  207. package/tests/engines/engine-selection.spec.ts +247 -0
  208. package/tests/engines/ngtsc-engine.spec.ts +274 -0
  209. package/tests/engines/server-esbuild-engine.spec.ts +256 -0
  210. package/tests/engines/tsc-engine.spec.ts +213 -0
  211. package/tests/engines/vite-engine.spec.ts +358 -0
  212. package/tests/infra/result-collector.spec.ts +46 -0
  213. package/tests/infra/signal-handler.spec.ts +32 -0
  214. package/tests/infra/worker-manager.spec.ts +63 -0
  215. package/tests/orchestrators/build-orchestrator.spec.ts +772 -0
  216. package/tests/orchestrators/dev-watch-orchestrator.spec.ts +1173 -0
  217. package/tests/sd-cli-entry.spec.ts +49 -0
  218. package/tests/utils/angular-build.spec.ts +251 -0
  219. package/tests/utils/build-env.spec.ts +33 -0
  220. package/tests/utils/concurrency.spec.ts +65 -0
  221. package/tests/utils/copy-src.spec.ts +144 -0
  222. package/tests/utils/esbuild-config.spec.ts +186 -0
  223. package/tests/utils/external-modules.spec.ts +161 -0
  224. package/tests/utils/ngtsc-scss-refactor.spec.ts +66 -0
  225. package/tests/utils/output-path-rewriter.spec.ts +165 -0
  226. package/tests/utils/output-utils.spec.ts +104 -0
  227. package/tests/utils/package-utils.spec.ts +52 -0
  228. package/tests/utils/rebuild-manager.spec.ts +30 -27
  229. package/tests/utils/replace-deps.spec.ts +69 -0
  230. package/tests/utils/scss-compiler.spec.ts +131 -0
  231. package/tests/utils/sd-config.spec.ts +77 -0
  232. package/tests/utils/tsc-build.spec.ts +358 -0
  233. package/tests/utils/tsconfig-angular.spec.ts +71 -0
  234. package/tests/utils/typecheck-non-package.spec.ts +120 -0
  235. package/tests/utils/worker-events.spec.ts +155 -0
  236. package/tests/utils/worker-utils.spec.ts +43 -0
  237. package/tests/vitest-plugin-cwd.spec.ts +68 -0
  238. package/tests/vitest-plugin.spec.ts +103 -0
  239. package/tests/workers/library-build-worker.spec.ts +258 -0
  240. package/tests/workers/ngtsc-build-worker.spec.ts +187 -0
  241. package/tests/workers/server-build-worker.spec.ts +566 -0
  242. package/tests/workers/server-runtime-worker.spec.ts +251 -0
  243. package/README.md +0 -295
  244. package/dist/builders/BaseBuilder.d.ts +0 -88
  245. package/dist/builders/BaseBuilder.d.ts.map +0 -1
  246. package/dist/builders/BaseBuilder.js +0 -142
  247. package/dist/builders/BaseBuilder.js.map +0 -6
  248. package/dist/builders/DtsBuilder.d.ts +0 -22
  249. package/dist/builders/DtsBuilder.d.ts.map +0 -1
  250. package/dist/builders/DtsBuilder.js +0 -72
  251. package/dist/builders/DtsBuilder.js.map +0 -6
  252. package/dist/builders/LibraryBuilder.d.ts +0 -22
  253. package/dist/builders/LibraryBuilder.d.ts.map +0 -1
  254. package/dist/builders/LibraryBuilder.js +0 -85
  255. package/dist/builders/LibraryBuilder.js.map +0 -6
  256. package/dist/builders/types.d.ts +0 -55
  257. package/dist/builders/types.d.ts.map +0 -1
  258. package/dist/builders/types.js +0 -1
  259. package/dist/builders/types.js.map +0 -6
  260. package/dist/capacitor/capacitor.d.ts +0 -151
  261. package/dist/capacitor/capacitor.d.ts.map +0 -1
  262. package/dist/capacitor/capacitor.js +0 -694
  263. package/dist/capacitor/capacitor.js.map +0 -6
  264. package/dist/commands/device.d.ts +0 -22
  265. package/dist/commands/device.d.ts.map +0 -1
  266. package/dist/commands/device.js +0 -98
  267. package/dist/commands/device.js.map +0 -6
  268. package/dist/commands/init.d.ts +0 -14
  269. package/dist/commands/init.d.ts.map +0 -1
  270. package/dist/commands/init.js +0 -72
  271. package/dist/commands/init.js.map +0 -6
  272. package/dist/electron/electron.d.ts +0 -84
  273. package/dist/electron/electron.d.ts.map +0 -1
  274. package/dist/electron/electron.js +0 -263
  275. package/dist/electron/electron.js.map +0 -6
  276. package/dist/orchestrators/DevOrchestrator.d.ts +0 -83
  277. package/dist/orchestrators/DevOrchestrator.d.ts.map +0 -1
  278. package/dist/orchestrators/DevOrchestrator.js +0 -540
  279. package/dist/orchestrators/DevOrchestrator.js.map +0 -6
  280. package/dist/orchestrators/WatchOrchestrator.d.ts +0 -57
  281. package/dist/orchestrators/WatchOrchestrator.d.ts.map +0 -1
  282. package/dist/orchestrators/WatchOrchestrator.js +0 -199
  283. package/dist/orchestrators/WatchOrchestrator.js.map +0 -6
  284. package/dist/utils/tailwind-config-deps.d.ts +0 -8
  285. package/dist/utils/tailwind-config-deps.d.ts.map +0 -1
  286. package/dist/utils/tailwind-config-deps.js +0 -82
  287. package/dist/utils/tailwind-config-deps.js.map +0 -6
  288. package/dist/utils/template.d.ts +0 -14
  289. package/dist/utils/template.d.ts.map +0 -1
  290. package/dist/utils/template.js +0 -33
  291. package/dist/utils/template.js.map +0 -6
  292. package/dist/utils/vite-config.d.ts +0 -35
  293. package/dist/utils/vite-config.d.ts.map +0 -1
  294. package/dist/utils/vite-config.js +0 -259
  295. package/dist/utils/vite-config.js.map +0 -6
  296. package/dist/workers/client.worker.d.ts +0 -83
  297. package/dist/workers/client.worker.d.ts.map +0 -1
  298. package/dist/workers/client.worker.js +0 -111
  299. package/dist/workers/client.worker.js.map +0 -6
  300. package/dist/workers/dts.worker.d.ts +0 -75
  301. package/dist/workers/dts.worker.d.ts.map +0 -1
  302. package/dist/workers/dts.worker.js +0 -270
  303. package/dist/workers/dts.worker.js.map +0 -6
  304. package/dist/workers/library.worker.d.ts +0 -75
  305. package/dist/workers/library.worker.d.ts.map +0 -1
  306. package/dist/workers/library.worker.js +0 -166
  307. package/dist/workers/library.worker.js.map +0 -6
  308. package/dist/workers/server.worker.d.ts.map +0 -1
  309. package/dist/workers/server.worker.js +0 -482
  310. package/dist/workers/server.worker.js.map +0 -6
  311. package/src/builders/BaseBuilder.ts +0 -218
  312. package/src/builders/DtsBuilder.ts +0 -92
  313. package/src/builders/LibraryBuilder.ts +0 -110
  314. package/src/builders/types.ts +0 -60
  315. package/src/capacitor/capacitor.ts +0 -931
  316. package/src/commands/device.ts +0 -140
  317. package/src/commands/init.ts +0 -113
  318. package/src/electron/electron.ts +0 -362
  319. package/src/orchestrators/DevOrchestrator.ts +0 -744
  320. package/src/orchestrators/WatchOrchestrator.ts +0 -277
  321. package/src/utils/tailwind-config-deps.ts +0 -98
  322. package/src/utils/template.ts +0 -56
  323. package/src/utils/vite-config.ts +0 -390
  324. package/src/workers/client.worker.ts +0 -250
  325. package/src/workers/dts.worker.ts +0 -453
  326. package/src/workers/library.worker.ts +0 -316
  327. package/src/workers/server.worker.ts +0 -734
  328. package/templates/init/.gitignore.hbs +0 -34
  329. package/templates/init/.npmrc.hbs +0 -1
  330. package/templates/init/.prettierignore +0 -1
  331. package/templates/init/.prettierrc.yaml +0 -12
  332. package/templates/init/eslint.config.ts +0 -15
  333. package/templates/init/mise.toml +0 -3
  334. package/templates/init/package.json.hbs +0 -32
  335. package/templates/init/packages/client-admin/index.html.hbs +0 -144
  336. package/templates/init/packages/client-admin/package.json.hbs +0 -27
  337. package/templates/init/packages/client-admin/public/assets/logo-landscape.png +0 -0
  338. package/templates/init/packages/client-admin/public/assets/logo.png +0 -0
  339. package/templates/init/packages/client-admin/public/favicon.ico +0 -0
  340. package/templates/init/packages/client-admin/src/App.tsx +0 -42
  341. package/templates/init/packages/client-admin/src/dev/DevDialog.tsx +0 -34
  342. package/templates/init/packages/client-admin/src/events/AuthChangeEvent.ts +0 -3
  343. package/templates/init/packages/client-admin/src/main.css +0 -4
  344. package/templates/init/packages/client-admin/src/main.tsx.hbs +0 -146
  345. package/templates/init/packages/client-admin/src/providers/AppServiceProvider.tsx.hbs +0 -103
  346. package/templates/init/packages/client-admin/src/providers/AppStructureProvider.tsx +0 -84
  347. package/templates/init/packages/client-admin/src/providers/AuthProvider.tsx.hbs +0 -96
  348. package/templates/init/packages/client-admin/src/providers/configureSharedData.ts.hbs +0 -67
  349. package/templates/init/packages/client-admin/src/views/auth/LoginView.tsx +0 -132
  350. package/templates/init/packages/client-admin/src/views/home/HomeView.tsx +0 -108
  351. package/templates/init/packages/client-admin/src/views/home/base/employee/EmployeeDetail.tsx.hbs +0 -243
  352. package/templates/init/packages/client-admin/src/views/home/base/employee/EmployeeSheet.tsx.hbs +0 -271
  353. package/templates/init/packages/client-admin/src/views/home/base/role-permission/RoleDetail.tsx.hbs +0 -146
  354. package/templates/init/packages/client-admin/src/views/home/base/role-permission/RolePermissionDetail.tsx.hbs +0 -121
  355. package/templates/init/packages/client-admin/src/views/home/base/role-permission/RolePermissionView.tsx +0 -52
  356. package/templates/init/packages/client-admin/src/views/home/base/role-permission/RoleSheet.tsx.hbs +0 -125
  357. package/templates/init/packages/client-admin/src/views/home/main/MainView.tsx.hbs +0 -13
  358. package/templates/init/packages/client-admin/src/views/home/my-info/MyInfoDetail.tsx.hbs +0 -241
  359. package/templates/init/packages/client-admin/src/views/home/system/system-log/SystemLogSheet.tsx.hbs +0 -169
  360. package/templates/init/packages/client-admin/src/views/not-found/NotFoundView.tsx +0 -15
  361. package/templates/init/packages/client-admin/tailwind.config.ts +0 -10
  362. package/templates/init/packages/db-main/package.json.hbs +0 -13
  363. package/templates/init/packages/db-main/src/MainDbContext.ts +0 -22
  364. package/templates/init/packages/db-main/src/dataLogExt.ts +0 -127
  365. package/templates/init/packages/db-main/src/index.ts +0 -14
  366. package/templates/init/packages/db-main/src/tables/base/Employee.ts +0 -24
  367. package/templates/init/packages/db-main/src/tables/base/EmployeeConfig.ts +0 -13
  368. package/templates/init/packages/db-main/src/tables/base/Role.ts +0 -9
  369. package/templates/init/packages/db-main/src/tables/base/RolePermission.ts +0 -13
  370. package/templates/init/packages/db-main/src/tables/system/_DataLog.ts +0 -19
  371. package/templates/init/packages/db-main/src/tables/system/_Log.ts +0 -16
  372. package/templates/init/packages/server/package.json.hbs +0 -20
  373. package/templates/init/packages/server/public-dev/dev//354/264/210/352/270/260/355/231/224.xlsx +0 -0
  374. package/templates/init/packages/server/src/index.ts +0 -4
  375. package/templates/init/packages/server/src/main.ts.hbs +0 -34
  376. package/templates/init/packages/server/src/services/AuthService.ts.hbs +0 -171
  377. package/templates/init/packages/server/src/services/DevService.ts.hbs +0 -94
  378. package/templates/init/packages/server/src/services/EmployeeService.ts.hbs +0 -122
  379. package/templates/init/packages/server/src/services/RoleService.ts.hbs +0 -59
  380. package/templates/init/pnpm-workspace.yaml +0 -15
  381. package/templates/init/sd.config.ts.hbs +0 -48
  382. package/templates/init/tsconfig.json.hbs +0 -39
  383. package/templates/init/vitest.config.ts +0 -36
  384. package/tests/capacitor-exclude.spec.ts +0 -78
  385. package/tests/capacitor.spec.ts +0 -49
  386. package/tests/copy-src.spec.ts +0 -50
  387. package/tests/electron-exclude.spec.ts +0 -61
  388. package/tests/get-compiler-options-for-package.spec.ts +0 -80
  389. package/tests/get-package-source-files.spec.ts +0 -139
  390. package/tests/get-types-from-package-json.spec.ts +0 -92
  391. package/tests/infra/ResultCollector.spec.ts +0 -30
  392. package/tests/infra/SignalHandler.spec.ts +0 -38
  393. package/tests/infra/WorkerManager.spec.ts +0 -63
  394. package/tests/load-ignore-patterns.spec.ts +0 -163
  395. package/tests/load-sd-config.spec.ts +0 -100
  396. package/tests/package-utils.spec.ts +0 -188
  397. package/tests/parse-root-tsconfig.spec.ts +0 -89
  398. package/tests/publish-config-narrowing.spec.ts +0 -20
  399. package/tests/replace-deps.spec.ts +0 -308
  400. package/tests/run-lint.spec.ts +0 -366
  401. package/tests/run-typecheck.spec.ts +0 -544
  402. package/tests/run-watch.spec.ts +0 -76
  403. package/tests/sd-cli.spec.ts +0 -265
  404. package/tests/sd-public-dev-plugin-mime.spec.ts +0 -19
  405. package/tests/tailwind-config-deps.spec.ts +0 -30
  406. package/tests/template.spec.ts +0 -70
  407. package/tests/vite-config-exclude.spec.ts +0 -35
  408. package/tests/vite-config-outdir.spec.ts +0 -38
  409. package/tests/write-changed-output-files.spec.ts +0 -97
@@ -0,0 +1,772 @@
1
+ import { describe, it, expect, vi, beforeEach } from "vitest";
2
+
3
+ // --- Mock factories (vi.mock is hoisted) ---
4
+
5
+ const mockLogger = {
6
+ debug: vi.fn(),
7
+ info: vi.fn(),
8
+ warn: vi.fn(),
9
+ error: vi.fn(),
10
+ start: vi.fn(),
11
+ success: vi.fn(),
12
+ };
13
+
14
+ vi.mock("consola", () => {
15
+ const consolaObj = {
16
+ withTag: vi.fn(() => mockLogger),
17
+ };
18
+ return { consola: consolaObj, default: consolaObj };
19
+ });
20
+
21
+ vi.mock("../../src/utils/sd-config", () => ({
22
+ loadSdConfig: vi.fn(),
23
+ }));
24
+
25
+ vi.mock("../../src/utils/build-env", () => ({
26
+ getVersion: vi.fn(),
27
+ }));
28
+
29
+ vi.mock("../../src/utils/copy-src", () => ({
30
+ copySrcFiles: vi.fn().mockResolvedValue(undefined),
31
+ }));
32
+
33
+ vi.mock("../../src/utils/output-utils", () => ({
34
+ formatBuildMessages: vi.fn(
35
+ (name: string, target: string, msgs: string[]) => `${name} (${target}): ${msgs.join(", ")}`,
36
+ ),
37
+ }));
38
+
39
+ vi.mock("../../src/utils/typecheck-serialization", () => ({
40
+ deserializeDiagnostic: vi.fn((d: any) => d),
41
+ }));
42
+
43
+ vi.mock("@simplysm/core-node", () => ({
44
+ Worker: {
45
+ create: vi.fn(),
46
+ },
47
+ fsx: {
48
+ rm: vi.fn().mockResolvedValue(undefined),
49
+ },
50
+ }));
51
+
52
+ const mockEngines: Array<{
53
+ run: ReturnType<typeof vi.fn>;
54
+ startWatch: ReturnType<typeof vi.fn>;
55
+ stop: ReturnType<typeof vi.fn>;
56
+ }> = [];
57
+
58
+ vi.mock("../../src/engines/index", () => ({
59
+ createBuildEngine: vi.fn(() => {
60
+ const engine = {
61
+ run: vi.fn().mockResolvedValue({
62
+ success: true,
63
+ js: { success: true, errors: [], warnings: [] },
64
+ dts: { success: true, errors: [], warnings: [], diagnostics: [] },
65
+ }),
66
+ startWatch: vi.fn().mockResolvedValue(undefined),
67
+ stop: vi.fn().mockResolvedValue(undefined),
68
+ };
69
+ mockEngines.push(engine);
70
+ return engine;
71
+ }),
72
+ }));
73
+
74
+ // --- Dynamic imports after mocking ---
75
+
76
+ const { BuildOrchestrator, classifyPackages } = await import("../../src/orchestrators/BuildOrchestrator");
77
+ const { loadSdConfig } = await import("../../src/utils/sd-config");
78
+ const { getVersion } = await import("../../src/utils/build-env");
79
+ const { copySrcFiles } = await import("../../src/utils/copy-src");
80
+ const { Worker, fsx } = await import("@simplysm/core-node");
81
+ const { createBuildEngine } = await import("../../src/engines/index");
82
+
83
+ import type { SdConfig } from "../../src/sd-config.types";
84
+
85
+ // --- Helpers ---
86
+
87
+ interface MockWorkerProxy {
88
+ build: ReturnType<typeof vi.fn>;
89
+ lint: ReturnType<typeof vi.fn>;
90
+ terminate: ReturnType<typeof vi.fn>;
91
+ }
92
+
93
+ function createMockWorkerProxy(overrides: Partial<MockWorkerProxy> = {}): MockWorkerProxy {
94
+ return {
95
+ build: vi.fn().mockResolvedValue({ success: true, errors: [], warnings: [], diagnostics: [] }),
96
+ lint: vi.fn().mockResolvedValue({ success: true }),
97
+ terminate: vi.fn().mockResolvedValue(undefined),
98
+ ...overrides,
99
+ };
100
+ }
101
+
102
+ function setupDefaults(config: Partial<SdConfig> = {}): void {
103
+ vi.mocked(loadSdConfig).mockResolvedValue({ packages: {}, ...config } as SdConfig);
104
+ vi.mocked(getVersion).mockResolvedValue("1.0.0");
105
+ }
106
+
107
+ // --- Tests ---
108
+
109
+ beforeEach(() => {
110
+ vi.clearAllMocks();
111
+ mockEngines.length = 0;
112
+ // Reset process.exitCode
113
+ process.exitCode = undefined;
114
+ // Mock process.stdout.write
115
+ vi.spyOn(process.stdout, "write").mockReturnValue(true);
116
+ });
117
+
118
+ describe("BuildOrchestrator.initialize", () => {
119
+ it("loads sd.config.ts with dev=false and classifies packages", async () => {
120
+ setupDefaults({
121
+ packages: {
122
+ "core-common": { target: "neutral", publish: { type: "npm" } },
123
+ "demo-server": { target: "server" },
124
+ },
125
+ });
126
+
127
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
128
+ await orchestrator.initialize();
129
+
130
+ expect(loadSdConfig).toHaveBeenCalledWith(
131
+ expect.objectContaining({ dev: false }),
132
+ );
133
+ });
134
+
135
+ it("throws and sets exitCode=1 when sd.config.ts load fails", async () => {
136
+ vi.mocked(loadSdConfig).mockRejectedValue(new Error("syntax error"));
137
+ vi.mocked(getVersion).mockResolvedValue("1.0.0");
138
+
139
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
140
+ await expect(orchestrator.initialize()).rejects.toThrow("syntax error");
141
+ expect(process.exitCode).toBe(1);
142
+ expect(mockLogger.error).toHaveBeenCalled();
143
+ });
144
+
145
+ it("prepares VER and DEV environment variables", async () => {
146
+ setupDefaults({
147
+ packages: {
148
+ "core-common": { target: "neutral", publish: { type: "npm" } },
149
+ },
150
+ });
151
+
152
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
153
+ await orchestrator.initialize();
154
+
155
+ expect(getVersion).toHaveBeenCalled();
156
+ });
157
+
158
+ it("passes options to loadSdConfig", async () => {
159
+ setupDefaults();
160
+
161
+ const orchestrator = new BuildOrchestrator({ targets: [], options: ["production"] });
162
+ await orchestrator.initialize();
163
+
164
+ expect(loadSdConfig).toHaveBeenCalledWith(
165
+ expect.objectContaining({ options: ["production"] }),
166
+ );
167
+ });
168
+
169
+ it("outputs message when no packages to build", async () => {
170
+ setupDefaults({
171
+ packages: {
172
+ "sd-claude": { target: "scripts" } as any,
173
+ },
174
+ });
175
+
176
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
177
+ await orchestrator.initialize();
178
+
179
+ expect(process.stdout.write).toHaveBeenCalledWith(
180
+ expect.stringContaining("No packages to build"),
181
+ );
182
+ });
183
+ });
184
+
185
+ describe("BuildOrchestrator.start", () => {
186
+ it("cleans dist folders before building", async () => {
187
+ setupDefaults({
188
+ packages: {
189
+ "core-common": { target: "neutral", publish: { type: "npm" } },
190
+ },
191
+ });
192
+ const mockProxy = createMockWorkerProxy();
193
+ vi.mocked(Worker.create).mockReturnValue(mockProxy as any);
194
+
195
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
196
+ await orchestrator.initialize();
197
+ await orchestrator.start();
198
+
199
+ expect(fsx.rm).toHaveBeenCalledWith(
200
+ expect.stringContaining("core-common"),
201
+ );
202
+ });
203
+
204
+ it("uses BuildEngine for buildPackages", async () => {
205
+ setupDefaults({
206
+ packages: {
207
+ "core-common": { target: "browser", publish: { type: "npm" } },
208
+ },
209
+ });
210
+ const mockProxy = createMockWorkerProxy();
211
+ vi.mocked(Worker.create).mockReturnValue(mockProxy as any);
212
+
213
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
214
+ await orchestrator.initialize();
215
+ await orchestrator.start();
216
+
217
+ // BuildEngine should be created and run() called
218
+ expect(createBuildEngine).toHaveBeenCalledOnce();
219
+ expect(mockEngines[0].run).toHaveBeenCalledWith({ js: true, dts: true });
220
+ expect(mockEngines[0].stop).toHaveBeenCalled();
221
+ });
222
+
223
+ it("creates BuildEngine for serverPackages with merged env", async () => {
224
+ setupDefaults({
225
+ packages: {
226
+ "demo-server": {
227
+ target: "server",
228
+ env: { DB_HOST: "localhost" },
229
+ },
230
+ },
231
+ });
232
+
233
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
234
+ await orchestrator.initialize();
235
+ await orchestrator.start();
236
+
237
+ expect(createBuildEngine).toHaveBeenCalledWith(
238
+ expect.objectContaining({
239
+ name: "demo-server",
240
+ config: expect.objectContaining({
241
+ target: "server",
242
+ env: expect.objectContaining({
243
+ VER: "1.0.0",
244
+ DEV: "false",
245
+ DB_HOST: "localhost",
246
+ }),
247
+ }),
248
+ }),
249
+ expect.any(Object),
250
+ );
251
+ });
252
+
253
+ it("creates BuildEngine for serverPackages with pm2 config", async () => {
254
+ setupDefaults({
255
+ packages: {
256
+ "demo-server": {
257
+ target: "server",
258
+ pm2: { name: "demo" },
259
+ },
260
+ },
261
+ });
262
+
263
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
264
+ await orchestrator.initialize();
265
+ await orchestrator.start();
266
+
267
+ expect(createBuildEngine).toHaveBeenCalledWith(
268
+ expect.objectContaining({
269
+ config: expect.objectContaining({
270
+ pm2: { name: "demo" },
271
+ }),
272
+ }),
273
+ expect.any(Object),
274
+ );
275
+ });
276
+
277
+ it("calls copySrcFiles when copySrc is configured", async () => {
278
+ setupDefaults({
279
+ packages: {
280
+ "core-node": {
281
+ target: "node",
282
+ publish: { type: "npm" },
283
+ copySrc: ["README.md"],
284
+ },
285
+ },
286
+ });
287
+ const mockProxy = createMockWorkerProxy();
288
+ vi.mocked(Worker.create).mockReturnValue(mockProxy as any);
289
+
290
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
291
+ await orchestrator.initialize();
292
+ await orchestrator.start();
293
+
294
+ expect(copySrcFiles).toHaveBeenCalled();
295
+ });
296
+
297
+ it("does not call copySrcFiles when copySrc is not configured", async () => {
298
+ setupDefaults({
299
+ packages: {
300
+ "core-common": { target: "neutral", publish: { type: "npm" } },
301
+ },
302
+ });
303
+ const mockProxy = createMockWorkerProxy();
304
+ vi.mocked(Worker.create).mockReturnValue(mockProxy as any);
305
+
306
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
307
+ await orchestrator.initialize();
308
+ await orchestrator.start();
309
+
310
+ expect(copySrcFiles).not.toHaveBeenCalled();
311
+ });
312
+
313
+ it("stops engine even when build fails", async () => {
314
+ setupDefaults({
315
+ packages: {
316
+ "core-common": { target: "neutral", publish: { type: "npm" } },
317
+ },
318
+ });
319
+ // Override createBuildEngine to return engine with failing run()
320
+ vi.mocked(createBuildEngine).mockReturnValue({
321
+ run: vi.fn().mockRejectedValue(new Error("build failed")),
322
+ startWatch: vi.fn(),
323
+ stop: vi.fn().mockResolvedValue(undefined),
324
+ } as any);
325
+ const mockProxy = createMockWorkerProxy();
326
+ vi.mocked(Worker.create).mockReturnValue(mockProxy as any);
327
+
328
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
329
+ await orchestrator.initialize();
330
+ await orchestrator.start();
331
+
332
+ // Engine stop should be called even after failure
333
+ const engineMock = vi.mocked(createBuildEngine).mock.results[0].value;
334
+ expect(engineMock.stop).toHaveBeenCalled();
335
+ });
336
+
337
+ it("returns false when all builds succeed", async () => {
338
+ setupDefaults({
339
+ packages: {
340
+ "core-common": { target: "neutral", publish: { type: "npm" } },
341
+ },
342
+ });
343
+ const mockProxy = createMockWorkerProxy();
344
+ vi.mocked(Worker.create).mockReturnValue(mockProxy as any);
345
+
346
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
347
+ await orchestrator.initialize();
348
+ const hasError = await orchestrator.start();
349
+
350
+ expect(hasError).toBe(false);
351
+ expect(mockLogger.info).toHaveBeenCalledWith("Build completed");
352
+ });
353
+
354
+ it("returns true and logs error when any build fails", async () => {
355
+ setupDefaults({
356
+ packages: {
357
+ "core-common": { target: "neutral", publish: { type: "npm" } },
358
+ },
359
+ });
360
+ vi.mocked(createBuildEngine).mockReturnValue({
361
+ run: vi.fn().mockResolvedValue({
362
+ success: false,
363
+ js: { success: false, errors: ["Module not found"], warnings: [] },
364
+ dts: { success: true, errors: [], warnings: [], diagnostics: [] },
365
+ }),
366
+ startWatch: vi.fn(),
367
+ stop: vi.fn().mockResolvedValue(undefined),
368
+ } as any);
369
+ const mockProxy = createMockWorkerProxy();
370
+ vi.mocked(Worker.create).mockReturnValue(mockProxy as any);
371
+
372
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
373
+ await orchestrator.initialize();
374
+ const hasError = await orchestrator.start();
375
+
376
+ expect(hasError).toBe(true);
377
+ expect(mockLogger.error).toHaveBeenCalledWith("Build failed");
378
+ });
379
+
380
+ it("returns false when no packages to build", async () => {
381
+ setupDefaults({
382
+ packages: {
383
+ "sd-claude": { target: "scripts" } as any,
384
+ },
385
+ });
386
+
387
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
388
+ await orchestrator.initialize();
389
+ const hasError = await orchestrator.start();
390
+
391
+ expect(hasError).toBe(false);
392
+ });
393
+
394
+ it("limits concurrent build engine workers to maxConcurrency", async () => {
395
+ // Use enough packages to exceed any reasonable CPU-based concurrency limit
396
+ const pkgCount = 50;
397
+ const packages: Record<string, any> = {};
398
+ for (let i = 0; i < pkgCount; i++) {
399
+ packages[`pkg-${i}`] = { target: "neutral", publish: { type: "npm" } };
400
+ }
401
+ setupDefaults({ packages });
402
+
403
+ let active = 0;
404
+ let maxActive = 0;
405
+
406
+ vi.mocked(createBuildEngine).mockImplementation(() => {
407
+ const engine = {
408
+ run: vi.fn(async () => {
409
+ active++;
410
+ maxActive = Math.max(maxActive, active);
411
+ await new Promise((resolve) => setTimeout(resolve, 5));
412
+ active--;
413
+ return {
414
+ success: true,
415
+ js: { success: true, errors: [], warnings: [] },
416
+ dts: { success: true, errors: [], warnings: [], diagnostics: [] },
417
+ };
418
+ }),
419
+ startWatch: vi.fn(),
420
+ stop: vi.fn().mockResolvedValue(undefined),
421
+ };
422
+ mockEngines.push(engine);
423
+ return engine as any;
424
+ });
425
+ const mockProxy = createMockWorkerProxy();
426
+ vi.mocked(Worker.create).mockReturnValue(mockProxy as any);
427
+
428
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
429
+ await orchestrator.initialize();
430
+ await orchestrator.start();
431
+
432
+ // Without concurrency limit, all 50 would start simultaneously (maxActive = 50)
433
+ // With limit, maxActive should be < pkgCount
434
+ expect(maxActive).toBeLessThan(pkgCount);
435
+ expect(maxActive).toBeGreaterThan(0);
436
+ expect(mockEngines).toHaveLength(pkgCount);
437
+ expect(mockEngines.every((e) => e.stop.mock.calls.length > 0)).toBe(true);
438
+ });
439
+
440
+ it("runs lint independently of build concurrency limit", async () => {
441
+ const packages: Record<string, any> = {};
442
+ for (let i = 0; i < 5; i++) {
443
+ packages[`pkg-${i}`] = { target: "neutral", publish: { type: "npm" } };
444
+ }
445
+ setupDefaults({ packages });
446
+
447
+ let lintStarted = false;
448
+ let buildCompletedCount = 0;
449
+
450
+ vi.mocked(createBuildEngine).mockImplementation(() => {
451
+ const engine = {
452
+ run: vi.fn(async () => {
453
+ await new Promise((resolve) => setTimeout(resolve, 50));
454
+ buildCompletedCount++;
455
+ return {
456
+ success: true,
457
+ js: { success: true, errors: [], warnings: [] },
458
+ dts: { success: true, errors: [], warnings: [], diagnostics: [] },
459
+ };
460
+ }),
461
+ startWatch: vi.fn(),
462
+ stop: vi.fn().mockResolvedValue(undefined),
463
+ };
464
+ mockEngines.push(engine);
465
+ return engine as any;
466
+ });
467
+
468
+ const mockProxy = createMockWorkerProxy({
469
+ lint: vi.fn(() => {
470
+ lintStarted = true;
471
+ // Lint starts immediately, not blocked by build concurrency
472
+ expect(buildCompletedCount).toBe(0);
473
+ return { success: true };
474
+ }),
475
+ });
476
+ vi.mocked(Worker.create).mockReturnValue(mockProxy as any);
477
+
478
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
479
+ await orchestrator.initialize();
480
+ await orchestrator.start();
481
+
482
+ expect(lintStarted).toBe(true);
483
+ });
484
+
485
+ it("logs warnings from build results", async () => {
486
+ setupDefaults({
487
+ packages: {
488
+ "core-common": { target: "neutral", publish: { type: "npm" } },
489
+ },
490
+ });
491
+ vi.mocked(createBuildEngine).mockReturnValue({
492
+ run: vi.fn().mockResolvedValue({
493
+ success: true,
494
+ js: { success: true, errors: [], warnings: ["Unused variable"] },
495
+ dts: { success: true, errors: [], warnings: [], diagnostics: [] },
496
+ }),
497
+ startWatch: vi.fn(),
498
+ stop: vi.fn().mockResolvedValue(undefined),
499
+ } as any);
500
+ const mockProxy = createMockWorkerProxy();
501
+ vi.mocked(Worker.create).mockReturnValue(mockProxy as any);
502
+
503
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
504
+ await orchestrator.initialize();
505
+ await orchestrator.start();
506
+
507
+ expect(mockLogger.warn).toHaveBeenCalled();
508
+ });
509
+ });
510
+
511
+ describe("classifyPackages", () => {
512
+ // Acceptance: Scenario "client target 패키지 분류"
513
+ it("classifies client target packages to clientPackages", () => {
514
+ const result = classifyPackages(
515
+ { "my-client": { target: "client", server: "my-server" } as any },
516
+ [],
517
+ );
518
+ expect(result.clientPackages).toHaveLength(1);
519
+ expect(result.clientPackages[0].name).toBe("my-client");
520
+ expect(result.clientPackages[0].config.target).toBe("client");
521
+ });
522
+
523
+ // Acceptance: Scenario "targets 필터로 특정 client 패키지만 분류"
524
+ it("filters clientPackages by targets", () => {
525
+ const result = classifyPackages(
526
+ {
527
+ "client-a": { target: "client", server: "srv" } as any,
528
+ "client-b": { target: "client", server: "srv" } as any,
529
+ },
530
+ ["client-a"],
531
+ );
532
+ expect(result.clientPackages).toHaveLength(1);
533
+ expect(result.clientPackages[0].name).toBe("client-a");
534
+ });
535
+
536
+ // Acceptance: Scenario "targets 필터에 미포함된 client 패키지 제외"
537
+ it("excludes client packages not in targets", () => {
538
+ const result = classifyPackages(
539
+ { "my-client": { target: "client", server: "srv" } as any },
540
+ ["other-pkg"],
541
+ );
542
+ expect(result.clientPackages).toHaveLength(0);
543
+ });
544
+
545
+ // Acceptance: Scenario "scripts target은 여전히 제외"
546
+ it("still excludes scripts target", () => {
547
+ const result = classifyPackages(
548
+ { "sd-claude": { target: "scripts" } },
549
+ [],
550
+ );
551
+ expect(result.buildPackages).toHaveLength(0);
552
+ expect(result.serverPackages).toHaveLength(0);
553
+ expect(result.clientPackages).toHaveLength(0);
554
+ });
555
+
556
+ // Acceptance: Scenario "client 패키지가 0개인 경우"
557
+ it("returns empty clientPackages when no client packages exist", () => {
558
+ const result = classifyPackages(
559
+ {
560
+ "core-common": { target: "neutral", publish: { type: "npm" } } as any,
561
+ "demo-server": { target: "server" } as any,
562
+ },
563
+ [],
564
+ );
565
+ expect(result.clientPackages).toHaveLength(0);
566
+ expect(result.buildPackages).toHaveLength(1);
567
+ expect(result.serverPackages).toHaveLength(1);
568
+ });
569
+
570
+ // Unit: mixed packages — all types classified correctly
571
+ it("correctly classifies all package types together", () => {
572
+ const result = classifyPackages(
573
+ {
574
+ "core-common": { target: "neutral", publish: { type: "npm" } } as any,
575
+ "demo-server": { target: "server" } as any,
576
+ "my-client": { target: "client", server: "srv" } as any,
577
+ "sd-claude": { target: "scripts" },
578
+ },
579
+ [],
580
+ );
581
+ expect(result.buildPackages).toHaveLength(1);
582
+ expect(result.buildPackages[0].name).toBe("core-common");
583
+ expect(result.serverPackages).toHaveLength(1);
584
+ expect(result.serverPackages[0].name).toBe("demo-server");
585
+ expect(result.clientPackages).toHaveLength(1);
586
+ expect(result.clientPackages[0].name).toBe("my-client");
587
+ });
588
+ });
589
+
590
+ describe("BuildOrchestrator client build", () => {
591
+ // Acceptance: Scenario "client 패키지 프로덕션 빌드 성공"
592
+ it("uses ViteEngine for client packages with js:true dts:false", async () => {
593
+ setupDefaults({
594
+ packages: {
595
+ "my-client": { target: "client", server: "my-server" } as any,
596
+ },
597
+ });
598
+ vi.mocked(createBuildEngine).mockReturnValue({
599
+ run: vi.fn().mockResolvedValue({
600
+ success: true,
601
+ js: { success: true, errors: [], warnings: [] },
602
+ dts: { success: true, errors: [], warnings: [], diagnostics: [] },
603
+ }),
604
+ startWatch: vi.fn(),
605
+ stop: vi.fn().mockResolvedValue(undefined),
606
+ } as any);
607
+ const mockProxy = createMockWorkerProxy();
608
+ vi.mocked(Worker.create).mockReturnValue(mockProxy as any);
609
+
610
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
611
+ await orchestrator.initialize();
612
+ await orchestrator.start();
613
+
614
+ expect(createBuildEngine).toHaveBeenCalledWith(
615
+ expect.objectContaining({
616
+ name: "my-client",
617
+ config: expect.objectContaining({ target: "client" }),
618
+ }),
619
+ expect.any(Object),
620
+ );
621
+ const engineMock = vi.mocked(createBuildEngine).mock.results[0].value;
622
+ expect(engineMock.run).toHaveBeenCalledWith({ js: true, dts: false });
623
+ expect(engineMock.stop).toHaveBeenCalled();
624
+ });
625
+
626
+ // Acceptance: Scenario "client 패키지 빌드 실패"
627
+ it("returns true when client build fails", async () => {
628
+ setupDefaults({
629
+ packages: {
630
+ "my-client": { target: "client", server: "my-server" } as any,
631
+ },
632
+ });
633
+ vi.mocked(createBuildEngine).mockReturnValue({
634
+ run: vi.fn().mockResolvedValue({
635
+ success: false,
636
+ js: { success: false, errors: ["Template error"], warnings: [] },
637
+ dts: { success: true, errors: [], warnings: [], diagnostics: [] },
638
+ }),
639
+ startWatch: vi.fn(),
640
+ stop: vi.fn().mockResolvedValue(undefined),
641
+ } as any);
642
+ const mockProxy = createMockWorkerProxy();
643
+ vi.mocked(Worker.create).mockReturnValue(mockProxy as any);
644
+
645
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
646
+ await orchestrator.initialize();
647
+ const hasError = await orchestrator.start();
648
+
649
+ expect(hasError).toBe(true);
650
+ expect(mockLogger.error).toHaveBeenCalledWith("Build failed");
651
+ });
652
+
653
+ // Acceptance: Scenario "client 빌드에 env 주입하지 않음"
654
+ it("does not inject baseEnv for client packages", async () => {
655
+ setupDefaults({
656
+ packages: {
657
+ "my-client": { target: "client", server: "my-server" } as any,
658
+ },
659
+ });
660
+ const mockProxy = createMockWorkerProxy();
661
+ vi.mocked(Worker.create).mockReturnValue(mockProxy as any);
662
+
663
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
664
+ await orchestrator.initialize();
665
+ await orchestrator.start();
666
+
667
+ const callArgs = vi.mocked(createBuildEngine).mock.calls[0][0];
668
+ expect(callArgs.config).not.toHaveProperty("env");
669
+ });
670
+
671
+ // Acceptance: Scenario "client 패키지 dist 폴더 clean"
672
+ it("cleans client package dist folder before building", async () => {
673
+ setupDefaults({
674
+ packages: {
675
+ "my-client": { target: "client", server: "my-server" } as any,
676
+ },
677
+ });
678
+ const mockProxy = createMockWorkerProxy();
679
+ vi.mocked(Worker.create).mockReturnValue(mockProxy as any);
680
+
681
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
682
+ await orchestrator.initialize();
683
+ await orchestrator.start();
684
+
685
+ expect(fsx.rm).toHaveBeenCalledWith(
686
+ expect.stringContaining("my-client"),
687
+ );
688
+ });
689
+
690
+ // Acceptance: Scenario "client 패키지 lint 포함"
691
+ it("includes client packages in lint targets", async () => {
692
+ setupDefaults({
693
+ packages: {
694
+ "my-client": { target: "client", server: "my-server" } as any,
695
+ },
696
+ });
697
+ const mockProxy = createMockWorkerProxy();
698
+ vi.mocked(Worker.create).mockReturnValue(mockProxy as any);
699
+
700
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
701
+ await orchestrator.initialize();
702
+ await orchestrator.start();
703
+
704
+ expect(mockProxy.lint).toHaveBeenCalledWith(
705
+ expect.objectContaining({
706
+ targets: expect.arrayContaining(["packages/my-client"]),
707
+ }),
708
+ );
709
+ });
710
+
711
+ // Unit: client engine.stop() called even on failure
712
+ it("stops client engine even when build fails", async () => {
713
+ setupDefaults({
714
+ packages: {
715
+ "my-client": { target: "client", server: "my-server" } as any,
716
+ },
717
+ });
718
+ vi.mocked(createBuildEngine).mockReturnValue({
719
+ run: vi.fn().mockRejectedValue(new Error("build crashed")),
720
+ startWatch: vi.fn(),
721
+ stop: vi.fn().mockResolvedValue(undefined),
722
+ } as any);
723
+ const mockProxy = createMockWorkerProxy();
724
+ vi.mocked(Worker.create).mockReturnValue(mockProxy as any);
725
+
726
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
727
+ await orchestrator.initialize();
728
+ await orchestrator.start();
729
+
730
+ const engineMock = vi.mocked(createBuildEngine).mock.results[0].value;
731
+ expect(engineMock.stop).toHaveBeenCalled();
732
+ });
733
+ });
734
+
735
+ describe("BuildOrchestrator target validation", () => {
736
+ it("throws error for unknown target during initialize", async () => {
737
+ setupDefaults({
738
+ packages: {
739
+ "core-common": { target: "neutral", publish: { type: "npm" } },
740
+ },
741
+ });
742
+
743
+ const orchestrator = new BuildOrchestrator({ targets: ["nonexistent"], options: [] });
744
+ await expect(orchestrator.initialize()).rejects.toThrow("Unknown target: nonexistent");
745
+ });
746
+
747
+ it("passes with valid targets during initialize", async () => {
748
+ setupDefaults({
749
+ packages: {
750
+ "core-common": { target: "neutral", publish: { type: "npm" } },
751
+ },
752
+ });
753
+ const mockProxy = createMockWorkerProxy();
754
+ vi.mocked(Worker.create).mockReturnValue(mockProxy as any);
755
+
756
+ const orchestrator = new BuildOrchestrator({ targets: ["core-common"], options: [] });
757
+ await expect(orchestrator.initialize()).resolves.not.toThrow();
758
+ });
759
+
760
+ it("passes with empty targets during initialize", async () => {
761
+ setupDefaults({
762
+ packages: {
763
+ "core-common": { target: "neutral", publish: { type: "npm" } },
764
+ },
765
+ });
766
+ const mockProxy = createMockWorkerProxy();
767
+ vi.mocked(Worker.create).mockReturnValue(mockProxy as any);
768
+
769
+ const orchestrator = new BuildOrchestrator({ targets: [], options: [] });
770
+ await expect(orchestrator.initialize()).resolves.not.toThrow();
771
+ });
772
+ });