@simplysm/sd-cli 14.0.41 → 14.0.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (321) hide show
  1. package/dist/angular/angular-compiler.d.ts +0 -35
  2. package/dist/angular/angular-compiler.d.ts.map +1 -1
  3. package/dist/angular/angular-compiler.js +0 -374
  4. package/dist/angular/angular-compiler.js.map +1 -1
  5. package/dist/angular/hmr-candidates.d.ts +13 -0
  6. package/dist/angular/hmr-candidates.d.ts.map +1 -0
  7. package/dist/angular/hmr-candidates.js +230 -0
  8. package/dist/angular/hmr-candidates.js.map +1 -0
  9. package/dist/angular/ngtsc-build-core.d.ts +29 -34
  10. package/dist/angular/ngtsc-build-core.d.ts.map +1 -1
  11. package/dist/angular/ngtsc-build-core.js +90 -51
  12. package/dist/angular/ngtsc-build-core.js.map +1 -1
  13. package/dist/angular/vite-angular-plugin.d.ts +1 -1
  14. package/dist/angular/vite-angular-plugin.d.ts.map +1 -1
  15. package/dist/angular/vite-angular-plugin.js +63 -56
  16. package/dist/angular/vite-angular-plugin.js.map +1 -1
  17. package/dist/angular/web-worker-transformer.d.ts +9 -0
  18. package/dist/angular/web-worker-transformer.d.ts.map +1 -0
  19. package/dist/angular/web-worker-transformer.js +73 -0
  20. package/dist/angular/web-worker-transformer.js.map +1 -0
  21. package/dist/capacitor/capacitor.d.ts.map +1 -1
  22. package/dist/capacitor/capacitor.js +6 -4
  23. package/dist/capacitor/capacitor.js.map +1 -1
  24. package/dist/commands/check.d.ts +1 -1
  25. package/dist/commands/check.d.ts.map +1 -1
  26. package/dist/commands/check.js +15 -65
  27. package/dist/commands/check.js.map +1 -1
  28. package/dist/commands/publish/deployment-phase.d.ts.map +1 -1
  29. package/dist/commands/publish/deployment-phase.js +13 -5
  30. package/dist/commands/publish/deployment-phase.js.map +1 -1
  31. package/dist/commands/publish/npm-publisher.js +1 -1
  32. package/dist/commands/publish/npm-publisher.js.map +1 -1
  33. package/dist/commands/publish/publish-command.js +1 -1
  34. package/dist/commands/publish/publish-command.js.map +1 -1
  35. package/dist/commands/publish/version-upgrade.js +1 -1
  36. package/dist/commands/publish/version-upgrade.js.map +1 -1
  37. package/dist/commands/replace-deps.d.ts.map +1 -1
  38. package/dist/commands/replace-deps.js +2 -1
  39. package/dist/commands/replace-deps.js.map +1 -1
  40. package/dist/deps/replace-deps/collect-deps.d.ts.map +1 -1
  41. package/dist/deps/replace-deps/collect-deps.js +5 -2
  42. package/dist/deps/replace-deps/collect-deps.js.map +1 -1
  43. package/dist/deps/replace-deps/replace-deps.d.ts +21 -3
  44. package/dist/deps/replace-deps/replace-deps.d.ts.map +1 -1
  45. package/dist/deps/replace-deps/replace-deps.js +107 -62
  46. package/dist/deps/replace-deps/replace-deps.js.map +1 -1
  47. package/dist/electron/electron.js +7 -7
  48. package/dist/electron/electron.js.map +1 -1
  49. package/dist/engines/BaseEngine.d.ts.map +1 -1
  50. package/dist/engines/BaseEngine.js +2 -5
  51. package/dist/engines/BaseEngine.js.map +1 -1
  52. package/dist/engines/EsbuildClientEngine.d.ts.map +1 -1
  53. package/dist/engines/EsbuildClientEngine.js +16 -9
  54. package/dist/engines/EsbuildClientEngine.js.map +1 -1
  55. package/dist/engines/NgtscEngine.d.ts +4 -4
  56. package/dist/engines/NgtscEngine.d.ts.map +1 -1
  57. package/dist/engines/NgtscEngine.js +5 -5
  58. package/dist/engines/NgtscEngine.js.map +1 -1
  59. package/dist/engines/TscEngine.d.ts.map +1 -1
  60. package/dist/engines/TscEngine.js +0 -2
  61. package/dist/engines/TscEngine.js.map +1 -1
  62. package/dist/engines/types.d.ts +2 -0
  63. package/dist/engines/types.d.ts.map +1 -1
  64. package/dist/esbuild/esbuild-angular-compiler-plugin.d.ts +36 -0
  65. package/dist/esbuild/esbuild-angular-compiler-plugin.d.ts.map +1 -0
  66. package/dist/esbuild/esbuild-angular-compiler-plugin.js +464 -0
  67. package/dist/esbuild/esbuild-angular-compiler-plugin.js.map +1 -0
  68. package/dist/esbuild/esbuild-client-config.d.ts +8 -2
  69. package/dist/esbuild/esbuild-client-config.d.ts.map +1 -1
  70. package/dist/esbuild/esbuild-client-config.js +48 -33
  71. package/dist/esbuild/esbuild-client-config.js.map +1 -1
  72. package/dist/esbuild/esbuild-tsc-plugin.d.ts +4 -1
  73. package/dist/esbuild/esbuild-tsc-plugin.d.ts.map +1 -1
  74. package/dist/esbuild/esbuild-tsc-plugin.js +27 -23
  75. package/dist/esbuild/esbuild-tsc-plugin.js.map +1 -1
  76. package/dist/esbuild/file-reference-tracker.d.ts +24 -0
  77. package/dist/esbuild/file-reference-tracker.d.ts.map +1 -0
  78. package/dist/esbuild/file-reference-tracker.js +57 -0
  79. package/dist/esbuild/file-reference-tracker.js.map +1 -0
  80. package/dist/esbuild/lmdb-cache-store.d.ts +18 -0
  81. package/dist/esbuild/lmdb-cache-store.d.ts.map +1 -0
  82. package/dist/esbuild/lmdb-cache-store.js +41 -0
  83. package/dist/esbuild/lmdb-cache-store.js.map +1 -0
  84. package/dist/esbuild/load-result-cache.d.ts +17 -0
  85. package/dist/esbuild/load-result-cache.d.ts.map +1 -0
  86. package/dist/esbuild/load-result-cache.js +61 -0
  87. package/dist/esbuild/load-result-cache.js.map +1 -0
  88. package/dist/index.d.ts +3 -0
  89. package/dist/index.d.ts.map +1 -1
  90. package/dist/index.js +2 -0
  91. package/dist/index.js.map +1 -1
  92. package/dist/lint/lint-core.js +7 -7
  93. package/dist/lint/lint-core.js.map +1 -1
  94. package/dist/orchestrators/BaseOrchestrator.js +2 -2
  95. package/dist/orchestrators/BaseOrchestrator.js.map +1 -1
  96. package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
  97. package/dist/orchestrators/BuildOrchestrator.js +5 -19
  98. package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
  99. package/dist/orchestrators/DevOrchestrator.js +5 -5
  100. package/dist/orchestrators/DevOrchestrator.js.map +1 -1
  101. package/dist/orchestrators/WatchOrchestrator.js +6 -6
  102. package/dist/orchestrators/WatchOrchestrator.js.map +1 -1
  103. package/dist/runtime/ResultCollector.d.ts +1 -0
  104. package/dist/runtime/ResultCollector.d.ts.map +1 -1
  105. package/dist/runtime/ResultCollector.js.map +1 -1
  106. package/dist/runtime/engine-watch-events.d.ts.map +1 -1
  107. package/dist/runtime/engine-watch-events.js +3 -0
  108. package/dist/runtime/engine-watch-events.js.map +1 -1
  109. package/dist/runtime/rebuild-manager.js +1 -1
  110. package/dist/runtime/rebuild-manager.js.map +1 -1
  111. package/dist/runtime/worker-utils.js +1 -1
  112. package/dist/runtime/worker-utils.js.map +1 -1
  113. package/dist/sd-cli-entry.d.ts.map +1 -1
  114. package/dist/sd-cli-entry.js +4 -3
  115. package/dist/sd-cli-entry.js.map +1 -1
  116. package/dist/sd-cli.js +3 -3
  117. package/dist/sd-cli.js.map +1 -1
  118. package/dist/ts-compiler/SdTsCompiler.d.ts +39 -0
  119. package/dist/ts-compiler/SdTsCompiler.d.ts.map +1 -0
  120. package/dist/ts-compiler/SdTsCompiler.js +593 -0
  121. package/dist/ts-compiler/SdTsCompiler.js.map +1 -0
  122. package/dist/ts-compiler/sd-ts-compiler-options.d.ts +40 -0
  123. package/dist/ts-compiler/sd-ts-compiler-options.d.ts.map +1 -0
  124. package/dist/ts-compiler/sd-ts-compiler-options.js +2 -0
  125. package/dist/ts-compiler/sd-ts-compiler-options.js.map +1 -0
  126. package/dist/ts-compiler/sd-ts-compiler-result.d.ts +34 -0
  127. package/dist/ts-compiler/sd-ts-compiler-result.d.ts.map +1 -0
  128. package/dist/ts-compiler/sd-ts-compiler-result.js +2 -0
  129. package/dist/ts-compiler/sd-ts-compiler-result.js.map +1 -0
  130. package/dist/utils/copy-public.d.ts +6 -4
  131. package/dist/utils/copy-public.d.ts.map +1 -1
  132. package/dist/utils/copy-public.js +9 -7
  133. package/dist/utils/copy-public.js.map +1 -1
  134. package/dist/utils/diagnostic-utils.d.ts +2 -3
  135. package/dist/utils/diagnostic-utils.d.ts.map +1 -1
  136. package/dist/utils/diagnostic-utils.js +8 -9
  137. package/dist/utils/diagnostic-utils.js.map +1 -1
  138. package/dist/utils/output-utils.d.ts +8 -2
  139. package/dist/utils/output-utils.d.ts.map +1 -1
  140. package/dist/utils/output-utils.js +32 -8
  141. package/dist/utils/output-utils.js.map +1 -1
  142. package/dist/workers/client.worker.d.ts +1 -1
  143. package/dist/workers/client.worker.d.ts.map +1 -1
  144. package/dist/workers/client.worker.js +136 -110
  145. package/dist/workers/client.worker.js.map +1 -1
  146. package/dist/workers/library-build.worker.d.ts +0 -2
  147. package/dist/workers/library-build.worker.d.ts.map +1 -1
  148. package/dist/workers/library-build.worker.js +147 -70
  149. package/dist/workers/library-build.worker.js.map +1 -1
  150. package/dist/workers/server-build.worker.d.ts.map +1 -1
  151. package/dist/workers/server-build.worker.js +30 -57
  152. package/dist/workers/server-build.worker.js.map +1 -1
  153. package/dist/workers/server-esbuild-context.d.ts +7 -0
  154. package/dist/workers/server-esbuild-context.d.ts.map +1 -1
  155. package/dist/workers/server-esbuild-context.js +11 -2
  156. package/dist/workers/server-esbuild-context.js.map +1 -1
  157. package/package.json +7 -6
  158. package/src/angular/angular-compiler.ts +0 -502
  159. package/src/angular/hmr-candidates.ts +295 -0
  160. package/src/angular/ngtsc-build-core.ts +125 -92
  161. package/src/angular/vite-angular-plugin.ts +71 -65
  162. package/src/angular/web-worker-transformer.ts +117 -0
  163. package/src/capacitor/capacitor.ts +6 -4
  164. package/src/commands/check.ts +17 -76
  165. package/src/commands/publish/deployment-phase.ts +11 -7
  166. package/src/commands/publish/npm-publisher.ts +1 -1
  167. package/src/commands/publish/publish-command.ts +1 -1
  168. package/src/commands/publish/version-upgrade.ts +1 -1
  169. package/src/commands/replace-deps.ts +3 -1
  170. package/src/deps/replace-deps/collect-deps.ts +4 -2
  171. package/src/deps/replace-deps/replace-deps.ts +114 -66
  172. package/src/electron/electron.ts +7 -7
  173. package/src/engines/BaseEngine.ts +2 -6
  174. package/src/engines/EsbuildClientEngine.ts +16 -10
  175. package/src/engines/NgtscEngine.ts +7 -7
  176. package/src/engines/TscEngine.ts +0 -2
  177. package/src/engines/types.ts +2 -0
  178. package/src/esbuild/esbuild-angular-compiler-plugin.ts +647 -0
  179. package/src/esbuild/esbuild-client-config.ts +57 -41
  180. package/src/esbuild/esbuild-tsc-plugin.ts +33 -23
  181. package/src/esbuild/file-reference-tracker.ts +61 -0
  182. package/src/esbuild/lmdb-cache-store.ts +46 -0
  183. package/src/esbuild/load-result-cache.ts +85 -0
  184. package/src/index.ts +5 -0
  185. package/src/lint/lint-core.ts +7 -7
  186. package/src/orchestrators/BaseOrchestrator.ts +2 -2
  187. package/src/orchestrators/BuildOrchestrator.ts +5 -24
  188. package/src/orchestrators/DevOrchestrator.ts +5 -5
  189. package/src/orchestrators/WatchOrchestrator.ts +6 -6
  190. package/src/runtime/ResultCollector.ts +1 -0
  191. package/src/runtime/engine-watch-events.ts +3 -0
  192. package/src/runtime/rebuild-manager.ts +1 -1
  193. package/src/runtime/worker-utils.ts +1 -1
  194. package/src/sd-cli-entry.ts +5 -3
  195. package/src/sd-cli.ts +4 -4
  196. package/src/ts-compiler/SdTsCompiler.ts +815 -0
  197. package/src/ts-compiler/sd-ts-compiler-options.ts +46 -0
  198. package/src/ts-compiler/sd-ts-compiler-result.ts +34 -0
  199. package/src/utils/copy-public.ts +9 -6
  200. package/src/utils/diagnostic-utils.ts +8 -9
  201. package/src/utils/output-utils.ts +38 -8
  202. package/src/workers/client.worker.ts +160 -126
  203. package/src/workers/library-build.worker.ts +187 -75
  204. package/src/workers/server-build.worker.ts +31 -61
  205. package/src/workers/server-esbuild-context.ts +14 -2
  206. package/tests/angular/fixtures/packages/basic-app/dist/styles.css +3 -0
  207. package/tests/angular/fixtures/packages/basic-app/scss/styles.scss +5 -0
  208. package/tests/angular/vite-angular-plugin-sdtscompiler.verify.md +13 -0
  209. package/tests/angular/web-worker-transformer.spec.ts +154 -0
  210. package/tests/capacitor/capacitor-build.spec.ts +1 -1
  211. package/tests/capacitor/capacitor-icon.spec.ts +1 -1
  212. package/tests/capacitor/capacitor-init.spec.ts +1 -1
  213. package/tests/commands/check.spec.ts +90 -104
  214. package/tests/commands/publish.spec.ts +12 -4
  215. package/tests/commands/slice3-severity-cleanup.verify.md +12 -0
  216. package/tests/deps/replace-deps/collect-deps.acc.spec.ts +62 -0
  217. package/tests/deps/replace-deps/collect-deps.spec.ts +49 -0
  218. package/tests/deps/replace-deps/replace-deps-filter.spec.ts +103 -0
  219. package/tests/deps/replace-deps/replace-deps-setup.acc.spec.ts +156 -0
  220. package/tests/electron/electron.spec.ts +4 -1
  221. package/tests/engines/engine-adapter-isolation.spec.ts +5 -6
  222. package/tests/engines/engine-duplicate-output-removal.verify.md +10 -0
  223. package/tests/engines/esbuild-client-engine.acc.spec.ts +79 -0
  224. package/tests/engines/esbuild-client-engine.spec.ts +73 -3
  225. package/tests/esbuild/esbuild-angular-compiler-plugin-hmr.verify.md +23 -0
  226. package/tests/esbuild/esbuild-angular-compiler-plugin-onload.verify.md +21 -0
  227. package/tests/esbuild/esbuild-angular-compiler-plugin-onstart-extraction.verify.md +16 -0
  228. package/tests/esbuild/esbuild-angular-compiler-plugin-sdtscompiler.verify.md +15 -0
  229. package/tests/esbuild/esbuild-angular-compiler-plugin-stylesheet.verify.md +31 -0
  230. package/tests/esbuild/esbuild-angular-compiler-plugin-worker.verify.md +31 -0
  231. package/tests/esbuild/esbuild-angular-compiler-plugin.spec.ts +397 -0
  232. package/tests/esbuild/esbuild-angular-compiler-plugin.verify.md +21 -0
  233. package/tests/esbuild/esbuild-tsc-plugin-imports.verify.md +13 -0
  234. package/tests/esbuild/esbuild-tsc-plugin.acc.spec.ts +56 -111
  235. package/tests/esbuild/esbuild-tsc-plugin.spec.ts +116 -52
  236. package/tests/esbuild/file-reference-tracker.spec.ts +99 -0
  237. package/tests/esbuild/lmdb-cache-store.spec.ts +58 -0
  238. package/tests/esbuild/load-result-cache.acc.spec.ts +55 -0
  239. package/tests/esbuild/load-result-cache.spec.ts +133 -0
  240. package/tests/orchestrators/build-orchestrator.spec.ts +4 -3
  241. package/tests/orchestrators/dev-orchestrator.spec.ts +5 -5
  242. package/tests/orchestrators/slice1-stdout-to-consola.verify.md +10 -0
  243. package/tests/orchestrators/typecheck-orchestrator.spec.ts +1 -1
  244. package/tests/orchestrators/watch-orchestrator.spec.ts +7 -7
  245. package/tests/runtime/result-collector.spec.ts +64 -0
  246. package/tests/sd-cli-entry.spec.ts +3 -4
  247. package/tests/sd-cli-log-tag.verify.md +11 -0
  248. package/tests/ts-compiler/SdTsCompiler-affected-files.verify.md +8 -0
  249. package/tests/ts-compiler/SdTsCompiler-diagnostics.verify.md +12 -0
  250. package/tests/ts-compiler/SdTsCompiler-emit.verify.md +9 -0
  251. package/tests/ts-compiler/SdTsCompiler.acc.spec.ts +603 -0
  252. package/tests/ts-compiler/SdTsCompiler.spec.ts +265 -0
  253. package/tests/ts-compiler/SdTsCompiler.verify.md +41 -0
  254. package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck-browser.tsbuildinfo +1 -0
  255. package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck-node.tsbuildinfo +1 -0
  256. package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck.tsbuildinfo +1 -0
  257. package/tests/ts-compiler/fixtures/non-angular-pkg/dist/index.d.ts +2 -0
  258. package/tests/ts-compiler/fixtures/non-angular-pkg/dist/index.d.ts.map +1 -0
  259. package/tests/ts-compiler/fixtures/non-angular-pkg/dist/index.js +4 -0
  260. package/tests/ts-compiler/fixtures/non-angular-pkg/dist/index.js.map +1 -0
  261. package/tests/ts-compiler/fixtures/non-angular-pkg/dist/util.d.ts +2 -0
  262. package/tests/ts-compiler/fixtures/non-angular-pkg/dist/util.d.ts.map +1 -0
  263. package/tests/ts-compiler/fixtures/non-angular-pkg/dist/util.js +4 -0
  264. package/tests/ts-compiler/fixtures/non-angular-pkg/dist/util.js.map +1 -0
  265. package/tests/ts-compiler/fixtures/non-angular-pkg/src/index.ts +3 -0
  266. package/tests/ts-compiler/fixtures/non-angular-pkg/src/util.ts +3 -0
  267. package/tests/ts-compiler/fixtures/non-angular-pkg/tests/sample.test-file.ts +3 -0
  268. package/tests/ts-compiler/fixtures/non-angular-pkg/tsconfig.json +12 -0
  269. package/tests/ts-compiler/scss-lint-integration.verify.md +14 -0
  270. package/tests/utils/angular-build.spec.ts +1 -1
  271. package/tests/utils/copy-public-outdir.verify.md +8 -0
  272. package/tests/utils/copy-public.acc.spec.ts +52 -0
  273. package/tests/utils/copy-public.spec.ts +56 -0
  274. package/tests/utils/diagnostic-utils.spec.ts +24 -15
  275. package/tests/utils/engine-watch-events.acc.spec.ts +59 -0
  276. package/tests/utils/engine-watch-events.spec.ts +58 -0
  277. package/tests/utils/esbuild-client-config-integration.verify.md +9 -0
  278. package/tests/utils/esbuild-client-config.acc.spec.ts +45 -61
  279. package/tests/utils/esbuild-client-config.spec.ts +70 -52
  280. package/tests/utils/ngtsc-build-core-write-emit.spec.ts +12 -12
  281. package/tests/utils/ngtsc-build-core.spec.ts +1 -44
  282. package/tests/utils/output-utils.spec.ts +133 -13
  283. package/tests/utils/replace-deps-watch.acc.spec.ts +7 -1
  284. package/tests/utils/replace-deps-watch.spec.ts +57 -1
  285. package/tests/utils/worker-utils.spec.ts +8 -2
  286. package/tests/workers/client-worker-initial-build-error.verify.md +2 -3
  287. package/tests/workers/client-worker-initial-build-warnings.verify.md +7 -0
  288. package/tests/workers/client-worker-refactor.verify.md +22 -0
  289. package/tests/workers/client-worker-ts-cache-invalidation.verify.md +12 -0
  290. package/tests/workers/client-worker.acc.spec.ts +6 -3
  291. package/tests/workers/library-build-lint.spec.ts +40 -45
  292. package/tests/workers/library-build-worker.spec.ts +294 -40
  293. package/tests/workers/server-build-lint.spec.ts +59 -45
  294. package/tests/workers/server-build-worker.spec.ts +63 -24
  295. package/tests/workers/server-esbuild-context.acc.spec.ts +2 -0
  296. package/tests/workers/server-esbuild-context.spec.ts +2 -0
  297. package/tests/workers/server-runtime-worker.spec.ts +1 -1
  298. package/tests/workers/shared-worker-lifecycle.acc.spec.ts +1 -1
  299. package/dist/angular/angular-build-pipeline.d.ts +0 -97
  300. package/dist/angular/angular-build-pipeline.d.ts.map +0 -1
  301. package/dist/angular/angular-build-pipeline.js +0 -285
  302. package/dist/angular/angular-build-pipeline.js.map +0 -1
  303. package/dist/utils/tsc-build.d.ts +0 -51
  304. package/dist/utils/tsc-build.d.ts.map +0 -1
  305. package/dist/utils/tsc-build.js +0 -156
  306. package/dist/utils/tsc-build.js.map +0 -1
  307. package/dist/workers/ngtsc-build.worker.d.ts +0 -23
  308. package/dist/workers/ngtsc-build.worker.d.ts.map +0 -1
  309. package/dist/workers/ngtsc-build.worker.js +0 -267
  310. package/dist/workers/ngtsc-build.worker.js.map +0 -1
  311. package/src/angular/angular-build-pipeline.ts +0 -406
  312. package/src/utils/tsc-build.ts +0 -226
  313. package/src/workers/ngtsc-build.worker.ts +0 -351
  314. package/tests/angular/angular-build-pipeline.spec.ts +0 -247
  315. package/tests/angular/angular-compiler-aot.acc.spec.ts +0 -68
  316. package/tests/angular/angular-compiler-aot.spec.ts +0 -80
  317. package/tests/utils/angular-compiler-emit.spec.ts +0 -666
  318. package/tests/utils/angular-compiler.spec.ts +0 -707
  319. package/tests/utils/tsc-build.spec.ts +0 -527
  320. package/tests/workers/ngtsc-build-lint.spec.ts +0 -141
  321. package/tests/workers/ngtsc-build-worker.spec.ts +0 -199
