@simplysm/sd-cli 14.0.7 → 14.0.9

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 (265) hide show
  1. package/dist/angular/client-transform-stylesheet.d.ts.map +1 -1
  2. package/dist/angular/client-transform-stylesheet.js.map +1 -1
  3. package/dist/angular/vite-angular-plugin.d.ts.map +1 -1
  4. package/dist/angular/vite-angular-plugin.js +15 -8
  5. package/dist/angular/vite-angular-plugin.js.map +1 -1
  6. package/dist/angular/vite-postcss-inline-plugin.d.ts.map +1 -1
  7. package/dist/angular/vite-postcss-inline-plugin.js.map +1 -1
  8. package/dist/capacitor/capacitor.d.ts +1 -1
  9. package/dist/capacitor/capacitor.d.ts.map +1 -1
  10. package/dist/capacitor/capacitor.js +43 -44
  11. package/dist/capacitor/capacitor.js.map +1 -1
  12. package/dist/commands/build.d.ts.map +1 -1
  13. package/dist/commands/build.js.map +1 -1
  14. package/dist/commands/check.d.ts.map +1 -1
  15. package/dist/commands/check.js +2 -2
  16. package/dist/commands/check.js.map +1 -1
  17. package/dist/commands/dev.d.ts.map +1 -1
  18. package/dist/commands/dev.js.map +1 -1
  19. package/dist/commands/lint.d.ts.map +1 -1
  20. package/dist/commands/lint.js.map +1 -1
  21. package/dist/commands/publish.d.ts.map +1 -1
  22. package/dist/commands/publish.js +12 -13
  23. package/dist/commands/publish.js.map +1 -1
  24. package/dist/commands/replace-deps.d.ts.map +1 -1
  25. package/dist/commands/replace-deps.js.map +1 -1
  26. package/dist/commands/typecheck.d.ts.map +1 -1
  27. package/dist/commands/typecheck.js +12 -12
  28. package/dist/commands/typecheck.js.map +1 -1
  29. package/dist/commands/watch.d.ts.map +1 -1
  30. package/dist/commands/watch.js.map +1 -1
  31. package/dist/electron/electron.d.ts.map +1 -1
  32. package/dist/electron/electron.js +42 -37
  33. package/dist/electron/electron.js.map +1 -1
  34. package/dist/engines/BaseEngine.d.ts +1 -5
  35. package/dist/engines/BaseEngine.d.ts.map +1 -1
  36. package/dist/engines/BaseEngine.js +7 -16
  37. package/dist/engines/BaseEngine.js.map +1 -1
  38. package/dist/engines/NgtscEngine.d.ts.map +1 -1
  39. package/dist/engines/NgtscEngine.js +10 -11
  40. package/dist/engines/NgtscEngine.js.map +1 -1
  41. package/dist/engines/ServerEsbuildEngine.d.ts.map +1 -1
  42. package/dist/engines/ServerEsbuildEngine.js +10 -11
  43. package/dist/engines/ServerEsbuildEngine.js.map +1 -1
  44. package/dist/engines/TscEngine.d.ts.map +1 -1
  45. package/dist/engines/TscEngine.js +10 -11
  46. package/dist/engines/TscEngine.js.map +1 -1
  47. package/dist/engines/ViteEngine.d.ts.map +1 -1
  48. package/dist/engines/ViteEngine.js +3 -13
  49. package/dist/engines/ViteEngine.js.map +1 -1
  50. package/dist/engines/index.d.ts.map +1 -1
  51. package/dist/engines/index.js.map +1 -1
  52. package/dist/engines/types.d.ts +3 -6
  53. package/dist/engines/types.d.ts.map +1 -1
  54. package/dist/engines/types.js.map +1 -1
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js.map +1 -1
  57. package/dist/infra/ResultCollector.d.ts +1 -1
  58. package/dist/infra/ResultCollector.d.ts.map +1 -1
  59. package/dist/infra/ResultCollector.js.map +1 -1
  60. package/dist/infra/SignalHandler.d.ts.map +1 -1
  61. package/dist/infra/SignalHandler.js.map +1 -1
  62. package/dist/infra/WorkerManager.d.ts.map +1 -1
  63. package/dist/infra/WorkerManager.js.map +1 -1
  64. package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
  65. package/dist/orchestrators/BuildOrchestrator.js +30 -61
  66. package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
  67. package/dist/orchestrators/DevWatchOrchestrator.d.ts +2 -0
  68. package/dist/orchestrators/DevWatchOrchestrator.d.ts.map +1 -1
  69. package/dist/orchestrators/DevWatchOrchestrator.js +40 -44
  70. package/dist/orchestrators/DevWatchOrchestrator.js.map +1 -1
  71. package/dist/sd-cli-entry.d.ts.map +1 -1
  72. package/dist/sd-cli-entry.js +2 -13
  73. package/dist/sd-cli-entry.js.map +1 -1
  74. package/dist/sd-cli.d.ts.map +1 -1
  75. package/dist/sd-cli.js +5 -5
  76. package/dist/sd-cli.js.map +1 -1
  77. package/dist/sd-config.types.d.ts.map +1 -1
  78. package/dist/sd-config.types.js.map +1 -1
  79. package/dist/utils/SdCliReporter.d.ts +18 -0
  80. package/dist/utils/SdCliReporter.d.ts.map +1 -0
  81. package/dist/utils/SdCliReporter.js +144 -0
  82. package/dist/utils/SdCliReporter.js.map +1 -0
  83. package/dist/utils/angular-build.d.ts.map +1 -1
  84. package/dist/utils/angular-build.js.map +1 -1
  85. package/dist/utils/angular-compiler.d.ts.map +1 -1
  86. package/dist/utils/angular-compiler.js +11 -4
  87. package/dist/utils/angular-compiler.js.map +1 -1
  88. package/dist/utils/build-env.d.ts.map +1 -1
  89. package/dist/utils/build-env.js +2 -1
  90. package/dist/utils/build-env.js.map +1 -1
  91. package/dist/utils/concurrency.d.ts.map +1 -1
  92. package/dist/utils/concurrency.js.map +1 -1
  93. package/dist/utils/copy-public.d.ts.map +1 -1
  94. package/dist/utils/copy-public.js +21 -21
  95. package/dist/utils/copy-public.js.map +1 -1
  96. package/dist/utils/copy-src.d.ts.map +1 -1
  97. package/dist/utils/copy-src.js +12 -12
  98. package/dist/utils/copy-src.js.map +1 -1
  99. package/dist/utils/diagnostic-utils.d.ts.map +1 -1
  100. package/dist/utils/diagnostic-utils.js +3 -2
  101. package/dist/utils/diagnostic-utils.js.map +1 -1
  102. package/dist/utils/engine-stop.d.ts.map +1 -1
  103. package/dist/utils/engine-stop.js.map +1 -1
  104. package/dist/utils/esbuild-config.d.ts.map +1 -1
  105. package/dist/utils/esbuild-config.js +2 -0
  106. package/dist/utils/esbuild-config.js.map +1 -1
  107. package/dist/utils/generate-pwa-icons.d.ts.map +1 -1
  108. package/dist/utils/generate-pwa-icons.js.map +1 -1
  109. package/dist/utils/hmr-candidates.d.ts.map +1 -1
  110. package/dist/utils/hmr-candidates.js.map +1 -1
  111. package/dist/utils/lint-utils.d.ts.map +1 -1
  112. package/dist/utils/lint-utils.js.map +1 -1
  113. package/dist/utils/lint-with-program.d.ts.map +1 -1
  114. package/dist/utils/lint-with-program.js +7 -3
  115. package/dist/utils/lint-with-program.js.map +1 -1
  116. package/dist/utils/ngtsc-build-core.d.ts +2 -10
  117. package/dist/utils/ngtsc-build-core.d.ts.map +1 -1
  118. package/dist/utils/ngtsc-build-core.js +16 -15
  119. package/dist/utils/ngtsc-build-core.js.map +1 -1
  120. package/dist/utils/orchestrator-utils.d.ts.map +1 -1
  121. package/dist/utils/orchestrator-utils.js.map +1 -1
  122. package/dist/utils/output-path-rewriter.d.ts.map +1 -1
  123. package/dist/utils/output-path-rewriter.js +7 -7
  124. package/dist/utils/output-path-rewriter.js.map +1 -1
  125. package/dist/utils/output-utils.d.ts.map +1 -1
  126. package/dist/utils/output-utils.js +1 -1
  127. package/dist/utils/output-utils.js.map +1 -1
  128. package/dist/utils/package-utils.d.ts +4 -0
  129. package/dist/utils/package-utils.d.ts.map +1 -1
  130. package/dist/utils/package-utils.js +34 -13
  131. package/dist/utils/package-utils.js.map +1 -1
  132. package/dist/utils/rebuild-manager.d.ts +1 -1
  133. package/dist/utils/rebuild-manager.d.ts.map +1 -1
  134. package/dist/utils/rebuild-manager.js +3 -1
  135. package/dist/utils/rebuild-manager.js.map +1 -1
  136. package/dist/utils/replace-deps.d.ts.map +1 -1
  137. package/dist/utils/replace-deps.js +10 -10
  138. package/dist/utils/replace-deps.js.map +1 -1
  139. package/dist/utils/scss-compiler.d.ts.map +1 -1
  140. package/dist/utils/scss-compiler.js.map +1 -1
  141. package/dist/utils/sd-config.d.ts.map +1 -1
  142. package/dist/utils/sd-config.js +2 -3
  143. package/dist/utils/sd-config.js.map +1 -1
  144. package/dist/utils/tsc-build.d.ts +3 -1
  145. package/dist/utils/tsc-build.d.ts.map +1 -1
  146. package/dist/utils/tsc-build.js +7 -4
  147. package/dist/utils/tsc-build.js.map +1 -1
  148. package/dist/utils/tsconfig.d.ts.map +1 -1
  149. package/dist/utils/tsconfig.js.map +1 -1
  150. package/dist/utils/typecheck-non-package.d.ts.map +1 -1
  151. package/dist/utils/typecheck-non-package.js +10 -5
  152. package/dist/utils/typecheck-non-package.js.map +1 -1
  153. package/dist/utils/typecheck-serialization.d.ts.map +1 -1
  154. package/dist/utils/typecheck-serialization.js.map +1 -1
  155. package/dist/utils/vite-config.d.ts.map +1 -1
  156. package/dist/utils/vite-config.js +2 -1
  157. package/dist/utils/vite-config.js.map +1 -1
  158. package/dist/utils/vite-scope-watch-plugin.d.ts.map +1 -1
  159. package/dist/utils/vite-scope-watch-plugin.js.map +1 -1
  160. package/dist/utils/worker-events.d.ts +1 -1
  161. package/dist/utils/worker-events.d.ts.map +1 -1
  162. package/dist/utils/worker-events.js +1 -0
  163. package/dist/utils/worker-events.js.map +1 -1
  164. package/dist/utils/worker-utils.d.ts +1 -1
  165. package/dist/utils/worker-utils.d.ts.map +1 -1
  166. package/dist/utils/worker-utils.js +3 -1
  167. package/dist/utils/worker-utils.js.map +1 -1
  168. package/dist/vitest-plugin.d.ts.map +1 -1
  169. package/dist/vitest-plugin.js +2 -0
  170. package/dist/vitest-plugin.js.map +1 -1
  171. package/dist/workers/client.worker.d.ts.map +1 -1
  172. package/dist/workers/client.worker.js +4 -0
  173. package/dist/workers/client.worker.js.map +1 -1
  174. package/dist/workers/library-build.worker.d.ts +2 -10
  175. package/dist/workers/library-build.worker.d.ts.map +1 -1
  176. package/dist/workers/library-build.worker.js +38 -14
  177. package/dist/workers/library-build.worker.js.map +1 -1
  178. package/dist/workers/lint.worker.d.ts.map +1 -1
  179. package/dist/workers/lint.worker.js.map +1 -1
  180. package/dist/workers/ngtsc-build.worker.d.ts.map +1 -1
  181. package/dist/workers/ngtsc-build.worker.js +40 -14
  182. package/dist/workers/ngtsc-build.worker.js.map +1 -1
  183. package/dist/workers/server-build.worker.d.ts +2 -10
  184. package/dist/workers/server-build.worker.d.ts.map +1 -1
  185. package/dist/workers/server-build.worker.js +30 -22
  186. package/dist/workers/server-build.worker.js.map +1 -1
  187. package/dist/workers/server-runtime.worker.d.ts.map +1 -1
  188. package/dist/workers/server-runtime.worker.js.map +1 -1
  189. package/package.json +4 -5
  190. package/src/angular/vite-angular-plugin.ts +18 -9
  191. package/src/capacitor/capacitor.ts +43 -44
  192. package/src/commands/check.ts +2 -2
  193. package/src/commands/publish.ts +12 -13
  194. package/src/commands/typecheck.ts +12 -12
  195. package/src/electron/electron.ts +44 -38
  196. package/src/engines/BaseEngine.ts +8 -19
  197. package/src/engines/NgtscEngine.ts +11 -11
  198. package/src/engines/ServerEsbuildEngine.ts +11 -11
  199. package/src/engines/TscEngine.ts +11 -11
  200. package/src/engines/ViteEngine.ts +3 -14
  201. package/src/engines/types.ts +3 -6
  202. package/src/infra/ResultCollector.ts +1 -1
  203. package/src/orchestrators/BuildOrchestrator.ts +31 -62
  204. package/src/orchestrators/DevWatchOrchestrator.ts +41 -44
  205. package/src/sd-cli-entry.ts +2 -12
  206. package/src/sd-cli.ts +8 -5
  207. package/src/utils/SdCliReporter.ts +177 -0
  208. package/src/utils/angular-compiler.ts +11 -4
  209. package/src/utils/build-env.ts +2 -1
  210. package/src/utils/copy-public.ts +21 -21
  211. package/src/utils/copy-src.ts +12 -12
  212. package/src/utils/diagnostic-utils.ts +3 -2
  213. package/src/utils/esbuild-config.ts +2 -0
  214. package/src/utils/lint-with-program.ts +7 -3
  215. package/src/utils/ngtsc-build-core.ts +18 -18
  216. package/src/utils/output-path-rewriter.ts +7 -7
  217. package/src/utils/output-utils.ts +1 -1
  218. package/src/utils/package-utils.ts +37 -13
  219. package/src/utils/rebuild-manager.ts +4 -2
  220. package/src/utils/replace-deps.ts +10 -10
  221. package/src/utils/sd-config.ts +2 -3
  222. package/src/utils/tsc-build.ts +9 -4
  223. package/src/utils/typecheck-non-package.ts +10 -5
  224. package/src/utils/vite-config.ts +2 -1
  225. package/src/utils/worker-events.ts +2 -1
  226. package/src/utils/worker-utils.ts +3 -1
  227. package/src/vitest-plugin.ts +5 -0
  228. package/src/workers/client.worker.ts +4 -0
  229. package/src/workers/library-build.worker.ts +48 -18
  230. package/src/workers/ngtsc-build.worker.ts +48 -13
  231. package/src/workers/server-build.worker.ts +32 -26
  232. package/tests/angular/vite-angular-plugin-hmr-fallback.spec.ts +11 -7
  233. package/tests/angular/vite-angular-plugin-lint.spec.ts +6 -1
  234. package/tests/capacitor/capacitor-build.spec.ts +14 -7
  235. package/tests/capacitor/capacitor-icon.spec.ts +14 -7
  236. package/tests/capacitor/capacitor-init.spec.ts +13 -6
  237. package/tests/capacitor/capacitor-run.spec.ts +18 -11
  238. package/tests/capacitor/capacitor-workspace.spec.ts +13 -6
  239. package/tests/commands/check.spec.ts +5 -2
  240. package/tests/commands/publish.spec.ts +4 -4
  241. package/tests/commands/typecheck.spec.ts +20 -31
  242. package/tests/electron/electron.spec.ts +32 -23
  243. package/tests/engines/base-engine.spec.ts +15 -21
  244. package/tests/engines/engine-lint-integration.spec.ts +5 -10
  245. package/tests/engines/ngtsc-engine.spec.ts +27 -41
  246. package/tests/engines/server-esbuild-engine.spec.ts +18 -29
  247. package/tests/engines/tsc-engine.spec.ts +14 -23
  248. package/tests/engines/vite-engine.spec.ts +10 -15
  249. package/tests/infra/result-collector.spec.ts +2 -2
  250. package/tests/orchestrators/build-orchestrator.spec.ts +19 -29
  251. package/tests/orchestrators/dev-watch-orchestrator.spec.ts +110 -95
  252. package/tests/utils/copy-src.spec.ts +25 -19
  253. package/tests/utils/diagnostic-utils.spec.ts +72 -0
  254. package/tests/utils/ngtsc-build-core-angular-compiler.spec.ts +2 -3
  255. package/tests/utils/output-path-rewriter.spec.ts +7 -6
  256. package/tests/utils/output-utils.spec.ts +5 -5
  257. package/tests/utils/rebuild-manager.spec.ts +1 -1
  258. package/tests/utils/sd-config.spec.ts +4 -0
  259. package/tests/utils/tsc-build.spec.ts +23 -5
  260. package/tests/workers/library-build-worker.spec.ts +113 -20
  261. package/tests/workers/ngtsc-build-lint.spec.ts +3 -6
  262. package/tests/workers/ngtsc-build-worker.spec.ts +11 -13
  263. package/tests/workers/server-build-lint.spec.ts +4 -1
  264. package/tests/workers/server-build-worker.spec.ts +25 -25
  265. package/tests/angular/migration-cleanup.spec.ts +0 -59
