@simplysm/sd-cli 14.1.9 → 14.1.11

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 (264) hide show
  1. package/dist/capacitor/capacitor-icon.js +2 -2
  2. package/dist/capacitor/capacitor-icon.js.map +1 -1
  3. package/dist/capacitor/capacitor-npm-config.d.ts +1 -1
  4. package/dist/capacitor/capacitor-npm-config.d.ts.map +1 -1
  5. package/dist/capacitor/capacitor-npm-config.js +11 -18
  6. package/dist/capacitor/capacitor-npm-config.js.map +1 -1
  7. package/dist/capacitor/capacitor.d.ts +1 -1
  8. package/dist/capacitor/capacitor.js +2 -2
  9. package/dist/capacitor/capacitor.js.map +1 -1
  10. package/dist/commands/check.d.ts.map +1 -1
  11. package/dist/commands/check.js +1 -0
  12. package/dist/commands/check.js.map +1 -1
  13. package/dist/commands/device.js +2 -2
  14. package/dist/commands/device.js.map +1 -1
  15. package/dist/commands/init/generators/root.d.ts.map +1 -1
  16. package/dist/commands/init/generators/root.js +0 -1
  17. package/dist/commands/init/generators/root.js.map +1 -1
  18. package/dist/commands/init/init-client.js +1 -1
  19. package/dist/commands/init/init-client.js.map +1 -1
  20. package/dist/commands/init/init.js +2 -2
  21. package/dist/commands/init/init.js.map +1 -1
  22. package/dist/commands/publish/deployment-phase.d.ts.map +1 -1
  23. package/dist/commands/publish/deployment-phase.js +1 -0
  24. package/dist/commands/publish/deployment-phase.js.map +1 -1
  25. package/dist/commands/publish/npm-publisher.js +3 -3
  26. package/dist/commands/publish/npm-publisher.js.map +1 -1
  27. package/dist/commands/publish/post-publish-phase.d.ts.map +1 -1
  28. package/dist/commands/publish/post-publish-phase.js +1 -0
  29. package/dist/commands/publish/post-publish-phase.js.map +1 -1
  30. package/dist/commands/publish/publish-command.d.ts.map +1 -1
  31. package/dist/commands/publish/publish-command.js +7 -12
  32. package/dist/commands/publish/publish-command.js.map +1 -1
  33. package/dist/commands/publish/version-upgrade.d.ts.map +1 -1
  34. package/dist/commands/publish/version-upgrade.js +50 -0
  35. package/dist/commands/publish/version-upgrade.js.map +1 -1
  36. package/dist/deps/replace-deps/collect-deps.js +4 -4
  37. package/dist/deps/replace-deps/collect-deps.js.map +1 -1
  38. package/dist/deps/replace-deps/replace-deps-resolve.d.ts +4 -12
  39. package/dist/deps/replace-deps/replace-deps-resolve.d.ts.map +1 -1
  40. package/dist/deps/replace-deps/replace-deps-resolve.js +13 -49
  41. package/dist/deps/replace-deps/replace-deps-resolve.js.map +1 -1
  42. package/dist/deps/replace-deps/replace-deps.d.ts +2 -2
  43. package/dist/deps/replace-deps/replace-deps.js +3 -3
  44. package/dist/deps/server-externals/server-production-files.d.ts +3 -3
  45. package/dist/deps/server-externals/server-production-files.d.ts.map +1 -1
  46. package/dist/deps/server-externals/server-production-files.js +24 -17
  47. package/dist/deps/server-externals/server-production-files.js.map +1 -1
  48. package/dist/electron/electron.d.ts.map +1 -1
  49. package/dist/electron/electron.js +6 -11
  50. package/dist/electron/electron.js.map +1 -1
  51. package/dist/engines/BaseEngine.d.ts +1 -0
  52. package/dist/engines/BaseEngine.d.ts.map +1 -1
  53. package/dist/engines/BaseEngine.js +2 -1
  54. package/dist/engines/BaseEngine.js.map +1 -1
  55. package/dist/esbuild/esbuild-config.d.ts +6 -2
  56. package/dist/esbuild/esbuild-config.d.ts.map +1 -1
  57. package/dist/esbuild/esbuild-config.js +4 -3
  58. package/dist/esbuild/esbuild-config.js.map +1 -1
  59. package/dist/esbuild/esbuild-tsc-plugin.d.ts.map +1 -1
  60. package/dist/esbuild/esbuild-tsc-plugin.js +3 -1
  61. package/dist/esbuild/esbuild-tsc-plugin.js.map +1 -1
  62. package/dist/orchestrators/BaseOrchestrator.d.ts.map +1 -1
  63. package/dist/orchestrators/BaseOrchestrator.js +1 -0
  64. package/dist/orchestrators/BaseOrchestrator.js.map +1 -1
  65. package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
  66. package/dist/orchestrators/BuildOrchestrator.js +3 -5
  67. package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
  68. package/dist/orchestrators/DevOrchestrator.d.ts.map +1 -1
  69. package/dist/orchestrators/DevOrchestrator.js +1 -0
  70. package/dist/orchestrators/DevOrchestrator.js.map +1 -1
  71. package/dist/orchestrators/ServerRuntimeManager.d.ts.map +1 -1
  72. package/dist/orchestrators/ServerRuntimeManager.js +4 -0
  73. package/dist/orchestrators/ServerRuntimeManager.js.map +1 -1
  74. package/dist/orchestrators/TypecheckOrchestrator.d.ts.map +1 -1
  75. package/dist/orchestrators/TypecheckOrchestrator.js +4 -6
  76. package/dist/orchestrators/TypecheckOrchestrator.js.map +1 -1
  77. package/dist/runtime/engine-watch-events.d.ts.map +1 -1
  78. package/dist/runtime/engine-watch-events.js +5 -0
  79. package/dist/runtime/engine-watch-events.js.map +1 -1
  80. package/dist/runtime/worker-events.d.ts +1 -0
  81. package/dist/runtime/worker-events.d.ts.map +1 -1
  82. package/dist/sd-cli-entry.d.ts.map +1 -1
  83. package/dist/sd-cli-entry.js +0 -4
  84. package/dist/sd-cli-entry.js.map +1 -1
  85. package/dist/sd-cli.js +2 -0
  86. package/dist/sd-cli.js.map +1 -1
  87. package/dist/typecheck/typecheck-non-package.d.ts.map +1 -1
  88. package/dist/typecheck/typecheck-non-package.js +10 -0
  89. package/dist/typecheck/typecheck-non-package.js.map +1 -1
  90. package/dist/utils/package-utils.d.ts +8 -6
  91. package/dist/utils/package-utils.d.ts.map +1 -1
  92. package/dist/utils/package-utils.js +26 -24
  93. package/dist/utils/package-utils.js.map +1 -1
  94. package/dist/utils/workspace-utils.d.ts +17 -0
  95. package/dist/utils/workspace-utils.d.ts.map +1 -0
  96. package/dist/utils/workspace-utils.js +95 -0
  97. package/dist/utils/workspace-utils.js.map +1 -0
  98. package/dist/workers/client.worker.d.ts +1 -0
  99. package/dist/workers/client.worker.d.ts.map +1 -1
  100. package/dist/workers/client.worker.js +8 -3
  101. package/dist/workers/client.worker.js.map +1 -1
  102. package/dist/workers/library-build.worker.d.ts +1 -0
  103. package/dist/workers/library-build.worker.d.ts.map +1 -1
  104. package/dist/workers/library-build.worker.js +3 -2
  105. package/dist/workers/library-build.worker.js.map +1 -1
  106. package/dist/workers/server-build.worker.d.ts +1 -0
  107. package/dist/workers/server-build.worker.d.ts.map +1 -1
  108. package/dist/workers/server-build.worker.js +12 -12
  109. package/dist/workers/server-build.worker.js.map +1 -1
  110. package/dist/workers/server-esbuild-context.d.ts.map +1 -1
  111. package/dist/workers/server-esbuild-context.js +4 -2
  112. package/dist/workers/server-esbuild-context.js.map +1 -1
  113. package/dist/workers/server-runtime.worker.d.ts +1 -0
  114. package/dist/workers/server-runtime.worker.d.ts.map +1 -1
  115. package/dist/workers/server-runtime.worker.js +9 -3
  116. package/dist/workers/server-runtime.worker.js.map +1 -1
  117. package/dist/workers/server-watch-manager.d.ts +1 -1
  118. package/dist/workers/server-watch-manager.d.ts.map +1 -1
  119. package/dist/workers/server-watch-manager.js +2 -2
  120. package/dist/workers/server-watch-manager.js.map +1 -1
  121. package/package.json +11 -11
  122. package/src/capacitor/capacitor-icon.ts +2 -2
  123. package/src/capacitor/capacitor-npm-config.ts +10 -19
  124. package/src/capacitor/capacitor.ts +2 -2
  125. package/src/commands/check.ts +1 -0
  126. package/src/commands/device.ts +2 -2
  127. package/src/commands/init/generators/root.ts +0 -1
  128. package/src/commands/init/init-client.ts +1 -1
  129. package/src/commands/init/init.ts +2 -2
  130. package/src/commands/init/templates/workspace-root/mise.toml.hbs +1 -1
  131. package/src/commands/publish/deployment-phase.ts +1 -0
  132. package/src/commands/publish/npm-publisher.ts +3 -3
  133. package/src/commands/publish/post-publish-phase.ts +1 -0
  134. package/src/commands/publish/publish-command.ts +7 -15
  135. package/src/commands/publish/version-upgrade.ts +51 -0
  136. package/src/deps/replace-deps/collect-deps.ts +4 -4
  137. package/src/deps/replace-deps/replace-deps-resolve.ts +13 -56
  138. package/src/deps/replace-deps/replace-deps.ts +3 -3
  139. package/src/deps/server-externals/server-production-files.ts +31 -18
  140. package/src/electron/electron.ts +7 -13
  141. package/src/engines/BaseEngine.ts +3 -2
  142. package/src/esbuild/esbuild-config.ts +12 -3
  143. package/src/esbuild/esbuild-tsc-plugin.ts +4 -1
  144. package/src/orchestrators/BaseOrchestrator.ts +1 -0
  145. package/src/orchestrators/BuildOrchestrator.ts +3 -5
  146. package/src/orchestrators/DevOrchestrator.ts +1 -0
  147. package/src/orchestrators/ServerRuntimeManager.ts +4 -0
  148. package/src/orchestrators/TypecheckOrchestrator.ts +4 -6
  149. package/src/runtime/engine-watch-events.ts +7 -1
  150. package/src/runtime/worker-events.ts +1 -0
  151. package/src/sd-cli-entry.ts +0 -9
  152. package/src/sd-cli.ts +2 -0
  153. package/src/typecheck/typecheck-non-package.ts +11 -0
  154. package/src/utils/package-utils.ts +30 -23
  155. package/src/utils/workspace-utils.ts +117 -0
  156. package/src/workers/client.worker.ts +9 -4
  157. package/src/workers/library-build.worker.ts +4 -3
  158. package/src/workers/server-build.worker.ts +13 -13
  159. package/src/workers/server-esbuild-context.ts +5 -2
  160. package/src/workers/server-runtime.worker.ts +10 -3
  161. package/src/workers/server-watch-manager.ts +3 -3
  162. package/tests/capacitor/capacitor-build.spec.ts +142 -142
  163. package/tests/capacitor/capacitor-init.spec.ts +181 -181
  164. package/tests/capacitor/capacitor-npm-config.acc.spec.ts +114 -114
  165. package/tests/capacitor/capacitor-npm-config.spec.ts +94 -94
  166. package/tests/commands/publish-manifest.acc.spec.ts +67 -0
  167. package/tests/deps/replace-deps/collect-deps.acc.spec.ts +16 -1
  168. package/tests/deps/replace-deps/replace-deps-resolve.acc.spec.ts +9 -5
  169. package/tests/deps/replace-deps/replace-deps-setup.acc.spec.ts +3 -3
  170. package/tests/deps/server-externals/server-production-files.spec.ts +68 -0
  171. package/tests/electron/electron.spec.ts +608 -608
  172. package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck-browser.tsbuildinfo +1 -1
  173. package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck-node.tsbuildinfo +1 -1
  174. package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck.tsbuildinfo +1 -1
  175. package/tests/utils/engine-watch-events.spec.ts +17 -0
  176. package/tests/utils/esbuild-config.spec.ts +15 -0
  177. package/tests/utils/package-utils.spec.ts +36 -4
  178. package/tests/utils/replace-deps-watch.acc.spec.ts +4 -4
  179. package/tests/utils/replace-deps-watch.spec.ts +3 -3
  180. package/tests/utils/replace-deps.spec.ts +1 -35
  181. package/tests/utils/workspace-utils.spec.ts +87 -0
  182. package/tests/workers/library-build-worker.spec.ts +1 -1
  183. package/tests/workers/server-esbuild-context.spec.ts +4 -3
  184. package/dist/commands/reinstall.d.ts +0 -13
  185. package/dist/commands/reinstall.d.ts.map +0 -1
  186. package/dist/commands/reinstall.js +0 -56
  187. package/dist/commands/reinstall.js.map +0 -1
  188. package/src/commands/init/templates/workspace-root/pnpm-workspace.yaml +0 -5
  189. package/src/commands/reinstall.ts +0 -63
  190. package/tests/angular/angular-compiler-hmr-removal.verify.md +0 -16
  191. package/tests/angular/onbuild-lint-removal.verify.md +0 -8
  192. package/tests/angular/vite-angular-plugin-sdtscompiler.verify.md +0 -13
  193. package/tests/angular/vite-angular-plugin-vitest.verify.md +0 -20
  194. package/tests/capacitor/capacitor-android-exports.verify.md +0 -11
  195. package/tests/commands/publish-npm-local-split.verify.md +0 -9
  196. package/tests/commands/publish-responsibility-split.verify.md +0 -13
  197. package/tests/commands/publish-set.verify.md +0 -7
  198. package/tests/commands/publish-storage-split.verify.md +0 -8
  199. package/tests/commands/slice3-severity-cleanup.verify.md +0 -12
  200. package/tests/deps/deps-directory-separation.verify.md +0 -15
  201. package/tests/deps/replace-deps/replace-deps-perf.verify.md +0 -15
  202. package/tests/deps/server-externals/mise-toml-parse-intent.verify.md +0 -16
  203. package/tests/electron/electron-symlink-cleanup.verify.md +0 -8
  204. package/tests/engines/engine-duplicate-output-removal.verify.md +0 -10
  205. package/tests/engines/engine-typecheck-selection.verify.md +0 -8
  206. package/tests/engines/esbuild-client-engine.verify.md +0 -15
  207. package/tests/engines/normalize-result.verify.md +0 -9
  208. package/tests/engines/vite-dependency-cleanup.verify.md +0 -24
  209. package/tests/esbuild/esbuild-angular-compiler-plugin-hmr.verify.md +0 -23
  210. package/tests/esbuild/esbuild-angular-compiler-plugin-onload.verify.md +0 -21
  211. package/tests/esbuild/esbuild-angular-compiler-plugin-onstart-extraction.verify.md +0 -16
  212. package/tests/esbuild/esbuild-angular-compiler-plugin-sdtscompiler.verify.md +0 -15
  213. package/tests/esbuild/esbuild-angular-compiler-plugin-stylesheet.verify.md +0 -31
  214. package/tests/esbuild/esbuild-angular-compiler-plugin-worker.verify.md +0 -59
  215. package/tests/esbuild/esbuild-angular-compiler-plugin.verify.md +0 -21
  216. package/tests/esbuild/esbuild-postcss-plugin-chunking.verify.md +0 -17
  217. package/tests/esbuild/esbuild-tsc-plugin-imports.verify.md +0 -13
  218. package/tests/esbuild/esbuild-worker-plugin-node.verify.md +0 -12
  219. package/tests/esbuild/esbuild-worker-plugin.verify.md +0 -7
  220. package/tests/orchestrators/dist-delete-watcher.verify.md +0 -10
  221. package/tests/orchestrators/orchestrator-baseenv.verify.md +0 -10
  222. package/tests/orchestrators/orchestrator-diagnostic-formatting.verify.md +0 -10
  223. package/tests/orchestrators/orchestrator-initializemode-signature.verify.md +0 -9
  224. package/tests/orchestrators/slice1-stdout-to-consola.verify.md +0 -10
  225. package/tests/sd-cli-catch-all.verify.md +0 -7
  226. package/tests/sd-cli-log-tag.verify.md +0 -11
  227. package/tests/ts-compiler/SdTsCompiler-affected-files.verify.md +0 -8
  228. package/tests/ts-compiler/SdTsCompiler-crash-handling.verify.md +0 -24
  229. package/tests/ts-compiler/SdTsCompiler-diagnostics.verify.md +0 -12
  230. package/tests/ts-compiler/SdTsCompiler-emit.verify.md +0 -9
  231. package/tests/ts-compiler/SdTsCompiler.verify.md +0 -41
  232. package/tests/ts-compiler/scss-lint-integration.verify.md +0 -14
  233. package/tests/utils/copy-public-outdir.verify.md +0 -8
  234. package/tests/utils/dev-http-server.verify.md +0 -8
  235. package/tests/utils/engine-watch-events.verify.md +0 -17
  236. package/tests/utils/esbuild-client-config-integration.verify.md +0 -9
  237. package/tests/utils/esbuild-client-config-postcss.verify.md +0 -6
  238. package/tests/utils/esbuild-client-config.verify.md +0 -26
  239. package/tests/utils/esbuild-index-html.verify.md +0 -10
  240. package/tests/utils/esbuild-pwa.verify.md +0 -9
  241. package/tests/utils/esbuild-scss-plugin.verify.md +0 -8
  242. package/tests/utils/hmr-service.verify.md +0 -17
  243. package/tests/utils/lint-core-import-paths.verify.md +0 -10
  244. package/tests/utils/replace-deps-split.verify.md +0 -15
  245. package/tests/utils/replace-deps-watch.verify.md +0 -9
  246. package/tests/utils/server-production-files-import-paths.verify.md +0 -14
  247. package/tests/utils/vite-config-cleanup.verify.md +0 -7
  248. package/tests/workers/build-watch-paths-library.verify.md +0 -10
  249. package/tests/workers/build-watch-paths-ngtsc-server.verify.md +0 -12
  250. package/tests/workers/client-worker-browser-support.verify.md +0 -7
  251. package/tests/workers/client-worker-cleanup.verify.md +0 -8
  252. package/tests/workers/client-worker-initial-build-error.verify.md +0 -7
  253. package/tests/workers/client-worker-initial-build-warnings.verify.md +0 -7
  254. package/tests/workers/client-worker-mtime-incremental.verify.md +0 -10
  255. package/tests/workers/client-worker-onend-sync.verify.md +0 -7
  256. package/tests/workers/client-worker-refactor.verify.md +0 -22
  257. package/tests/workers/client-worker-ts-cache-invalidation.verify.md +0 -12
  258. package/tests/workers/dev-port-file.verify.md +0 -6
  259. package/tests/workers/ngtsc-build-rootnames-refresh.verify.md +0 -8
  260. package/tests/workers/server-build-context-dispose.verify.md +0 -8
  261. package/tests/workers/server-build-worker-plugin.verify.md +0 -9
  262. package/tests/workers/server-build-worker-refactoring.verify.md +0 -14
  263. package/tests/workers/server-esbuild-context-integration.verify.md +0 -10
  264. package/tests/workers/server-esbuild-context-tsc.verify.md +0 -7