@@ -0,0 +1,46 @@
1
+ import type ts from "typescript";
2
+ import type { AngularSourceFileCache } from "../angular/angular-compiler";
3
+ import type { TypecheckEnv } from "../utils/tsconfig";
4
+
5
+ export interface ISdTsCompilerEmitOptions {
6
+ /** emit 대상 소스 필터 (Angular only, 지정 시 해당 파일만 EmitResult에 포함) */
7
+ sourceFilter?: (fileName: string) => boolean;
8
+ /** Angular transformers 외 추가 transformers (Angular only) */
9
+ additionalTransformers?: {
10
+ before?: ts.TransformerFactory<ts.SourceFile>[];
11
+ after?: ts.TransformerFactory<ts.SourceFile>[];
12
+ };
13
+ }
14
+
15
+ export interface ISdTsCompilerOptions {
16
+ /** 패키지 디렉토리 */
17
+ pkgDir: string;
18
+ /** workspace 루트 (diagnostics 필터링 등에 사용) */
19
+ cwd: string;
20
+ /** 출력 제어 플래그 */
21
+ output: { js: boolean; dts: boolean };
22
+ /** tests/ 파일을 rootNames에 포함할지 여부. 기본값 false */
23
+ includeTests?: boolean;
24
+ /** 타입체크 환경. 설정 시 getCompilerOptionsForEnv()를 적용 */
25
+ env?: TypecheckEnv;
26
+
27
+ // === Angular 전용 (선택적, isForAngular 시 활성화) ===
28
+ /** SourceFile 캐시 (Angular 증분 빌드용). 미제공 시 내부 생성 */
29
+ sourceFileCache?: AngularSourceFileCache;
30
+ /** 스타일시트 변환 콜백 (Feature 1.3에서 활용) */
31
+ transformStylesheet?: (
32
+ data: string,
33
+ containingFile: string,
34
+ stylesheetFile?: string,
35
+ ) => Promise<string | null>;
36
+ /** 외부 스타일시트 맵 (클라이언트 빌드용, resourceNameToFileName에서 사용) */
37
+ externalStylesheets?: Map<string, string>;
38
+ /** compilerOptions 후처리 (클라이언트의 target/module 강제 등) */
39
+ compilerOptionsTransformer?: (options: ts.CompilerOptions) => ts.CompilerOptions;
40
+
41
+ // === SCSS/lint 통합 (Feature 1.3) ===
42
+ /** lint 실행 여부. true이면 compileAsync 결과에 lint 결과 포함 */
43
+ lint?: boolean;
44
+ /** 글로벌 SCSS 컴파일 여부. true이면 scss/styles.scss → dist/styles.css 생성 */
45
+ globalScss?: boolean;
46
+ }
@@ -0,0 +1,34 @@
1
+ import type ts from "typescript";
2
+ import type { SerializedDiagnostic } from "../typecheck/typecheck-serialization";
3
+ import type { EmitResult } from "../angular/angular-compiler";
4
+ import type { LintWithProgramResult } from "../lint/lint-with-program";
5
+ import type { NgtscProgram } from "../angular/angular-build";
6
+
7
+ export interface ISdTsCompilerResult {
8
+ /** TypeScript Program 참조 (lint, 외부 도구용) */
9
+ program: ts.Program;
10
+ /** Builder Program 참조 */
11
+ builderProgram: ts.EmitAndSemanticDiagnosticsBuilderProgram;
12
+ /** Angular 패키지 여부 */
13
+ isForAngular: boolean;
14
+ /** 이 빌드에서 영향받은 파일 (posix 경로). undefined = 전역 변경 (전체 리빌드) */
15
+ affectedFiles: ReadonlySet<string> | undefined;
16
+ /** 직렬화된 진단 정보 (Worker 경계 통과용) */
17
+ diagnostics: SerializedDiagnostic[];
18
+ /** Error 카테고리 진단 수 */
19
+ errorCount: number;
20
+ /** Warning 카테고리 진단 수 */
21
+ warningCount: number;
22
+ /** Error 카테고리 진단을 "파일:줄:열: TS코드: 메시지" 형식으로 포맷한 배열 */
23
+ errors?: string[];
24
+ /** NgtscProgram 참조 (Angular only, HMR용). Non-Angular이면 undefined */
25
+ ngtscProgram?: NgtscProgram;
26
+ /** Angular emit 결과 (Non-Angular이면 undefined — writeFile 훅으로 디스크 직접 쓰기) */
27
+ emitResults?: EmitResult[];
28
+ /** lint 결과 (lint 옵션 활성 시) */
29
+ lint?: LintWithProgramResult;
30
+ /** SCSS 에러 목록 */
31
+ scssErrors: string[];
32
+ /** SCSS 의존성 맵 (소유자 파일 → 의존 SCSS 경로 집합). watch 역방향 탐색용 */
33
+ scssDependencies: ReadonlyMap<string, ReadonlySet<string>>;
34
+ }
@@ -6,14 +6,15 @@ import {
6
6
  } from "@simplysm/core-node";