@@ -1,6 +1,5 @@
1
- import path from "path";
2
1
  import ts from "typescript";
3
- import { fsx } from "@simplysm/core-node";
2
+ import { fsx, pathx } from "@simplysm/core-node";
4
3
  import { consola } from "consola";
5
4
  import type {
6
5
  SdConfig,
@@ -37,7 +36,7 @@ export interface BuildOrchestratorOptions {
37
36
  interface BuildStepResult {
38
37
  name: string;
39
38
  target: string;
40
- type: "js" | "dts" | "lint";
39
+ type: "build" | "lint";
41
40
  success: boolean;
42
41
  errors?: string[];
43
42
  warnings?: string[];
@@ -101,7 +100,7 @@ export function classifyPackages(
101
100
  * Delete dist folders
102
101
  */
103
102
  async function cleanDistFolders(cwd: string, packageNames: string[]): Promise<void> {
104
- await Promise.all(packageNames.map((name) => fsx.rm(path.join(cwd, "packages", name, "dist"))));
103
+ await Promise.all(packageNames.map((name) => fsx.rm(pathx.posixResolve(cwd, "packages", name, "dist"))));
105
104
  }
106
105
 
107
106
  //#endregion
@@ -227,7 +226,7 @@ export class BuildOrchestrator {
227
226
 
228
227
  // buildPackages: JS build + dts generation via BuildEngine
229
228
  for (const { name, config } of classified.buildPackages) {
230
- const pkgDir = path.join(this._cwd, "packages", name);
229
+ const pkgDir = pathx.posixResolve(this._cwd, "packages", name);
231
230
 
232
231
  buildTasks.push(async () => {
233
232
  this._logger.debug(`[${name}] (${config.target}) 빌드 시작`);
@@ -239,28 +238,18 @@ export class BuildOrchestrator {
239
238
  try {
240
239
  const engineResult = await engine.run({ js: true, dts: true, lint: true });
241
240
 
242
- // JS 빌드 결과 처리
241
+ // 빌드 결과 처리
242
+ const diagnostics = engineResult.build.diagnostics.map((d) => deserializeDiagnostic(d, fileCache));
243
243
  results.push({
244
244
  name,
245
245
  target: config.target,
246
- type: "js",
247
- success: engineResult.js.success,
248
- errors: engineResult.js.errors.length > 0 ? engineResult.js.errors : undefined,
249
- warnings: engineResult.js.warnings.length > 0 ? engineResult.js.warnings : undefined,
250
- });
251
- if (!engineResult.js.success) state.hasError = true;
252
-
253
- // DTS 결과 처리
254
- const diagnostics = engineResult.dts.diagnostics.map((d) => deserializeDiagnostic(d, fileCache));
255
- results.push({
256
- name,
257
- target: config.target,
258
- type: "dts",
259
- success: engineResult.dts.success,
260
- errors: engineResult.dts.errors.length > 0 ? engineResult.dts.errors : undefined,
246
+ type: "build",
247
+ success: engineResult.build.success,
248
+ errors: engineResult.build.errors.length > 0 ? engineResult.build.errors : undefined,
249
+ warnings: engineResult.build.warnings.length > 0 ? engineResult.build.warnings : undefined,
261
250
  diagnostics,
262
251
  });
263
- if (!engineResult.dts.success) state.hasError = true;
252
+ if (!engineResult.build.success) state.hasError = true;
264
253
 
265
254
  // 린트 결과 처리
266
255
  if (engineResult.lint != null) {
@@ -289,7 +278,7 @@ export class BuildOrchestrator {
289
278
 
290
279
  // serverPackages: JS build + typecheck via BuildEngine
291
280
  for (const { name, config } of classified.serverPackages) {
292
- const pkgDir = path.join(this._cwd, "packages", name);
281
+ const pkgDir = pathx.posixResolve(this._cwd, "packages", name);
293
282
 
294
283
  buildTasks.push(async () => {
295
284
  this._logger.debug(`[${name}] (server) 빌드 시작`);
@@ -301,28 +290,18 @@ export class BuildOrchestrator {
301
290
  try {
302
291
  const engineResult = await engine.run({ js: true, dts: false, lint: true });
303
292
 
304
- // JS 빌드 결과 처리
293
+ // 빌드 결과 처리
294
+ const diagnostics = engineResult.build.diagnostics.map((d) => deserializeDiagnostic(d, fileCache));
305
295
  results.push({
306
296
  name,
307
297
  target: "server",
308
- type: "js",
309
- success: engineResult.js.success,
310
- errors: engineResult.js.errors.length > 0 ? engineResult.js.errors : undefined,
311
- warnings: engineResult.js.warnings.length > 0 ? engineResult.js.warnings : undefined,
312
- });
313
- if (!engineResult.js.success) state.hasError = true;
314
-
315
- // DTS/타입체크 결과 처리
316
- const diagnostics = engineResult.dts.diagnostics.map((d) => deserializeDiagnostic(d, fileCache));
317
- results.push({
318
- name,
319
- target: "server",
320
- type: "dts",
321
- success: engineResult.dts.success,
322
- errors: engineResult.dts.errors.length > 0 ? engineResult.dts.errors : undefined,
298
+ type: "build",
299
+ success: engineResult.build.success,
300
+ errors: engineResult.build.errors.length > 0 ? engineResult.build.errors : undefined,
301
+ warnings: engineResult.build.warnings.length > 0 ? engineResult.build.warnings : undefined,
323
302
  diagnostics,
324
303
  });
325
- if (!engineResult.dts.success) state.hasError = true;
304
+ if (!engineResult.build.success) state.hasError = true;
326
305
 
327
306
  // 린트 결과 처리
328
307
  if (engineResult.lint != null) {
@@ -345,7 +324,7 @@ export class BuildOrchestrator {
345
324
 
346
325
  // clientPackages: Vite production build via ViteEngine (no dts)
347
326
  for (const { name, config } of classified.clientPackages) {
348
- const pkgDir = path.join(this._cwd, "packages", name);
327
+ const pkgDir = pathx.posixResolve(this._cwd, "packages", name);
349
328
 
350
329
  buildTasks.push(async () => {
351
330
  this._logger.debug(`[${name}] (client) 빌드 시작`);
@@ -357,28 +336,18 @@ export class BuildOrchestrator {
357
336
  try {
358
337
  const engineResult = await engine.run({ js: true, dts: false, lint: true });
359
338
 
360
- // JS 빌드 결과 처리
361
- results.push({
362
- name,
363
- target: "client",
364
- type: "js",
365
- success: engineResult.js.success,
366
- errors: engineResult.js.errors.length > 0 ? engineResult.js.errors : undefined,
367
- warnings: engineResult.js.warnings.length > 0 ? engineResult.js.warnings : undefined,
368
- });
369
- if (!engineResult.js.success) state.hasError = true;
370
-
371
- // DTS 결과 처리
372
- const diagnostics = engineResult.dts.diagnostics.map((d) => deserializeDiagnostic(d, fileCache));
339
+ // 빌드 결과 처리
340
+ const diagnostics = engineResult.build.diagnostics.map((d) => deserializeDiagnostic(d, fileCache));
373
341
  results.push({
374
342
  name,
375
343
  target: "client",
376
- type: "dts",
377
- success: engineResult.dts.success,
378
- errors: engineResult.dts.errors.length > 0 ? engineResult.dts.errors : undefined,
344
+ type: "build",
345
+ success: engineResult.build.success,
346
+ errors: engineResult.build.errors.length > 0 ? engineResult.build.errors : undefined,
347
+ warnings: engineResult.build.warnings.length > 0 ? engineResult.build.warnings : undefined,
379
348
  diagnostics,
380
349
  });
381
- if (!engineResult.dts.success) state.hasError = true;
350
+ if (!engineResult.build.success) state.hasError = true;
382
351
 
383
352
  // 린트 결과 처리
384
353
  if (engineResult.lint != null) {
@@ -392,9 +361,9 @@ export class BuildOrchestrator {
392
361
  if (!engineResult.lint.success) state.hasError = true;
393
362
  }
394
363
 
395
- // 네이티브 빌드 (JS 빌드 성공 시에만 실행)
396
- if (engineResult.js.success) {
397
- const distPath = path.join(pkgDir, "dist");
364
+ // 네이티브 빌드 (빌드 성공 시에만 실행)
365
+ if (engineResult.build.success) {
366
+ const distPath = pathx.posixResolve(pkgDir, "dist");
398
367
  const nativeBuildPromises: Array<Promise<void>> = [];
399
368
 
400
369
  if (config.capacitor != null) {
@@ -462,7 +431,7 @@ export class BuildOrchestrator {
462
431
  // 결과 출력
463
432
  const allDiagnostics: ts.Diagnostic[] = [];
464
433
  for (const result of results) {
465
- const typeLabel = result.type === "dts" ? "dts" : result.type === "lint" ? "lint" : result.target;
434
+ const typeLabel = result.type === "lint" ? "lint" : result.target;
466
435
 
467
436
  // 경고 출력
468
437
  if (result.warnings != null) {
@@ -1,7 +1,6 @@
1
- import path from "path";
2
1
  import { spawn, type ChildProcess } from "child_process";
3
2
  import { consola } from "consola";
4
- import { Worker, type WorkerProxy } from "@simplysm/core-node";
3
+ import { Worker, type WorkerProxy, pathx } from "@simplysm/core-node";
5
4
  import { FsWatcher } from "@simplysm/core-node";
6
5
  import { err as errNs } from "@simplysm/core-common";
7
6
  import type {
@@ -12,7 +11,7 @@ import type {
12
11
  SdServerPackageConfig,
13
12
  } from "../sd-config.types";
14
13
  import { loadSdConfig } from "../utils/sd-config";
15
- import { discoverWorkspacePackages, filterPackagesByTargets, mergeTestsPackagesIntoConfig, validateTargets, classifyWatchPackages, classifyDevPackages } from "../utils/package-utils";
14
+ import { filterPackagesByTargets, validateTargets, classifyWatchPackages, classifyDevPackages, buildPathMapFromConfig } from "../utils/package-utils";
16
15
  import { getVersion } from "../utils/build-env";
17
16
  import { watchReplaceDeps, type WatchReplaceDepResult } from "../utils/replace-deps";
18
17
  import { printErrors, printServers } from "../utils/output-utils";
@@ -72,6 +71,7 @@ export class DevWatchOrchestrator {
72
71
  private _baseEnv: { VER: string; DEV: string } | undefined;
73
72
  private readonly _serverRuntimeWorkers = new Map<string, WorkerProxy<typeof ServerRuntimeWorkerModule>>();
74
73
  private _printServersTimer: ReturnType<typeof setTimeout> | undefined;
74
+ private _serverRestartTimer: ReturnType<typeof setTimeout> | undefined;
75
75
 
76
76
  // Watchers
77
77
  private _copySrcWatchers: FsWatcher[] = [];
@@ -107,13 +107,11 @@ export class DevWatchOrchestrator {
107
107
  throw err;
108
108
  }
109
109
 
110
- // Discover tests packages and merge into config
111
- const workspacePackages = discoverWorkspacePackages(this._cwd);
112
- const { merged, pathMap } = mergeTestsPackagesIntoConfig(sdConfig.packages, workspacePackages);
113
- this._pathMap = pathMap;
110
+ // Build pathMap from config packages only (tests packages are excluded from watch/dev)
111
+ this._pathMap = buildPathMapFromConfig(sdConfig.packages);
114
112
 
115
113
  // Validate targets
116
- validateTargets(this._options.targets, merged);
114
+ validateTargets(this._options.targets, sdConfig.packages);
117
115
 
118
116
  // Store replaceDeps for engine creation
119
117
  this._replaceDeps = sdConfig.replaceDeps;
@@ -130,7 +128,7 @@ export class DevWatchOrchestrator {
130
128
  }
131
129
 
132
130
  // Filter by targets
133
- const allPackages = filterPackagesByTargets(merged, this._options.targets);
131
+ const allPackages = filterPackagesByTargets(sdConfig.packages, this._options.targets);
134
132
 
135
133
  // Classify packages based on mode
136
134
  if (this._options.mode === "watch") {
@@ -161,12 +159,12 @@ export class DevWatchOrchestrator {
161
159
 
162
160
  // Batch complete handler
163
161
  if (this._options.mode === "watch") {
164
- this._rebuildManager.on("batchComplete", () => {
162
+ this._rebuildManager.on("batchComplete", (_completedKeys) => {
165
163
  printErrors(this._resultCollector.toMap());
166
164
  });
167
165
  } else {
168
- this._rebuildManager.on("batchComplete", () => {
169
- this._onDevBatchComplete();
166
+ this._rebuildManager.on("batchComplete", (completedKeys) => {
167
+ this._onDevBatchComplete(completedKeys);
170
168
  });
171
169
  }
172
170
 
@@ -223,8 +221,10 @@ export class DevWatchOrchestrator {
223
221
 
224
222
  async start(): Promise<void> {
225
223
  if (!this._hasPackages) {
224
+ this._logger.debug("대상 패키지 없음, start 건너뜀");
226
225
  return;
227
226
  }
227
+ this._logger.debug("start 시작");
228
228
 
229
229
  if (this._options.mode === "watch") {
230
230
  await this._startWatchMode();
@@ -244,6 +244,7 @@ export class DevWatchOrchestrator {
244
244
  if (!this._hasPackages) {
245
245
  return;
246
246
  }
247
+ this._logger.debug("shutdown 시작");
247
248
 
248
249
  process.stdout.write("⏳ 종료 중...\n");
249
250
 
@@ -280,6 +281,7 @@ export class DevWatchOrchestrator {
280
281
  // --- Watch mode ---
281
282
 
282
283
  private async _startWatchMode(): Promise<void> {
284
+ this._logger.debug("watch 모드 시작");
283
285
  // Start copySrc watchers for library packages
284
286
  for (const pkg of this._libraryPackages) {
285
287
  if (pkg.config.copySrc != null && pkg.config.copySrc.length > 0) {
@@ -295,7 +297,7 @@ export class DevWatchOrchestrator {
295
297
 
296
298
  const watchPromises = this._libraryEngines.map(async (engine, i) => {
297
299
  const pkgName = this._libraryPackages[i].name;
298
- await engine.startWatch({ js: true, dts: true, lint: true });
300
+ await engine.startWatch({ js: true, dts: true, lint: false });
299
301
  completed++;
300
302
  this._logger.info(` [${completed}/${total}] ${pkgName} 완료`);
301
303
  });
@@ -309,7 +311,7 @@ export class DevWatchOrchestrator {
309
311
  // Start watch hook watchers for scripts+watch packages
310
312
  for (const pkg of this._watchHookPackages) {
311
313
  const watchConfig = pkg.config.watch!;
312
- const watchTargets = watchConfig.target.map((t) => path.resolve(pkg.dir, t));
314
+ const watchTargets = watchConfig.target.map((t) => pathx.posixResolve(pkg.dir, t));
313
315
 
314
316
  // Run initial hook
315
317
  this._runWatchHookCmd(pkg.name, pkg.dir, watchConfig.cmd, watchConfig.args);
@@ -355,14 +357,14 @@ export class DevWatchOrchestrator {
355
357
  for (const [name, engine] of this._clientEngines) {
356
358
  initialBuildPromises.push({
357
359
  name: `${name} (client)`,
358
- promise: engine.startWatch({ js: true, dts: false, lint: true }),
360
+ promise: engine.startWatch({ js: true, dts: false, lint: false }),
359
361
  });
360
362
  }
361
363
 
362
364
  for (const [name, engine] of this._serverEngines) {
363
365
  initialBuildPromises.push({
364
366
  name: `${name} (server)`,
365
- promise: engine.startWatch({ js: true, dts: false, lint: true }),
367
+ promise: engine.startWatch({ js: true, dts: false, lint: false }),
366
368
  });
367
369
  }
368
370
 
@@ -398,34 +400,13 @@ export class DevWatchOrchestrator {
398
400
  }
399
401
  }
400
402
 
401
- // Start runtimes for successful initial builds
402
- for (const { name, config } of this._serverPackages) {
403
- const buildResult = this._resultCollector.get(`${name}:build`);
404
- if (buildResult?.status === "success") {
405
- const mainJsPath = path.join(this._cwd, "packages", name, "dist", "main.js");
406
- const clientPorts = this._collectClientPorts(name);
407
- try {
408
- await this._startServerRuntime(name, mainJsPath, { ...this._baseEnv, ...config.env }, clientPorts);
409
- } catch (err) {
410
- this._logger.error(`[${name}] 서버 런타임 시작 실패:`, errNs.message(err));
411
- this._resultCollector.add({
412
- name,
413
- target: "server",
414
- type: "server",
415
- status: "error",
416
- message: errNs.message(err),
417
- });
418
- }
419
- }
420
- }
421
-
422
403
  // Start native apps for client packages with capacitor/electron config
423
404
  for (const { name, config } of this._clientPackages) {
424
405
  const port = this._getClientPort(name);
425
406
  if (port == null) continue;
426
407
 
427
408
  const devServerUrl = `http://localhost:${port}`;
428
- const pkgDir = path.join(this._cwd, "packages", name);
409
+ const pkgDir = pathx.posixResolve(this._cwd, "packages", name);
429
410
 
430
411
  if (config.capacitor != null) {
431
412
  try {
@@ -466,12 +447,28 @@ export class DevWatchOrchestrator {
466
447
  printServers(this._resultCollector.toMap(), this._serverClientsMap);
467
448
  }
468
449
 
469
- private _onDevBatchComplete(): void {
450
+ private _onDevBatchComplete(completedKeys: string[]): void {
451
+ this._logger.debug(`배치 완료 (${completedKeys.join(", ")})`);
452
+ const serverBuildKeys = this._serverPackages.map((p) => `${p.name}:build`);
453
+ if (!completedKeys.some((k) => serverBuildKeys.includes(k))) {
454
+ printErrors(this._resultCollector.toMap());
455
+ return;
456
+ }
457
+
458
+ if (this._serverRestartTimer != null) clearTimeout(this._serverRestartTimer);
459
+ this._serverRestartTimer = setTimeout(() => {
460
+ this._serverRestartTimer = undefined;
461
+ void this._restartServers();
462
+ }, 100);
463
+ }
464
+
465
+ private async _restartServers(): Promise<void> {
466
+ this._logger.debug("서버 재시작 시작");
470
467
  const restartPromises: Array<Promise<void>> = [];
471
468
  for (const { name, config } of this._serverPackages) {
472
469
  const buildResult = this._resultCollector.get(`${name}:build`);
473
470
  if (buildResult?.status === "success") {
474
- const mainJsPath = path.join(this._cwd, "packages", name, "dist", "main.js");
471
+ const mainJsPath = pathx.posixResolve(this._cwd, "packages", name, "dist", "main.js");
475
472
  const clientPorts = this._collectClientPorts(name);
476
473
  restartPromises.push(
477
474
  this._startServerRuntime(name, mainJsPath, { ...this._baseEnv, ...config.env }, clientPorts)
@@ -488,10 +485,10 @@ export class DevWatchOrchestrator {
488
485
  );
489
486
  }
490
487
  }
491
- void Promise.all(restartPromises).then(() => {
492
- printErrors(this._resultCollector.toMap());
493
- this._schedulePrintServers();
494
- });
488
+ await Promise.all(restartPromises);
489
+ this._logger.debug("서버 재시작 완료");
490
+ printErrors(this._resultCollector.toMap());
491
+ this._schedulePrintServers();
495
492
  }
496
493
 
497
494
  private _schedulePrintServers(): void {
@@ -16,22 +16,12 @@ import fs from "fs";
16
16
  import { fileURLToPath } from "url";
17
17
  import { EventEmitter } from "node:events";
18
18
  import { consola, LogLevels } from "consola";
19
+ import { SdCliReporter } from "./utils/SdCliReporter";
19
20
 
20
21
  Error.stackTraceLimit = Infinity;
21
22
  EventEmitter.defaultMaxListeners = 100;
22
23
 
23
- // consola 타임스탬프에 밀리초 포함
24
- for (const reporter of consola.options.reporters) {
25
- const r = reporter as { formatDate?: (date: Date, opts: { date?: boolean }) => string };
26
- if (typeof r.formatDate === "function") {
27
- const orig = r.formatDate.bind(r);
28
- r.formatDate = (date: Date, opts: { date?: boolean }) => {
29
- const base = orig(date, opts);
30
- if (base === "") return "";
31
- return `${base}.${String(date.getMilliseconds()).padStart(3, "0")}`;
32
- };
33
- }
34
- }
24
+ consola.options.reporters = [new SdCliReporter()];
35
25
 
36
26
  const COMMAND_NAMES = ["check", "watch", "dev", "build", "publish", "replace-deps"];
37
27
 
package/src/sd-cli.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  * .js execution (production): run replaceDeps then spawn sd-cli-entry in new process
8
8
  */
9
9
 
10
- import { execa } from "execa";
10
+ import { cpx } from "@simplysm/core-node";
11
11
  import os from "os";
12
12
  import path from "path";
13
13
  import { fileURLToPath } from "url";
@@ -40,7 +40,7 @@ if (isDev) {
40
40
 
41
41
  // Phase 2: Run actual CLI in new process (reset module cache)
42
42
  const cliEntryFilePath = path.join(__dirname, "sd-cli-entry.js");
43
- const subprocess = execa(
43
+ const subprocess = cpx.exec(
44
44
  "node",
45
45
  [
46
46
  "--max-old-space-size=8192",
@@ -52,7 +52,7 @@ if (isDev) {
52
52
  );
53
53
  if (subprocess.pid != null) configureAffinityAndPriority(subprocess.pid);
54
54
  const result = await subprocess;
55
- process.exitCode = result.exitCode ?? 0;
55
+ process.exitCode = result.exitCode;
56
56
  }
57
57
 
58
58
  /**
@@ -94,8 +94,11 @@ function configureAffinityAndPriority(pid: number): void {
94
94
  command = `taskset -p ${mask} ${pid} && renice +10 -p ${pid}`;
95
95
  }
96
96
 
97
- execa({ shell: true })`${command}`.catch((err: Error) => {
97
+ cpx.exec(command, [], { shell: true }).catch((err: unknown) => {
98
98
  // eslint-disable-next-line no-console
99
- console.warn("Failed to configure CPU affinity/priority:", err.message);
99
+ console.warn(
100
+ "Failed to configure CPU affinity/priority:",
101
+ err instanceof Error ? err.message : String(err),
102
+ );
100
103
  });
101
104
  }
@@ -0,0 +1,177 @@
1
+ import type { ConsolaReporter, LogObject, ConsolaOptions } from "consola";
2
+ import { formatWithOptions } from "node:util";
3
+ import { sep } from "node:path";
4
+
5
+ // -- Constants ----------------------------------------------------------------
6
+
7
+ const TYPE_ICONS: Record<string, string> = {
8
+ error: "✖",
9
+ fatal: "✖",
10
+ ready: "✔",
11
+ warn: "⚠",
12
+ info: "ℹ",
13
+ success: "✔",
14
+ debug: "⚙",
15
+ trace: "→",
16
+ fail: "✖",
17
+ start: "◐",
18
+ log: "",
19
+ };
20
+
21
+ type AnsiColor = "gray" | "red" | "green" | "yellow" | "cyan" | "magenta";
22
+
23
+ const TYPE_COLORS: Record<string, AnsiColor | undefined> = {
24
+ info: "cyan",
25
+ fail: "red",
26
+ success: "green",
27
+ ready: "green",
28
+ start: "magenta",
29
+ };
30
+
31
+ const LEVEL_COLORS: Record<number, AnsiColor | undefined> = {
32
+ 0: "red",
33
+ 1: "yellow",
34
+ };
35
+
36
+ const ANSI_CODES: Record<AnsiColor, string> = {
37
+ gray: "\x1b[90m",
38
+ red: "\x1b[31m",
39
+ green: "\x1b[32m",
40
+ yellow: "\x1b[33m",
41
+ cyan: "\x1b[36m",
42
+ magenta: "\x1b[35m",
43
+ };
44
+
45
+ const ANSI_RESET = "\x1b[0m";
46
+
47
+ // -- Helpers ------------------------------------------------------------------
48
+
49
+ function colorize(color: AnsiColor, text: string, enabled: boolean): string {
50
+ if (!enabled) return text;
51
+ return `${ANSI_CODES[color]}${text}${ANSI_RESET}`;
52
+ }
53
+
54
+ function writeStream(data: string, stream: NodeJS.WritableStream): void {
55
+ const s = stream as NodeJS.WritableStream & { __write?: typeof stream.write };
56
+ const write = s.__write ?? s.write;
57
+ write.call(stream, data);
58
+ }
59
+
60
+ function detectColorSupport(): boolean {
61
+ if (process.env["NO_COLOR"] != null) return false;
62
+ if (process.env["FORCE_COLOR"] != null) return true;
63
+ if (process.stdout.isTTY === true) return true;
64
+ // 워커 스레드에서는 process.stdout.isTTY가 없음. Windows 터미널은 ANSI 지원.
65
+ return process.platform === "win32";
66
+ }
67
+
68
+ // -- Reporter -----------------------------------------------------------------
69
+
70
+ interface FormatOpts {
71
+ date?: boolean;
72
+ colors: boolean;
73
+ compact?: boolean | number;
74
+ errorLevel?: number;
75
+ }
76
+
77
+ /**
78
+ * sd-cli 전용 consola reporter.
79
+ * 모든 로그를 `[tag] icon message time` 형식으로 통일한다.
80
+ */
81
+ export class SdCliReporter implements ConsolaReporter {
82
+ log(logObj: LogObject, ctx: { options: ConsolaOptions }): void {
83
+ const opts: FormatOpts = {
84
+ ...ctx.options.formatOptions,
85
+ colors: detectColorSupport(),
86
+ };
87
+
88
+ const line = this._formatLogObj(logObj, opts);
89
+ const stream =
90
+ logObj.level < 2
91
+ ? ctx.options.stderr ?? process.stderr
92
+ : ctx.options.stdout ?? process.stdout;
93
+
94
+ writeStream(line + "\n", stream);
95
+ }
96
+
97
+ private _formatLogObj(logObj: LogObject, opts: FormatOpts): string {
98
+ const formattedArgs = this._formatArgs(logObj.args, opts);
99
+ const [message, ...additional] = formattedArgs.split("\n");
100
+
101
+ if (logObj.type === "box") {
102
+ return this._formatBox(logObj, formattedArgs);
103
+ }
104
+
105
+ // Build: [tag] icon message time
106
+ const tag = logObj.tag !== "" ? colorize("gray", `[${logObj.tag}]`, opts.colors) : "";
107
+ const icon = this._formatIcon(logObj, opts.colors);
108
+ const date = this._formatDate(logObj.date, opts);
109
+ const coloredDate = date !== "" ? colorize("gray", date, opts.colors) : "";
110
+
111
+ let fullLine = [tag, icon, message, coloredDate].filter(Boolean).join(" ");
112
+
113
+ if (additional.length > 0) {
114
+ fullLine += "\n" + additional.join("\n");
115
+ }
116
+
117
+ if (logObj.type === "trace") {
118
+ const err = new Error("Trace: " + logObj.message);
119
+ fullLine += this._formatStack(err.stack ?? "", err.message);
120
+ }
121
+
122
+ const isBadge = (logObj as LogObject & { badge?: boolean }).badge ?? logObj.level < 2;
123
+ return isBadge ? "\n" + fullLine + "\n" : fullLine;
124
+ }
125
+
126
+ private _formatArgs(args: unknown[], opts: FormatOpts): string {
127
+ const processed = args.map((arg) => {
128
+ if (arg != null && typeof arg === "object" && typeof (arg as Error).stack === "string") {
129
+ return this._formatError(arg as Error, opts);
130
+ }
131
+ return arg;
132
+ });
133
+ return formatWithOptions({ colors: opts.colors, compact: opts.compact }, ...processed);
134
+ }
135
+
136
+ private _formatError(err: Error, opts: FormatOpts): string {
137
+ const message = err.message;
138
+ const stack = err.stack != null ? this._formatStack(err.stack, message, opts) : "";
139
+ const level = opts.errorLevel ?? 0;
140
+ const prefix = level > 0 ? `${" ".repeat(level)}[cause]: ` : "";
141
+ const cause =
142
+ err.cause instanceof Error
143
+ ? "\n\n" + this._formatError(err.cause, { ...opts, errorLevel: level + 1 })
144
+ : "";
145
+ return prefix + message + "\n" + stack + cause;
146
+ }
147
+
148
+ private _formatStack(stack: string, message: string, opts?: FormatOpts): string {
149
+ const cwd = process.cwd() + sep;
150
+ const indent = " ".repeat((opts?.errorLevel ?? 0) + 1);
151
+ const lines = stack
152
+ .split("\n")
153
+ .splice(message.split("\n").length)
154
+ .map((l) => l.trim().replace("file://", "").replace(cwd, ""));
155
+ return `\n${indent}` + lines.map((l) => ` ${l}`).join(`\n${indent}`);
156
+ }
157
+
158
+ private _formatIcon(logObj: LogObject, useColors: boolean): string {
159
+ const icon = TYPE_ICONS[logObj.type] ?? "";
160
+ if (icon === "") return "";
161
+ const color: AnsiColor = TYPE_COLORS[logObj.type] ?? LEVEL_COLORS[logObj.level] ?? "gray";
162
+ return colorize(color, icon, useColors);
163
+ }
164
+
165
+ private _formatDate(date: Date, opts: FormatOpts): string {
166
+ if (!opts.date) return "";
167
+ const base = date.toLocaleTimeString();
168
+ return `${base}.${String(date.getMilliseconds()).padStart(3, "0")}`;
169
+ }
170
+
171
+ private _formatBox(logObj: LogObject, message: string): string {
172
+ const tag = logObj.tag !== "" ? `[${logObj.tag}]` : "";
173
+ const title = (logObj as LogObject & { title?: string }).title;
174
+ const lines = [tag, title, ...message.split("\n")].filter(Boolean);
175
+ return "\n" + lines.map((l) => ` > ${l}`).join("\n") + "\n";
176
+ }
177
+ }