@@ -6,9 +6,8 @@ import type { SdConfig, SdPublishConfig } from "../../sd-config.types";
6
6
  import { loadSdConfig } from "../../utils/sd-config";
7
7
  import { validateTargets } from "../../utils/package-utils";
8
8
  import { shellSpawn } from "../../utils/shell-spawn";
9
+ import { collectWorkspacePackages } from "../../utils/workspace-utils";
9
10
  import { runBuild } from "../build";
10
- import { parseWorkspaceGlobs } from "../../deps/replace-deps/replace-deps-resolve";
11
- import fs from "fs";
12
11
  import { ensureSshAuth } from "./storage-publisher";
13
12
  import { type PackageJson, upgradeVersion } from "./version-upgrade";
14
13
  import { waitWithCountdown } from "./env-utils";
@@ -65,6 +64,7 @@ export async function runPublish(options: PublishOptions): Promise<void> {
65
64
  logger.debug("sd.config.ts 로드 완료");
66
65
  } catch (err) {
67
66
  logger.error(`sd.config.ts 로드 실패: ${errNs.message(err)}`);
67
+ logger.debug(`sd.config.ts 로드 실패 스택:\n${errNs.stack(err)}`);
68
68
  process.exitCode = 1;
69
69
  return;
70
70
  }