7
7
 
8
8
  /**
9
- * public/ 및 public-dev/ 디렉토리의 파일을 dist/로 복사한다.
9
+ * public/ 및 public-dev/ 디렉토리의 파일을 출력 디렉토리로 복사한다.
10
10
  * public-dev/가 public/보다 우선한다 (오버레이).
11
11
  *
12
12
  * @param pkgDir 패키지 루트 디렉토리
13
13
  * @param includeDev public-dev/ 포함 여부 (dev 모드에서만 true)
14
+ * @param outDir 출력 디렉토리 (미지정 시 pkgDir/dist)
14
15
  */
15
- export async function copyPublicFiles(pkgDir: string, includeDev: boolean): Promise<void> {
16
- const distDir = pathx.posix(path.join(pkgDir, "dist"));
16
+ export async function copyPublicFiles(pkgDir: string, includeDev: boolean, outDir?: string): Promise<void> {
17
+ const distDir = pathx.posix(outDir ?? path.join(pkgDir, "dist"));
17
18
  await fsx.mkdir(distDir);
18
19
 
19
20
  // public/ 복사
@@ -48,23 +49,25 @@ export async function copyPublicFiles(pkgDir: string, includeDev: boolean): Prom
48
49
  }
49
50
 
50
51
  /**
51
- * public/ 및 public-dev/ 디렉토리를 감시하고 변경사항을 실시간으로 dist/에 복사한다.
52
+ * public/ 및 public-dev/ 디렉토리를 감시하고 변경사항을 실시간으로 출력 디렉토리에 복사한다.
52
53
  * 초기 복사 후 변경/추가/삭제를 자동으로 반영한다.
53
54
  *
54
55
  * @param pkgDir 패키지 루트 디렉토리
55
56
  * @param includeDev public-dev/ 포함 여부 (dev 모드에서만 true)
57
+ * @param outDir 출력 디렉토리 (미지정 시 pkgDir/dist)
56
58
  * @returns FsWatcher 인스턴스 (종료 시 close() 호출 필요) 또는 감시 대상이 없으면 undefined
57
59
  */
58
60
  export async function watchPublicFiles(
59
61
  pkgDir: string,
60
62
  includeDev: boolean,
63
+ outDir?: string,
61
64
  ): Promise<FsWatcher | undefined> {
62
- const distDir = pathx.posix(path.join(pkgDir, "dist"));
65
+ const distDir = pathx.posix(outDir ?? path.join(pkgDir, "dist"));
63
66
  const publicDir = pathx.posix(path.join(pkgDir, "public"));
64
67
  const publicDevDir = pathx.posix(path.join(pkgDir, "public-dev"));
65
68
 
66
69
  // 초기 복사
67
- await copyPublicFiles(pkgDir, includeDev);
70
+ await copyPublicFiles(pkgDir, includeDev, outDir);
68
71
 
69
72
  // 감시 대상 경로 수집
70
73
  const watchPaths: string[] = [];
@@ -30,14 +30,13 @@ export function formatDiagnosticsOutput(diagnostics: ts.Diagnostic[], cwd: strin
30
30
  }
31
31
 
32
32
  /**
33
- * 진단 에러를 "파일:줄:열: TS코드: 메시지" 형식으로 포맷한다.
34
- * 파일 정보가 없는 경우 "TS코드: 메시지" 형식으로 반환한다.
33
+ * 진단 에러를 TypeScript 네이티브 컬러+코드 컨텍스트 포맷으로 변환한다.
35
34
  */
36
- export function formatDiagnosticError(diagnostic: ts.Diagnostic): string {
37
- const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
38
- if (diagnostic.file != null && diagnostic.start != null) {
39
- const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
40
- return `${diagnostic.file.fileName}:${line + 1}:${character + 1}: TS${diagnostic.code}: ${message}`;
41
- }
42
- return `TS${diagnostic.code}: ${message}`;
35
+ export function formatDiagnosticError(diagnostic: ts.Diagnostic, cwd: string): string {
36
+ const formatHost: ts.FormatDiagnosticsHost = {
37
+ getCanonicalFileName: (f) => f,
38
+ getCurrentDirectory: () => cwd,
39
+ getNewLine: () => ts.sys.newLine,
40
+ };
41
+ return ts.formatDiagnosticsWithColorAndContext([diagnostic], formatHost).trimEnd();
43
42
  }
@@ -1,6 +1,23 @@
1
+ import { formatMessagesSync, type PartialMessage } from "esbuild";
1
2
  import { consola } from "consola";
2
3
  import type { BuildResult } from "../runtime/ResultCollector";
3
4
 
5
+ const logger = consola.withTag("sd:cli:output");
6
+
7
+ /**
8
+ * esbuild Message 배열을 포맷된 문자열 배열로 변환한다.
9
+ * esbuild 네이티브 포맷(코드 컨텍스트, 위치 정보, 밑줄)을 유지한다.
10
+ */
11
+ export function formatEsbuildMessages(
12
+ messages: PartialMessage[],
13
+ kind: "error" | "warning",
14
+ ): string[] {
15
+ if (messages.length === 0) return [];
16
+ return formatMessagesSync(messages, { kind, color: true }).map((msg) =>
17
+ msg.replace(/^.*?\x1b\[0m |^X \[ERROR] |^▲ \[WARNING] /, "").trimEnd(),
18
+ );
19
+ }
20
+
4
21
  /**
5
22
  * 빌드 경고/에러 메시지를 포맷팅한다.
6
23
  */
@@ -8,27 +25,40 @@ export function formatBuildMessages(name: string, label: string, messages: strin
8
25
  const lines: string[] = [`${name} (${label})`];
9
26
  for (const msg of messages) {
10
27
  for (const line of msg.split("\n")) {
11
- lines.push(` → ${line}`);
28
+ if (line === "") {
29
+ lines.push("");
30
+ } else {
31
+ lines.push(` ${line}`);
32
+ }
12
33
  }
13
34
  }
14
35
  return lines.join("\n");
15
36
  }
16
37
 
17
38
  /**
18
- * 에러만 출력한다.
39
+ * 에러와 경고를 출력한다. 에러를 먼저, 경고를 나중에 출력한다.
19
40
  * @param results 패키지별 빌드 결과 상태
20
41
  */
21
- export function printErrors(results: ReadonlyMap<string, BuildResult>): void {
42
+ export function printDiagnostics(results: ReadonlyMap<string, BuildResult>): void {
43
+ // 에러 출력
22
44
  for (const result of results.values()) {
23
45
  if (result.status === "error") {
24
46
  const typeLabel = result.type === "lint" ? "lint" : result.target;
25
47
  if (result.message != null && result.message !== "") {
26
- consola.error(formatBuildMessages(result.name, typeLabel, [result.message]));
48
+ logger.error(formatBuildMessages(result.name, typeLabel, [result.message]));
27
49
  } else {
28
- consola.error(`[${result.name}] (${typeLabel}) 실패`);
50
+ logger.error(`[${result.name}] (${typeLabel}) 실패`);
29
51
  }
30
52
  }
31
53
  }
54
+
55
+ // 경고 출력
56
+ for (const result of results.values()) {
57
+ if (result.warnings != null && result.warnings !== "") {
58
+ const typeLabel = result.type === "lint" ? "lint" : result.target;
59
+ logger.warn(formatBuildMessages(result.name, typeLabel, [result.warnings]));
60
+ }
61
+ }
32
62
  }
33
63
 
34
64
  /**
@@ -53,15 +83,15 @@ export function printServers(
53
83
  const activeClients = clients.filter((c) => results.get(`${c}:build`)?.status !== "error");
54
84
  if (activeClients.length > 0) {
55
85
  for (const clientName of activeClients) {
56
- consola.info(`[server] http://localhost:${server.port}/${clientName}/`);
86
+ logger.info(`[server] http://localhost:${server.port}/${clientName}/`);
57
87
  }
58
88
  } else {
59
89
  // 연결된 클라이언트가 없으면 서버 루트 URL 출력
60
- consola.info(`[server] http://localhost:${server.port}/`);
90
+ logger.info(`[server] http://localhost:${server.port}/`);
61
91
  }
62
92
  } else {
63
93
  // 독립형 클라이언트: 이름 포함하여 출력
64
- consola.info(`[server] http://localhost:${server.port}/${server.name}/`);
94
+ logger.info(`[server] http://localhost:${server.port}/${server.name}/`);
65
95
  }
66
96
  }
67
97
  }
@@ -2,19 +2,21 @@ import path from "path";
2
2
  import fs from "node:fs";
3
3
  import { createWorker, FsWatcher } from "@simplysm/core-node";
4
4
  import { err as errNs } from "@simplysm/core-common";
5
- import { setupWorkerLifecycle } from "./shared-worker-lifecycle.js";
5
+ import { setupWorkerLifecycle } from "./shared-worker-lifecycle";
6
6
  import {
7
7
  createClientEsbuildContext,
8
8
  type ClientEsbuildResult,
9
- } from "../esbuild/esbuild-client-config.js";
10
- import { generateIndexHtml } from "../esbuild/esbuild-index-html.js";
11
- import { applyPwa, createPwaHtmlTransform } from "../esbuild/esbuild-pwa.js";
12
- import { createDevHttpServer, type DevHttpServer } from "../dev-server/dev-http-server.js";
13
- import { createHmrService, type HmrService } from "../dev-server/hmr-service.js";
14
- import { createHmrPostTransform } from "../dev-server/hmr-client-script.js";
15
- import { copyPublicFiles, watchPublicFiles } from "../utils/copy-public.js";
16
- import type { SdBrowserSupportConfig, SdPwaConfig } from "../sd-config.types.js";
9
+ } from "../esbuild/esbuild-client-config";
10
+ import { generateIndexHtml } from "../esbuild/esbuild-index-html";
11
+ import { formatEsbuildMessages } from "../utils/output-utils";
12
+ import { applyPwa, createPwaHtmlTransform } from "../esbuild/esbuild-pwa";
13
+ import { createDevHttpServer, type DevHttpServer } from "../dev-server/dev-http-server";
14
+ import { createHmrService, type HmrService } from "../dev-server/hmr-service";
15
+ import { createHmrPostTransform } from "../dev-server/hmr-client-script";
16
+ import { copyPublicFiles, watchPublicFiles } from "../utils/copy-public";
17
+ import type { SdBrowserSupportConfig, SdPwaConfig } from "../sd-config.types";
17
18
  import type esbuild from "esbuild";
19
+ import type { PartialMessage } from "esbuild";
18
20
 
19
21
  //#region Types
20
22
 
@@ -63,6 +65,9 @@ let devServer: DevHttpServer | undefined;
63
65
  let hmrService: HmrService | undefined;
64
66
  let publicWatcher: FsWatcher | undefined;
65
67
  let indexHtmlWatcher: FsWatcher | undefined;
68
+ let lastMetafile: esbuild.Metafile | undefined;
69
+ let isInitialBuild = true;
70
+ let initialBuildResolve: ((result: ClientBuildResult) => void) | undefined;
66
71
 
67
72
  const { logger, guardStartWatch } = setupWorkerLifecycle("client", async () => {
68
73
  await stopWatch();
@@ -98,7 +103,7 @@ async function build(info: ClientBuildInfo): Promise<ClientBuildResult> {
98
103
  const outdir = info.outDir ?? path.join(info.pkgDir, "dist");
99
104
 
100
105
  // 1. public/ 복사
101
- await copyPublicFiles(info.pkgDir, false);
106
+ await copyPublicFiles(info.pkgDir, false, outdir);
102
107
 
103
108
  // 2. polyfills 감지
104
109
  const polyfillsPath = path.join(info.pkgDir, "src", "polyfills.ts");
@@ -160,7 +165,7 @@ async function build(info: ClientBuildInfo): Promise<ClientBuildResult> {
160
165
  // SourceFileCache는 LMDB 기반. context.dispose()에 의해 정리됨.
161
166
 
162
167
  // 8. .config.json 기록
163
- writeConfigJson(path.join(info.pkgDir, "dist"), info.configs);
168
+ writeConfigJson(outdir, info.configs);
164
169
 
165
170
  logger.debug(`[${info.name}] client worker build 완료`);
166
171
  return {
@@ -171,17 +176,151 @@ async function build(info: ClientBuildInfo): Promise<ClientBuildResult> {
171
176
  } catch (err) {
172
177
  const errors: string[] = [];
173
178
  if (err != null && typeof err === "object" && "errors" in err) {
174
- const buildErrors = (err as { errors: Array<{ text: string }> }).errors;
175
- errors.push(...buildErrors.map((e) => e.text));
179
+ const buildErrors = (err as { errors: PartialMessage[] }).errors;
180
+ errors.push(...formatEsbuildMessages(buildErrors, "error"));
176
181
  }
177
182
  if (errors.length === 0) {
178
183
  errors.push(errNs.message(err));
179
184
  }
180
- logger.debug(`[${info.name}] client worker build 예외: ${errors.join("; ")}`);
185
+ logger.debug(`[${info.name}] client worker build 예외: ${errors.join("\n")}`);
181
186
  return { success: false, errors };
182
187
  }
183
188
  }
184
189
 
190
+ /**
191
+ * sourceFileCache 무효화 + mtime 추적 플러그인 생성
192
+ */
193
+ function createSourceFileCachePlugin(): esbuild.Plugin {
194
+ return {
195
+ name: "sd-build-start",
196
+ setup(pluginBuild: esbuild.PluginBuild) {
197
+ const prevMtimes = new Map<string, number>();
198
+
199
+ pluginBuild.onStart(() => {
200
+ // sourceFileCache 무효화: 변경된 파일의 loadResultCache + TypeScript 소스 캐시 모두 제거
201
+ if (esbuildResult != null) {
202
+ const { loadResultCache, typeScriptFileCache } =
203
+ esbuildResult.sourceFileCache;
204
+ const changedFiles = new Set<string>();
205
+ // JS 파일 (loadResultCache) + TS 파일 (typeScriptFileCache) 모두 감시
206
+ const watchTargets = [
207
+ ...loadResultCache.watchFiles,
208
+ ...typeScriptFileCache.keys(),
209
+ ];
210
+ for (const file of watchTargets) {
211
+ try {
212
+ const mtime = fs.statSync(file).mtimeMs;
213
+ const prev = prevMtimes.get(file);
214
+ if (prev != null && prev !== mtime) {
215
+ changedFiles.add(file);
216
+ }
217
+ } catch {
218
+ if (prevMtimes.has(file)) {
219
+ changedFiles.add(file);
220
+ }
221
+ }
222
+ }
223
+ if (changedFiles.size > 0) {
224
+ esbuildResult.sourceFileCache.invalidate(changedFiles);
225
+ }
226
+ }
227
+
228
+ if (!isInitialBuild) {
229
+ sender.send("buildStart", {});
230
+ }
231
+ });
232
+
233
+ pluginBuild.onEnd(() => {
234
+ if (esbuildResult == null) return;
235
+ prevMtimes.clear();
236
+ // JS 파일 (loadResultCache) + TS 파일 (typeScriptFileCache) 모두 기록
237
+ const watchTargets = [
238
+ ...esbuildResult.sourceFileCache.loadResultCache.watchFiles,
239
+ ...esbuildResult.sourceFileCache.typeScriptFileCache.keys(),
240
+ ];
241
+ for (const file of watchTargets) {
242
+ try {
243
+ prevMtimes.set(file, fs.statSync(file).mtimeMs);
244
+ } catch {
245
+ // 삭제된 파일
246
+ }
247
+ }
248
+ });
249
+ },
250
+ };
251
+ }
252
+
253
+ /**
254
+ * dev watch 빌드 완료 핸들러 생성 (index.html 재생성 + HMR + 이벤트 전송)
255
+ */
256
+ function createDevBuildEndHandler(
257
+ basePath: string,
258
+ actualPort: number,
259
+ outdir: string,
260
+ entryNames: string[],
261
+ pkgDir: string,
262
+ ): (result: esbuild.BuildResult) => Promise<void> {
263
+ return async (result: esbuild.BuildResult) => {
264
+ try {
265
+ // index.html 재생성 (lastMetafile 보관 — index.html 단독 변경 시 재생성용)
266
+ if (result.metafile != null) {
267
+ lastMetafile = result.metafile;
268
+ const hmrPostTransform = createHmrPostTransform(basePath, actualPort);
269
+ const indexPath = path.join(pkgDir, "src", "index.html");
270
+ const indexResult = await generateIndexHtml({
271
+ indexPath,
272
+ metafile: result.metafile,
273
+ outdir,
274
+ baseHref: basePath,
275
+ mode: "dev",
276
+ entryNames,
277
+ postTransform: hmrPostTransform,
278
+ });
279
+ fs.writeFileSync(path.join(outdir, "index.html"), indexResult.content);
280
+ }
281
+
282
+ // HMR 메시지 디스패치
283
+ if (hmrService != null && result.metafile != null && !isInitialBuild) {
284
+ hmrService.onBuildEnd(result.metafile);
285
+ }
286
+
287
+ // build 이벤트 전송
288
+ const success = result.errors.length === 0;
289
+ const errors = result.errors.length > 0
290
+ ? formatEsbuildMessages(result.errors, "error")
291
+ : undefined;
292
+ const warnings = result.warnings.length > 0
293
+ ? formatEsbuildMessages(result.warnings, "warning")
294
+ : undefined;
295
+
296
+ if (!isInitialBuild) {
297
+ sender.send("build", { success, errors, warnings });
298
+ }
299
+
300
+ // 초기 빌드 완료 시 resolve
301
+ if (isInitialBuild) {
302
+ isInitialBuild = false;
303
+ initialBuildResolve?.({ success, errors, warnings });
304
+ }
305
+ } catch (err) {
306
+ const message = errNs.message(err);
307
+ if (!isInitialBuild) {
308
+ sender.send("error", { message });
309
+ } else {
310
+ isInitialBuild = false;
311
+ initialBuildResolve?.({
312
+ success: false,
313
+ errors: [message],
314
+ warnings:
315
+ result.warnings.length > 0
316
+ ? formatEsbuildMessages(result.warnings, "warning")
317
+ : undefined,
318
+ });
319
+ }
320
+ }
321
+ };
322
+ }
323
+
185
324
  /**
186
325
  * dev watch 시작
187
326
  */
@@ -232,10 +371,6 @@ async function startWatch(info: ClientBuildInfo): Promise<ClientBuildResult> {
232
371
  });
233
372
 
234
373
  // 7. esbuild context 생성
235
- let lastMetafile: esbuild.Metafile | undefined;
236
- let initialBuildResolve: ((result: ClientBuildResult) => void) | undefined;
237
- let isInitialBuild = true;
238
-
239
374
  esbuildResult = await createClientEsbuildContext({
240
375
  pkgDir: info.pkgDir,
241
376
  cwd: info.cwd,
@@ -247,114 +382,8 @@ async function startWatch(info: ClientBuildInfo): Promise<ClientBuildResult> {
247
382
  legacyModule,
248
383
  postcssPlugins,
249
384
  templateUpdates: legacyModule ? undefined : templateUpdates,
250
- plugins: [
251
- {
252
- name: "sd-build-start",
253
- setup(pluginBuild: esbuild.PluginBuild) {
254
- const prevMtimes = new Map<string, number>();
255
-
256
- pluginBuild.onStart(() => {
257
- // sourceFileCache 무효화: 변경된 파일의 loadResultCache + TypeScript 소스 캐시 모두 제거
258
- if (esbuildResult != null) {
259
- const { loadResultCache } = esbuildResult.sourceFileCache;
260
- const changedFiles = new Set<string>();
261
- for (const file of loadResultCache.watchFiles) {
262
- try {
263
- const mtime = fs.statSync(file).mtimeMs;
264
- const prev = prevMtimes.get(file);
265
- if (prev != null && prev !== mtime) {
266
- changedFiles.add(file);
267
- }
268
- } catch {
269
- if (prevMtimes.has(file)) {
270
- changedFiles.add(file);
271
- }
272
- }
273
- }
274
- if (changedFiles.size > 0) {
275
- esbuildResult.sourceFileCache.invalidate(changedFiles);
276
- }
277
- }
278
-
279
- if (!isInitialBuild) {
280
- sender.send("buildStart", {});
281
- }
282
- });
283
-
284
- pluginBuild.onEnd(() => {
285
- if (esbuildResult == null) return;
286
- prevMtimes.clear();
287
- for (const file of esbuildResult.sourceFileCache.loadResultCache.watchFiles) {
288
- try {
289
- prevMtimes.set(file, fs.statSync(file).mtimeMs);
290
- } catch {
291
- // 삭제된 파일
292
- }
293
- }
294
- });
295
- },
296
- },
297
- ],
298
- onEnd: async (result: esbuild.BuildResult) => {
299
- try {
300
- // index.html 재생성 (lastMetafile 보관 — index.html 단독 변경 시 재생성용)
301
- if (result.metafile != null) {
302
- lastMetafile = result.metafile;
303
- const hmrPostTransform = createHmrPostTransform(basePath, actualPort);
304
- const indexPath = path.join(info.pkgDir, "src", "index.html");
305
- const indexResult = await generateIndexHtml({
306
- indexPath,
307
- metafile: result.metafile,
308
- outdir,
309
- baseHref: basePath,
310
- mode: "dev",
311
- entryNames,
312
- postTransform: hmrPostTransform,
313
- });
314
- fs.writeFileSync(path.join(outdir, "index.html"), indexResult.content);
315
- }
316
-
317
- // HMR 메시지 디스패치
318
- if (hmrService != null && result.metafile != null && !isInitialBuild) {
319
- hmrService.onBuildEnd(result.metafile);
320
- }
321
-
322
- // build 이벤트 전송
323
- const success = result.errors.length === 0;
324
- if (!isInitialBuild) {
325
- sender.send("build", {
326
- success,
327
- errors:
328
- result.errors.length > 0
329
- ? result.errors.map((e) => e.text)
330
- : undefined,
331
- warnings:
332
- result.warnings.length > 0
333
- ? result.warnings.map((w) => w.text)
334
- : undefined,
335
- });
336
- }
337
-
338
- // 초기 빌드 완료 시 resolve
339
- if (isInitialBuild) {
340
- isInitialBuild = false;
341
- initialBuildResolve?.({
342
- success,
343
- errors:
344
- result.errors.length > 0
345
- ? result.errors.map((e) => e.text)
346
- : undefined,
347
- });
348
- }
349
- } catch (err) {
350
- const message = errNs.message(err);
351
- sender.send("error", { message });
352
- if (isInitialBuild) {
353
- isInitialBuild = false;
354
- initialBuildResolve?.({ success: false, errors: [message] });
355
- }
356
- }
357
- },
385
+ plugins: [createSourceFileCachePlugin()],
386
+ onEnd: createDevBuildEndHandler(basePath, actualPort, outdir, entryNames, info.pkgDir),
358
387
  });
359
388
 
360
389
  // 8. esbuild watch 시작 + 초기 빌드 대기
@@ -440,6 +469,11 @@ async function stopWatch(): Promise<void> {
440
469
  indexHtmlWatcher = undefined;
441
470
  }
442
471
 
472
+ // 6. 빌드 세션 상태 리셋
473
+ lastMetafile = undefined;
474
+ isInitialBuild = true;
475
+ initialBuildResolve = undefined;
476
+
443
477
  logger.debug("esbuild watch 정리 완료");
444
478
  }
445
479