@@ -76,19 +76,8 @@ export async function runPublish(options: PublishOptions): Promise<void> {
76
76
  const projPkgPath = path.resolve(cwd, "package.json");
77
77
  const projPkg = await fsx.readJson<PackageJson>(projPkgPath);
78
78
 
79
- // pnpm-workspace.yaml에서 워크스페이스 패키지 경로 수집
80
- const workspaceYamlPath = path.resolve(cwd, "pnpm-workspace.yaml");
81
- const workspaceGlobs: string[] = [];
82
- if (await fsx.exists(workspaceYamlPath)) {
83
- const yamlContent = await fsx.read(workspaceYamlPath);
84
- workspaceGlobs.push(...parseWorkspaceGlobs(yamlContent));
85
- }
86
-
87
- const allPkgPaths = (
88
- await Promise.all(workspaceGlobs.map((item) => fsx.glob(path.resolve(cwd, item))))
89
- )
90
- .flat()
91
- .filter((item) => fs.existsSync(path.join(item, "package.json")));
79
+ // package.json#workspaces에서 워크스페이스 패키지 경로 수집
80
+ const allPkgPaths = collectWorkspacePackages(cwd).map((item) => item.absPath);
92
81
 
93
82
  // publish 설정이 있는 패키지 필터링
94
83
  const publishPackages: Array<{
@@ -159,6 +148,7 @@ export async function runPublish(options: PublishOptions): Promise<void> {
159
148
  await ensureSshAuth(publishPackages, logger);
160
149
  } catch (err) {
161
150
  logger.error(`SSH 인증 설정 실패: ${errNs.message(err)}`);
151
+ logger.debug(`SSH 인증 설정 실패 스택:\n${errNs.stack(err)}`);
162
152
  process.exitCode = 1;
163
153
  return;
164
154
  }
@@ -169,6 +159,7 @@ export async function runPublish(options: PublishOptions): Promise<void> {
169
159
  await ensureCleanWorkingTree(hasGit, logger);
170
160
  } catch (err) {
171
161
  logger.error(errNs.message(err));
162
+ logger.debug(`작업 트리 확인 실패 스택:\n${errNs.stack(err)}`);
172
163
  process.exitCode = 1;
173
164
  return;
174
165
  }
@@ -233,6 +224,7 @@ export async function runPublish(options: PublishOptions): Promise<void> {
233
224
  await commitTagAndPush(hasGit, version, _changedFiles, logger, dryRun);
234
225
  } catch (err) {
235
226
  logger.error(errNs.message(err));
227
+ logger.debug(`Git 배포 단계 실패 스택:\n${errNs.stack(err)}`);
236
228
  process.exitCode = 1;
237
229
  return;
238
230
  }
@@ -15,6 +15,46 @@ export interface PackageJson {
15
15
  optionalDependencies?: Record<string, string>;
16
16
  }
17
17
 
18
+ /**
19
+ * bun.lock의 workspaces 섹션에 스냅샷된 각 워크스페이스 패키지 version을 새 버전으로 맞춘다.
20
+ *
21
+ * bun publish/pack은 `workspace:*` 의존성을 치환할 때 대상 패키지의 package.json이 아니라
22
+ * bun.lock의 `workspaces.<dir>.version`을 읽는다 (bun 1.2.8+, oven-sh/bun#20477). 또한 version만
23
+ * bump하면 `bun install`이 lock의 워크스페이스 version을 갱신하지 않으므로 (oven-sh/bun#18906),
24
+ * package.json만 올리면 lock이 뒤처져 이전 버전으로 치환된다. 이를 막기 위해 lock을 직접 맞춘다.
25
+ *
26
+ * `"version"` 키는 workspaces 섹션에만 나타나므로(packages 섹션의 의존성은 `"name@ver"` 배열 형태),
27
+ * workspaces 객체 범위 안의 `"version"` 값만 새 버전으로 치환한다. 값이 아닌 위치 기준이라
28
+ * lock이 몇 버전 뒤처져 있든 정확히 맞춰진다.
29
+ */
30
+ function syncBunLockWorkspaceVersions(content: string, newVersion: string): string {
31
+ const wsKeyIdx = content.indexOf('"workspaces":');
32
+ if (wsKeyIdx === -1) return content;
33
+
34
+ const braceStart = content.indexOf("{", wsKeyIdx);
35
+ if (braceStart === -1) return content;
36
+
37
+ // balanced brace로 workspaces 객체의 끝을 찾는다 (값 문자열에 중괄호가 없어 안전).
38
+ let depth = 0;
39
+ let braceEnd = -1;
40
+ for (let i = braceStart; i < content.length; i++) {
41
+ const ch = content[i];
42
+ if (ch === "{") depth++;
43
+ else if (ch === "}") {
44
+ depth--;
45
+ if (depth === 0) {
46
+ braceEnd = i;
47
+ break;
48
+ }
49
+ }
50
+ }
51
+ if (braceEnd === -1) return content;
52
+
53
+ const section = content.slice(braceStart, braceEnd + 1);
54
+ const newSection = section.replace(/("version"\s*:\s*)"[^"]*"/g, `$1"${newVersion}"`);
55
+ return content.slice(0, braceStart) + newSection + content.slice(braceEnd + 1);
56
+ }
57
+
18
58
  /**
19
59
  * 프로젝트 및 패키지 버전 업그레이드
20
60
  * @param dryRun true이면 파일을 수정하지 않고 새 버전만 계산
@@ -58,6 +98,17 @@ export async function upgradeVersion(
58
98
  );
59
99
  changedFiles.push(...pkgChangedFiles);
60
100
 
101
+ // bun.lock의 워크스페이스 version 동기화 (bun publish가 lock을 읽어 workspace:* 를 치환하므로)
102
+ const bunLockPath = path.resolve(cwd, "bun.lock");
103
+ if (await fsx.exists(bunLockPath)) {
104
+ const lockContent = await fsx.read(bunLockPath);
105
+ const newLockContent = syncBunLockWorkspaceVersions(lockContent, newVersion);
106
+ if (newLockContent !== lockContent) {
107
+ await fsx.write(bunLockPath, newLockContent);
108
+ changedFiles.push(bunLockPath);
109
+ }
110
+ }
111
+
61
112
  // 템플릿 파일의 @simplysm 패키지 버전 동기화
62
113
  const templateFiles = await fsx.glob(path.resolve(cwd, "packages/sd-cli/templates/**/*.hbs"));
63
114
  const versionRegex = /("@simplysm\/[^"]+"\s*:\s*)"~[^"]+"/g;
@@ -11,15 +11,15 @@ export interface DepsResult {
11
11
  }
12
12
 
13
13
  /**
14
- * 워크스페이스 디렉토리(packages/, tests/) 스캔 기반으로 packages/ 패키지의 name → 상대 디렉토리 맵을 구성한다.
15
- * tests/ 패키지는 제외된다.
14
+ * package.json#workspaces 기반으로 packages/(배포 대상) 패키지의 name → 상대 디렉토리 맵을 구성한다.
15
+ * packages/ 가 아닌 워크스페이스(tests/·plugins/ 등)는 제외된다.
16
16
  * 예: "@simplysm/core-node" → "packages/core-node"
17
17
  */
18
18
  function buildWorkspacePkgMap(cwd: string): Map<string, string> {
19
19
  const map = new Map<string, string>();
20
20
  const wsPkgs = discoverWorkspacePackages(cwd);
21
21
  for (const [, relDir] of wsPkgs) {
22
- if (relDir.startsWith("tests/")) continue;
22
+ if (!relDir.startsWith("packages/")) continue;
23
23
  const pkgJsonPath = pathx.posix(path.join(cwd, relDir, "package.json"));
24
24
  if (!fsx.existsSync(pkgJsonPath)) continue;
25
25
  const pkgJson = fsx.readJsonSync<{ name: string }>(pkgJsonPath);
@@ -36,7 +36,7 @@ export function collectDeps(
36
36
  const startTime = performance.now();
37
37
  logger.debug("의존성 수집 시작");
38
38
 
39
- // 워크스페이스 디렉토리 스캔으로 packages/ 패키지 맵 구성 (tests/ 제외)
39
+ // 워크스페이스 설정으로 packages/ 패키지 맵 구성 (tests/ 제외)
40
40
  const workspacePkgMap = buildWorkspacePkgMap(cwd);
41
41
 
42
42
  const replaceDepsPatterns: Array<{ regex: RegExp }> = [];
@@ -3,6 +3,7 @@ import path from "path";
3
3
  import { glob } from "glob";
4
4
  import type { ConsolaInstance } from "consola";
5
5
  import { fsx, pathx } from "@simplysm/core-node";
6
+ import { collectWorkspacePackages } from "../../utils/workspace-utils";
6
7
 
7
8
  /**
8
9
  * replaceDeps 설정의 glob 패턴을 대상 패키지 목록과 매칭하여
@@ -44,45 +45,6 @@ export function resolveReplaceDepEntries(
44
45
  return results;
45
46
  }
46
47
 
47
- /**
48
- * pnpm-workspace.yaml 내용을 파싱하여 워크스페이스 패키지 glob 배열을 반환한다.
49
- * 별도 YAML 라이브러리 없이 간단한 줄 파싱으로 처리한다.
50
- *
51
- * @param content - pnpm-workspace.yaml 파일 내용
52
- * @returns glob 패턴 배열 (예: ["packages/*", "tools/*"])
53
- */
54
- export function parseWorkspaceGlobs(content: string): string[] {
55
- const lines = content.split("\n");
56
- const globs: string[] = [];
57
- let inPackages = false;
58
-
59
- for (const line of lines) {
60
- const trimmed = line.trim();
61
-
62
- if (trimmed === "packages:") {
63
- inPackages = true;
64
- continue;
65
- }
66
-
67
- // packages 섹션의 목록 항목
68
- if (inPackages && trimmed.startsWith("- ")) {
69
- const value = trimmed
70
- .slice(2)
71
- .trim()
72
- .replace(/^["']|["']$/g, "");
73
- globs.push(value);
74
- continue;
75
- }
76
-
77
- // 다른 섹션이 시작되면 종료
78
- if (inPackages && trimmed !== "" && !trimmed.startsWith("#")) {
79
- break;
80
- }
81
- }
82
-
83
- return globs;
84
- }
85
-
86
48
  /**
87
49
  * replaceDeps 복사/교체 항목
88
50
  */
@@ -97,26 +59,21 @@ export interface ReplaceDepEntry {
97
59
  /**
98
60
  * 프로젝트 루트 및 워크스페이스 패키지 경로를 수집한다.
99
61
  *
100
- * pnpm-workspace.yaml을 파싱하여 워크스페이스 패키지의 절대 경로를 수집한다.
101
- * 파일이 없거나 파싱 실패 시 루트 경로만 반환한다.
62
+ * package.json#workspaces를 기준으로 워크스페이스 패키지의 절대 경로를 수집한다.
63
+ * 설정이 없거나 파싱 실패 시 루트 경로만 반환한다.
102
64
  *
103
65
  * @param projectRoot - 프로젝트 루트 경로
104
66
  * @returns [루트, ...워크스페이스 패키지 경로] 배열
105
67
  */
106
- export async function collectSearchRoots(projectRoot: string): Promise<string[]> {
107
- const searchRoots = [projectRoot];
68
+ export function collectSearchRoots(projectRoot: string): string[] {
69
+ const root = pathx.posix(projectRoot);
70
+ const searchRoots: string[] = [root];
108
71
 
109
- const workspaceYamlPath = pathx.posix(path.join(projectRoot, "pnpm-workspace.yaml"));
110
72
  try {
111
- const yamlContent = await fsx.read(workspaceYamlPath);
112
- const workspaceGlobs = parseWorkspaceGlobs(yamlContent);
113
-
114
- for (const pattern of workspaceGlobs) {
115
- const dirs = await fsx.glob(pattern, { cwd: projectRoot });
116
- searchRoots.push(...dirs);
117
- }
73
+ const workspacePackages = collectWorkspacePackages(root);
74
+ searchRoots.push(...workspacePackages.map((item) => item.absPath));
118
75
  } catch {
119
- // pnpm-workspace.yaml이 존재하지 않으면 루트만 처리
76
+ // workspace 설정이 없거나 파싱할 수 없으면 루트만 처리
120
77
  }
121
78
 
122
79
  return searchRoots;
@@ -125,7 +82,7 @@ export async function collectSearchRoots(projectRoot: string): Promise<string[]>
125
82
  /**
126
83
  * replaceDeps 설정에서 모든 교체 대상 항목을 해결한다.
127
84
  *
128
- * 1. pnpm-workspace.yaml 파싱 → 워크스페이스 패키지 경로
85
+ * 1. package.json#workspaces 파싱 → 워크스페이스 패키지 경로
129
86
  * 2. [루트, ...워크스페이스 패키지] node_modules에서 매칭 패키지 탐색
130
87
  * 3. 패턴 매칭 + 소스 경로 존재 확인 + symlink 해결
131
88
  *
@@ -144,7 +101,7 @@ export async function resolveAllReplaceDepEntries(
144
101
  const searchedDirs = new Set<string>();
145
102
 
146
103
  // 초기 탐색 대상: 프로젝트 루트 + workspace 패키지들의 node_modules
147
- const searchRoots = await collectSearchRoots(projectRoot);
104
+ const searchRoots = collectSearchRoots(projectRoot);
148
105
  const pendingDirs: string[] = searchRoots.map((root) =>
149
106
  pathx.posix(path.join(root, "node_modules")),
150
107
  );
@@ -188,7 +145,7 @@ export async function resolveAllReplaceDepEntries(
188
145
  continue;
189
146
  }
190
147
 
191
- // targetPath가 symlink이면 실제 .pnpm 저장소 경로로 해결
148
+ // targetPath가 symlink이면 실제 패키지 저장소 경로로 해결
192
149
  let actualTargetPath = targetPath;
193
150
  try {
194
151
  const stat = await fs.promises.lstat(targetPath);
@@ -199,7 +156,7 @@ export async function resolveAllReplaceDepEntries(
199
156
  // targetPath가 존재하지 않으면 그대로 사용
200
157
  }
201
158
 
202
- // 동일 actualTargetPath가 이미 등록된 경우 건너뜀 (pnpm 중복 방지)
159
+ // 동일 actualTargetPath가 이미 등록된 경우 건너뜀
203
160
  if (seenTargetPaths.has(actualTargetPath)) continue;
204
161
  seenTargetPaths.add(actualTargetPath);
205
162
 
@@ -32,7 +32,7 @@ async function isFileContentSame(pathA: string, pathB: string): Promise<boolean>
32
32
  }
33
33
 
34
34
  /**
35
- * pnpm hard link를 끊으면서 파일/디렉토리를 복사한다.
35
+ * package manager hard link를 끊으면서 파일/디렉토리를 복사한다.
36
36
  * 대상 파일을 먼저 unlink하여 글로벌 store의 hard link를 끊고 새 파일을 생성한다.
37
37
  * 다른 프로젝트의 node_modules에 영향을 주지 않기 위함이다.
38
38
  */
@@ -160,7 +160,7 @@ export interface WatchReplaceDepResult {
160
160
  /**
161
161
  * replaceDeps 설정에 따라 node_modules의 패키지를 소스 디렉토리로 교체한다.
162
162
  *
163
- * 1. pnpm-workspace.yaml 파싱 → 워크스페이스 패키지 경로
163
+ * 1. package.json#workspaces 파싱 → 워크스페이스 패키지 경로
164
164
  * 2. [루트, ...워크스페이스 패키지] node_modules에서 매칭 패키지 탐색
165
165
  * 3. 소스 package.json의 files 필드 + npm 기본 파일만 대상 경로에 복사 (package.json 제외)
166
166
  *
@@ -207,7 +207,7 @@ export async function setupReplaceDeps(
207
207
  /**
208
208
  * replaceDeps 설정에 따라 소스 디렉토리를 감시하고 변경사항을 대상 경로에 복사한다.
209
209
  *
210
- * 1. pnpm-workspace.yaml 파싱 → 워크스페이스 패키지 경로
210
+ * 1. package.json#workspaces 파싱 → 워크스페이스 패키지 경로
211
211
  * 2. [루트, ...워크스페이스 패키지] node_modules에서 매칭 패키지 탐색
212
212
  * 3. FsWatcher로 files 항목 경로만 감시 (300ms 딜레이)
213
213
  * 4. 변경사항을 대상 경로에 복사
@@ -29,30 +29,43 @@ export function collectAllExternals(
29
29
  };
30
30
  }
31
31
 
32
+ interface BunLockFile {
33
+ packages?: Record<string, unknown>;
34
+ }
35
+
36
+ function parsePackageReferenceVersion(reference: string): string | undefined {
37
+ const normalized = reference.split("(")[0];
38
+ const match = /^(.+?)@(\d[^@]*)$/.exec(normalized);
39
+ return match?.[2];
40
+ }
41
+
42
+ function parsePackageKeyName(key: string): string {
43
+ const match = /^(.+?)@(\d.+)$/.exec(key);
44
+ return match?.[1] ?? key;
45
+ }
46
+
32
47
  /**
33
- * pnpm-lock.yaml의 packages 섹션을 파싱하여 name→version 맵을 생성한다.
34
- * 키 형태: "name@version" · "@scope/name@version" · "name@version(peer@ver)..."
48
+ * bun.lock의 packages 섹션을 파싱하여 name→version 맵을 생성한다.
49
+ * 키 형태는 일반 패키지명 또는 alias이고, 실제 버전은 package entry의 resolution에서 확인한다.
35
50
  */
36
51
  export function parseLockfileVersions(cwd: string): Map<string, string> {
37
- const lockfilePath = path.join(cwd, "pnpm-lock.yaml");
52
+ const lockfilePath = path.join(cwd, "bun.lock");
38
53
  if (!fsx.existsSync(lockfilePath)) {
39
- throw new Error(`pnpm-lock.yaml not found in ${cwd}. Run "pnpm install" first.`);
54
+ throw new Error(`bun.lock not found in ${cwd}. Run "bun install" first.`);
40
55
  }
41
56
 
42
57
  const content = fsx.readSync(lockfilePath);
43
- const parsed = YAML.parse(content) as { packages?: Record<string, unknown> };
58
+ const parsed = YAML.parse(content) as BunLockFile;
44
59
  const map = new Map<string, string>();
45
60
 
46
- for (const key of Object.keys(parsed.packages ?? {})) {
47
- // 번째 @숫자 기준으로 name / version 분리 (scope 패키지의 선두 @ 보존)
48
- const m = /^(.+?)@(\d.+)$/.exec(key);
49
- if (m == null) continue;
50
- const name = m[1];
51
- // peerDep suffix "(peer@ver)..." 제거
52
- const parenIdx = m[2].indexOf("(");
53
- const version = parenIdx === -1 ? m[2] : m[2].substring(0, parenIdx);
54
- if (!map.has(name)) {
55
- map.set(name, version);
61
+ for (const [key, entry] of Object.entries(parsed.packages ?? {})) {
62
+ if (!Array.isArray(entry) || typeof entry[0] !== "string") continue;
63
+ const version = parsePackageReferenceVersion(entry[0]);
64
+ if (version == null) continue;
65
+
66
+ const keyName = parsePackageKeyName(key);
67
+ if (!map.has(keyName)) {
68
+ map.set(keyName, version);
56
69
  }
57
70
  }
58
71
 
@@ -60,7 +73,7 @@ export function parseLockfileVersions(cwd: string): Map<string, string> {
60
73
  }
61
74
 
62
75
  /**
63
- * pnpm-lock.yaml에서 주어진 모든 패키지의 잠긴 버전을 확인한다.
76
+ * bun.lock에서 주어진 모든 패키지의 잠긴 버전을 확인한다.
64
77
  * lockfile에서 패키지를 찾을 수 없으면 에러를 던진다.
65
78
  */
66
79
  export function resolveLockedVersions(cwd: string, pkgNames: string[]): Record<string, string> {
@@ -70,8 +83,8 @@ export function resolveLockedVersions(cwd: string, pkgNames: string[]): Record<s
70
83
  const version = versionMap.get(name);
71
84
  if (version == null) {
72
85
  throw new Error(
73
- `External dependency "${name}" not found in pnpm-lock.yaml. ` +
74
- `Run "pnpm install" and try again.`,
86
+ `External dependency "${name}" not found in bun.lock. ` +
87
+ `Run "bun install" and try again.`,
75
88
  );
76
89
  }
77
90
  result[name] = version;
@@ -68,20 +68,14 @@ export class Electron {
68
68
  await this._setupNpmConf();
69
69
  Electron._logger.debug("package.json 설정 완료");
70
70
 
71
- // pnpm-workspace.yaml 생성 (상위 workspace 탐색 차단)
72
- const workspaceYamlPath = pathx.posixResolve(this._srcPath, "pnpm-workspace.yaml");
73
- if (!(await fsx.exists(workspaceYamlPath))) {
74
- await fsx.write(workspaceYamlPath, "");
75
- }
76
-
77
- Electron._logger.debug("pnpm install 시작");
78
- await this._exec("pnpm", ["install", "--config.dangerously-allow-all-builds=true"], this._srcPath);
79
- Electron._logger.debug("pnpm install 완료");
71
+ Electron._logger.debug("bun install 시작");
72
+ await this._exec("bun", ["install"], this._srcPath);
73
+ Electron._logger.debug("bun install 완료");
80
74
 
81
75
  const reinstallDeps = this._config.reinstallDependencies ?? [];
82
76
  if (reinstallDeps.length > 0) {
83
77
  Electron._logger.debug(`electron-rebuild 시작 (${reinstallDeps.join(", ")})`);
84
- await this._exec("pnpm", ["exec", "electron-rebuild"], this._srcPath);
78
+ await this._exec("bun", ["run", "electron-rebuild"], this._srcPath);
85
79
  Electron._logger.debug("electron-rebuild 완료");
86
80
  }
87
81
  Electron._logger.success("initialize 완료");
@@ -102,7 +96,7 @@ export class Electron {
102
96
 
103
97
  const spawnElectron = () => {
104
98
  Electron._logger.debug("Electron 프로세스 시작");
105
- currentElectron = shellSpawn("pnpm", ["exec", "electron", "."], {
99
+ currentElectron = shellSpawn("bun", ["run", "electron", "."], {
106
100
  cwd: this._srcPath,
107
101
  stdio: "inherit",
108
102
  reject: false,
@@ -385,8 +379,8 @@ export class Electron {
385
379
 
386
380
  Electron._logger.debug(`electron-builder 설정: ${configFilePath}`);
387
381
  await this._exec(
388
- "pnpm",
389
- ["exec", "electron-builder", "--win", "--config", configFilePath],
382
+ "bun",
383
+ ["run", "electron-builder", "--win", "--config", configFilePath],
390
384
  this._srcPath,
391
385
  );
392
386
  }
@@ -21,7 +21,7 @@ export interface CommonBuildWorkerEvents extends Record<string, unknown> {
21
21
  build: { success: boolean; errors?: string[]; warnings?: string[] };
22
22
  lint?: LintWithProgramResult;
23
23
  };
24
- error: { message: string };
24
+ error: { message: string; stack?: string };
25
25
  }
26
26
 
27
27
  /**
@@ -180,7 +180,8 @@ export abstract class BaseEngine<
180
180
  });
181
181
 
182
182
  this._callStartWatch(output).catch((err: unknown) => {
183
- logger.debug(`[${this._pkg.name}] startWatch 실패:`, errNs.message(err));
183
+ logger.debug(`[${this._pkg.name}] startWatch 실패: ${errNs.message(err)}`);
184
+ logger.debug(`[${this._pkg.name}] startWatch 실패 스택:\n${errNs.stack(err)}`);
184
185
  this._resultCollector?.add({
185
186
  name: this._pkg.name,
186
187
  target: this._getTarget(),
@@ -7,18 +7,27 @@ import { addJsExtensionToImports } from "../utils/output-path-rewriter";
7
7
 
8
8
  const logger = createLogger("sd:cli:esbuild-config");
9
9
 
10
+ export interface WriteChangedOutputFilesOptions {
11
+ /** .js 파일의 확장자 없는 상대 import/export 경로에 .js를 붙일지 여부 */
12
+ rewriteJsExtensions?: boolean;
13
+ }
14
+
10
15
  /**
11
16
  * esbuild outputFiles에서 변경된 파일만 디스크에 쓴다.
12
17
  *
13
- * - .js 파일: 비교 전 ESM 상대 import 경로에 .js 확장자를 추가한다
18
+ * - .js 파일: 기본적으로 비교 전 ESM 상대 import 경로에 .js 확장자를 추가한다
14
19
  * - 기타 파일(.js.map 등): 원본 내용을 그대로 비교한다
15
20
  * - 기존 파일과 내용이 동일하면 타임스탬프 보존을 위해 쓰기를 스킵한다
16
21
  */
17
- export async function writeChangedOutputFiles(outputFiles: esbuild.OutputFile[]): Promise<void> {
22
+ export async function writeChangedOutputFiles(
23
+ outputFiles: esbuild.OutputFile[],
24
+ options?: WriteChangedOutputFilesOptions,
25
+ ): Promise<void> {
26
+ const rewriteJsExtensions = options?.rewriteJsExtensions ?? true;
18
27
  logger.debug(`변경된 출력 파일 쓰기 시작 (${outputFiles.length}개)`);
19
28
  await Promise.all(
20
29
  outputFiles.map(async (file) => {
21
- const finalText = file.path.endsWith(".js")
30
+ const finalText = file.path.endsWith(".js") && rewriteJsExtensions
22
31
  ? addJsExtensionToImports(file.text)
23
32
  : file.text;
24
33
 
@@ -1,12 +1,14 @@
1
1
  import type esbuild from "esbuild";
2
2
  import type ts from "typescript";
3
- import { err as errNs } from "@simplysm/core-common";
3
+ import { createLogger, err as errNs } from "@simplysm/core-common";
4
4
  import { SdTsCompiler } from "../ts-compiler/SdTsCompiler";
5
5
  import type { ISdTsCompilerResult } from "../ts-compiler/sd-ts-compiler-result";
6
6
  import type { SerializedDiagnostic } from "../typecheck/typecheck-serialization";
7
7
  import type { LintWithProgramResult } from "../lint/lint-with-program";
8
8
  import type { TypecheckEnv } from "../utils/tsconfig";
9
9
 
10
+ const logger = createLogger("sd:cli:esbuild-tsc-plugin");
11
+
10
12
  export interface TscPluginOptions {
11
13
  pkgDir: string;
12
14
  cwd: string;
@@ -69,6 +71,7 @@ export function createTscPlugin(options: TscPluginOptions): TscPluginResult {
69
71
  lastErrors = result.errors;
70
72
  lastLintResult = result.lint;
71
73
  } catch (err) {
74
+ logger.debug(`tsc plugin 예외 스택:\n${errNs.stack(err)}`);
72
75
  lastProgram = undefined;
73
76
  lastAffectedFiles = undefined;
74
77
  lastDiagnostics = [];
@@ -57,6 +57,7 @@ export abstract class BaseOrchestrator {
57
57
  this._logger.debug("sd.config.ts 로드 완료");
58
58
  } catch (err) {
59
59
  this._logger.error(`sd.config.ts 로드 실패: ${errNs.message(err)}`);
60
+ this._logger.debug(`sd.config.ts 로드 실패 스택:\n${errNs.stack(err)}`);
60
61
  process.exitCode = 1;
61
62
  throw err;
62
63
  }
@@ -152,6 +152,7 @@ export class BuildOrchestrator implements OrchestratorLifecycle<boolean> {
152
152
  this._logger.debug("sd.config.ts 로드 완료");
153
153
  } catch (err) {
154
154
  this._logger.error(`sd.config.ts 로드 실패: ${errNs.message(err)}`);
155
+ this._logger.debug(`sd.config.ts 로드 실패 스택:\n${errNs.stack(err)}`);
155
156
  process.exitCode = 1;
156
157
  throw err;
157
158
  }
@@ -238,13 +239,10 @@ export class BuildOrchestrator implements OrchestratorLifecycle<boolean> {
238
239
  for (const settledResult of buildResults) {
239
240
  if (settledResult.status === "rejected") {
240
241
  const err = settledResult.reason;
241
- const stack = err instanceof Error ? err.stack : undefined;
242
242
  this._logger.error("빌드 중 예기치 않은 에러", {
243
- error: String(err),
243
+ error: errNs.message(err),
244
244
  });
245
- if (stack != null) {
246
- this._logger.debug(`빌드 예외 스택:\n${stack}`);
247
- }
245
+ this._logger.debug(`빌드 예외 스택:\n${errNs.stack(err)}`);
248
246
  hasUntrackedError.value = true;
249
247
  }
250
248
  }
@@ -246,6 +246,7 @@ export class DevOrchestrator extends BaseOrchestrator implements OrchestratorLif
246
246
  onServerReady: () => this._schedulePrintServers(),
247
247
  }).catch((err: unknown) => {
248
248
  this._logger.error(`[${name}] 서버 런타임 시작 실패:`, errNs.message(err));
249
+ this._logger.debug(`[${name}] 서버 런타임 시작 실패 스택:\n${errNs.stack(err)}`);
249
250
  this._resultCollector.add({
250
251
  name,
251
252
  target: "server",
@@ -52,6 +52,9 @@ export class ServerRuntimeManager {
52
52
  });
53
53
 
54
54
  runtimeWorker.on("error", (errorData) => {
55
+ if (errorData.stack != null) {
56
+ this._logger.debug(`[${params.serverName}] 서버 런타임 에러 스택:\n${errorData.stack}`);
57
+ }
55
58
  params.resultCollector.add({
56
59
  name: params.serverName,
57
60
  target: "server",
@@ -65,6 +68,7 @@ export class ServerRuntimeManager {
65
68
  .start({ mainJsPath: params.mainJsPath, clientPorts: params.clientPorts, env: params.env })
66
69
  .catch((err: unknown) => {
67
70
  this._logger.error(`[${params.serverName}] 서버 런타임 워커 비정상 종료:`, errNs.message(err));
71
+ this._logger.debug(`[${params.serverName}] 서버 런타임 워커 비정상 종료 스택:\n${errNs.stack(err)}`);
68
72
  params.resultCollector.add({
69
73
  name: params.serverName,
70
74
  target: "server",
@@ -51,12 +51,13 @@ export interface TypecheckResult {
51
51
 
52
52
  //#region Utilities
53
53
 
54
- const TARGET_PATH_PATTERN = /^(?:packages|tests)\/([^/]+)/;
54
+ const TARGET_PATH_PATTERN = /^[^/]+\/([^/]+)/;
55
55
 
56
56
  /**
57
- * 대상 경로에서 패키지명을 추출한다.
57
+ * 대상 경로에서 패키지명을 추출한다. 워크스페이스 종류(packages/·tests/·plugins/ 등)를 가리지 않는다.
58
58
  * "packages/core-common" → "core-common"
59
59
  * "tests/orm" → "orm"
60
+ * "plugins/sd" → "sd"
60
61
  */
61
62
  function extractTargetPackageNames(targets: string[]): Set<string> {
62
63
  const names = new Set<string>();
@@ -229,11 +230,8 @@ export class TypecheckOrchestrator implements OrchestratorLifecycle<TypecheckRes
229
230
  return result;
230
231
  } catch (err) {
231
232
  const message = errNs.message(err);
232
- const stack = err instanceof Error ? err.stack : undefined;
233
233
  this._logger.error(`[${label}] 엔진 작업 실패: ${message}`);
234
- if (stack != null) {
235
- this._logger.debug(`[${label}] 스택 트레이스:\n${stack}`);
236
- }
234
+ this._logger.debug(`[${label}] 스택 트레이스:\n${errNs.stack(err)}`);
237
235
  return {
238
236
  build: {
239
237
  success: false,
@@ -1,6 +1,9 @@
1
+ import { createLogger } from "@simplysm/core-common";
1
2
  import type { BuildResult, ResultCollector } from "../runtime/ResultCollector";
2
3
  import type { RebuildManager } from "./rebuild-manager";
3
4
 
5
+ const logger = createLogger("sd:cli:watch-events");
6
+
4
7
  /**
5
8
  * worker.on()으로 이벤트를 구독할 수 있는 최소 인터페이스
6
9
  */
@@ -84,7 +87,10 @@ export function setupWatchEvents(
84
87
  });
85
88
 
86
89
  worker.on("error", (data: unknown) => {
87
- const event = data as { message: string };
90
+ const event = data as { message: string; stack?: string };
91
+ if (event.stack != null) {
92
+ logger.debug(`[${name}] 워커 에러 스택:\n${event.stack}`);
93
+ }
88
94
 
89
95
  const buildResult: BuildResult = {
90
96
  name,
@@ -8,6 +8,7 @@ export interface BuildEventData {
8
8
  /** 워커 에러 이벤트 데이터 */
9
9
  export interface ErrorEventData {
10
10
  message: string;
11
+ stack?: string;
11
12
  }
12
13
 
13
14
  /** 워커 서버 준비 완료 이벤트 데이터 */
@@ -12,7 +12,6 @@ import { runInit } from "./commands/init/init";
12
12
  import { runInitClient } from "./commands/init/init-client";
13
13
  import { runPublish } from "./commands/publish/publish-command";
14
14
  import { runReplaceDeps } from "./commands/replace-deps";
15
- import { runReinstall } from "./commands/reinstall";
16
15
  import path from "path";
17
16
  import fs from "fs";
18
17
  import { fileURLToPath } from "url";
@@ -286,14 +285,6 @@ export function createCliParser(argv: string[]): Argv {
286
285
  });
287
286
  },
288
287
  )
289
- .command(
290
- "reinstall",
291
- "Clean reinstall: delete node_modules/lock/dist/.cache then reinstall with build approval",
292
- (cmd) => cmd.version(false).hide("help"),
293
- async () => {
294
- await runReinstall();
295
- },
296
- )
297
288
  .command(
298
289
  "init [kind]",
299
290
  "Bootstrap a new SI workspace via interactive prompts (kind=client: add a client package to an existing workspace)",