@simplysm/sd-cli 14.0.8 → 14.0.10

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 (254) 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.map +1 -1
  9. package/dist/capacitor/capacitor.js +41 -41
  10. package/dist/capacitor/capacitor.js.map +1 -1
  11. package/dist/commands/build.d.ts.map +1 -1
  12. package/dist/commands/build.js.map +1 -1
  13. package/dist/commands/check.d.ts.map +1 -1
  14. package/dist/commands/check.js.map +1 -1
  15. package/dist/commands/dev.d.ts.map +1 -1
  16. package/dist/commands/dev.js.map +1 -1
  17. package/dist/commands/lint.d.ts.map +1 -1
  18. package/dist/commands/lint.js.map +1 -1
  19. package/dist/commands/publish.d.ts.map +1 -1
  20. package/dist/commands/publish.js.map +1 -1
  21. package/dist/commands/replace-deps.d.ts.map +1 -1
  22. package/dist/commands/replace-deps.js.map +1 -1
  23. package/dist/commands/typecheck.d.ts.map +1 -1
  24. package/dist/commands/typecheck.js +12 -12
  25. package/dist/commands/typecheck.js.map +1 -1
  26. package/dist/commands/watch.d.ts.map +1 -1
  27. package/dist/commands/watch.js.map +1 -1
  28. package/dist/electron/electron.d.ts.map +1 -1
  29. package/dist/electron/electron.js +26 -27
  30. package/dist/electron/electron.js.map +1 -1
  31. package/dist/engines/BaseEngine.d.ts +1 -5
  32. package/dist/engines/BaseEngine.d.ts.map +1 -1
  33. package/dist/engines/BaseEngine.js +7 -16
  34. package/dist/engines/BaseEngine.js.map +1 -1
  35. package/dist/engines/NgtscEngine.d.ts.map +1 -1
  36. package/dist/engines/NgtscEngine.js +10 -11
  37. package/dist/engines/NgtscEngine.js.map +1 -1
  38. package/dist/engines/ServerEsbuildEngine.d.ts.map +1 -1
  39. package/dist/engines/ServerEsbuildEngine.js +10 -11
  40. package/dist/engines/ServerEsbuildEngine.js.map +1 -1
  41. package/dist/engines/TscEngine.d.ts.map +1 -1
  42. package/dist/engines/TscEngine.js +10 -11
  43. package/dist/engines/TscEngine.js.map +1 -1
  44. package/dist/engines/ViteEngine.d.ts.map +1 -1
  45. package/dist/engines/ViteEngine.js +3 -13
  46. package/dist/engines/ViteEngine.js.map +1 -1
  47. package/dist/engines/index.d.ts.map +1 -1
  48. package/dist/engines/index.js.map +1 -1
  49. package/dist/engines/types.d.ts +3 -6
  50. package/dist/engines/types.d.ts.map +1 -1
  51. package/dist/engines/types.js.map +1 -1
  52. package/dist/index.d.ts.map +1 -1
  53. package/dist/index.js.map +1 -1
  54. package/dist/infra/ResultCollector.d.ts +1 -1
  55. package/dist/infra/ResultCollector.d.ts.map +1 -1
  56. package/dist/infra/ResultCollector.js.map +1 -1
  57. package/dist/infra/SignalHandler.d.ts.map +1 -1
  58. package/dist/infra/SignalHandler.js.map +1 -1
  59. package/dist/infra/WorkerManager.d.ts.map +1 -1
  60. package/dist/infra/WorkerManager.js.map +1 -1
  61. package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
  62. package/dist/orchestrators/BuildOrchestrator.js +30 -61
  63. package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
  64. package/dist/orchestrators/DevWatchOrchestrator.d.ts +2 -0
  65. package/dist/orchestrators/DevWatchOrchestrator.d.ts.map +1 -1
  66. package/dist/orchestrators/DevWatchOrchestrator.js +40 -44
  67. package/dist/orchestrators/DevWatchOrchestrator.js.map +1 -1
  68. package/dist/sd-cli-entry.d.ts.map +1 -1
  69. package/dist/sd-cli-entry.js +2 -13
  70. package/dist/sd-cli-entry.js.map +1 -1
  71. package/dist/sd-cli.d.ts.map +1 -1
  72. package/dist/sd-cli.js.map +1 -1
  73. package/dist/sd-config.types.d.ts.map +1 -1
  74. package/dist/sd-config.types.js.map +1 -1
  75. package/dist/utils/SdCliReporter.d.ts +18 -0
  76. package/dist/utils/SdCliReporter.d.ts.map +1 -0
  77. package/dist/utils/SdCliReporter.js +144 -0
  78. package/dist/utils/SdCliReporter.js.map +1 -0
  79. package/dist/utils/angular-build.d.ts.map +1 -1
  80. package/dist/utils/angular-build.js.map +1 -1
  81. package/dist/utils/angular-compiler.d.ts.map +1 -1
  82. package/dist/utils/angular-compiler.js +11 -4
  83. package/dist/utils/angular-compiler.js.map +1 -1
  84. package/dist/utils/build-env.d.ts.map +1 -1
  85. package/dist/utils/build-env.js +2 -1
  86. package/dist/utils/build-env.js.map +1 -1
  87. package/dist/utils/concurrency.d.ts.map +1 -1
  88. package/dist/utils/concurrency.js.map +1 -1
  89. package/dist/utils/copy-public.d.ts.map +1 -1
  90. package/dist/utils/copy-public.js +21 -21
  91. package/dist/utils/copy-public.js.map +1 -1
  92. package/dist/utils/copy-src.d.ts.map +1 -1
  93. package/dist/utils/copy-src.js +12 -12
  94. package/dist/utils/copy-src.js.map +1 -1
  95. package/dist/utils/diagnostic-utils.d.ts.map +1 -1
  96. package/dist/utils/diagnostic-utils.js +3 -2
  97. package/dist/utils/diagnostic-utils.js.map +1 -1
  98. package/dist/utils/engine-stop.d.ts.map +1 -1
  99. package/dist/utils/engine-stop.js.map +1 -1
  100. package/dist/utils/esbuild-config.d.ts.map +1 -1
  101. package/dist/utils/esbuild-config.js +2 -0
  102. package/dist/utils/esbuild-config.js.map +1 -1
  103. package/dist/utils/generate-pwa-icons.d.ts.map +1 -1
  104. package/dist/utils/generate-pwa-icons.js.map +1 -1
  105. package/dist/utils/hmr-candidates.d.ts.map +1 -1
  106. package/dist/utils/hmr-candidates.js.map +1 -1
  107. package/dist/utils/lint-utils.d.ts.map +1 -1
  108. package/dist/utils/lint-utils.js.map +1 -1
  109. package/dist/utils/lint-with-program.d.ts.map +1 -1
  110. package/dist/utils/lint-with-program.js +7 -3
  111. package/dist/utils/lint-with-program.js.map +1 -1
  112. package/dist/utils/ngtsc-build-core.d.ts +2 -10
  113. package/dist/utils/ngtsc-build-core.d.ts.map +1 -1
  114. package/dist/utils/ngtsc-build-core.js +16 -15
  115. package/dist/utils/ngtsc-build-core.js.map +1 -1
  116. package/dist/utils/orchestrator-utils.d.ts.map +1 -1
  117. package/dist/utils/orchestrator-utils.js.map +1 -1
  118. package/dist/utils/output-path-rewriter.d.ts.map +1 -1
  119. package/dist/utils/output-path-rewriter.js +7 -7
  120. package/dist/utils/output-path-rewriter.js.map +1 -1
  121. package/dist/utils/output-utils.d.ts.map +1 -1
  122. package/dist/utils/output-utils.js +1 -1
  123. package/dist/utils/output-utils.js.map +1 -1
  124. package/dist/utils/package-utils.d.ts +4 -0
  125. package/dist/utils/package-utils.d.ts.map +1 -1
  126. package/dist/utils/package-utils.js +34 -13
  127. package/dist/utils/package-utils.js.map +1 -1
  128. package/dist/utils/rebuild-manager.d.ts +1 -1
  129. package/dist/utils/rebuild-manager.d.ts.map +1 -1
  130. package/dist/utils/rebuild-manager.js +3 -1
  131. package/dist/utils/rebuild-manager.js.map +1 -1
  132. package/dist/utils/replace-deps.d.ts.map +1 -1
  133. package/dist/utils/replace-deps.js +10 -10
  134. package/dist/utils/replace-deps.js.map +1 -1
  135. package/dist/utils/scss-compiler.d.ts.map +1 -1
  136. package/dist/utils/scss-compiler.js.map +1 -1
  137. package/dist/utils/sd-config.d.ts.map +1 -1
  138. package/dist/utils/sd-config.js +2 -3
  139. package/dist/utils/sd-config.js.map +1 -1
  140. package/dist/utils/tsc-build.d.ts +3 -1
  141. package/dist/utils/tsc-build.d.ts.map +1 -1
  142. package/dist/utils/tsc-build.js +7 -4
  143. package/dist/utils/tsc-build.js.map +1 -1
  144. package/dist/utils/tsconfig.d.ts.map +1 -1
  145. package/dist/utils/tsconfig.js.map +1 -1
  146. package/dist/utils/typecheck-non-package.d.ts.map +1 -1
  147. package/dist/utils/typecheck-non-package.js +10 -5
  148. package/dist/utils/typecheck-non-package.js.map +1 -1
  149. package/dist/utils/typecheck-serialization.d.ts.map +1 -1
  150. package/dist/utils/typecheck-serialization.js.map +1 -1
  151. package/dist/utils/vite-config.d.ts.map +1 -1
  152. package/dist/utils/vite-config.js +2 -1
  153. package/dist/utils/vite-config.js.map +1 -1
  154. package/dist/utils/vite-scope-watch-plugin.d.ts.map +1 -1
  155. package/dist/utils/vite-scope-watch-plugin.js.map +1 -1
  156. package/dist/utils/worker-events.d.ts +1 -1
  157. package/dist/utils/worker-events.d.ts.map +1 -1
  158. package/dist/utils/worker-events.js +1 -0
  159. package/dist/utils/worker-events.js.map +1 -1
  160. package/dist/utils/worker-utils.d.ts +1 -1
  161. package/dist/utils/worker-utils.d.ts.map +1 -1
  162. package/dist/utils/worker-utils.js +3 -1
  163. package/dist/utils/worker-utils.js.map +1 -1
  164. package/dist/vitest-plugin.d.ts.map +1 -1
  165. package/dist/vitest-plugin.js.map +1 -1
  166. package/dist/workers/client.worker.d.ts.map +1 -1
  167. package/dist/workers/client.worker.js +4 -0
  168. package/dist/workers/client.worker.js.map +1 -1
  169. package/dist/workers/library-build.worker.d.ts +2 -10
  170. package/dist/workers/library-build.worker.d.ts.map +1 -1
  171. package/dist/workers/library-build.worker.js +38 -14
  172. package/dist/workers/library-build.worker.js.map +1 -1
  173. package/dist/workers/lint.worker.d.ts.map +1 -1
  174. package/dist/workers/lint.worker.js.map +1 -1
  175. package/dist/workers/ngtsc-build.worker.d.ts.map +1 -1
  176. package/dist/workers/ngtsc-build.worker.js +40 -14
  177. package/dist/workers/ngtsc-build.worker.js.map +1 -1
  178. package/dist/workers/server-build.worker.d.ts +2 -10
  179. package/dist/workers/server-build.worker.d.ts.map +1 -1
  180. package/dist/workers/server-build.worker.js +28 -19
  181. package/dist/workers/server-build.worker.js.map +1 -1
  182. package/dist/workers/server-runtime.worker.d.ts.map +1 -1
  183. package/dist/workers/server-runtime.worker.js.map +1 -1
  184. package/package.json +4 -4
  185. package/src/angular/vite-angular-plugin.ts +18 -9
  186. package/src/capacitor/capacitor.ts +41 -41
  187. package/src/commands/typecheck.ts +12 -12
  188. package/src/electron/electron.ts +26 -27
  189. package/src/engines/BaseEngine.ts +8 -19
  190. package/src/engines/NgtscEngine.ts +11 -11
  191. package/src/engines/ServerEsbuildEngine.ts +11 -11
  192. package/src/engines/TscEngine.ts +11 -11
  193. package/src/engines/ViteEngine.ts +3 -14
  194. package/src/engines/types.ts +3 -6
  195. package/src/infra/ResultCollector.ts +1 -1
  196. package/src/orchestrators/BuildOrchestrator.ts +31 -62
  197. package/src/orchestrators/DevWatchOrchestrator.ts +41 -44
  198. package/src/sd-cli-entry.ts +2 -12
  199. package/src/utils/SdCliReporter.ts +177 -0
  200. package/src/utils/angular-compiler.ts +11 -4
  201. package/src/utils/build-env.ts +2 -1
  202. package/src/utils/copy-public.ts +21 -21
  203. package/src/utils/copy-src.ts +12 -12
  204. package/src/utils/diagnostic-utils.ts +3 -2
  205. package/src/utils/esbuild-config.ts +2 -0
  206. package/src/utils/lint-with-program.ts +7 -3
  207. package/src/utils/ngtsc-build-core.ts +18 -18
  208. package/src/utils/output-path-rewriter.ts +7 -7
  209. package/src/utils/output-utils.ts +1 -1
  210. package/src/utils/package-utils.ts +37 -13
  211. package/src/utils/rebuild-manager.ts +4 -2
  212. package/src/utils/replace-deps.ts +10 -10
  213. package/src/utils/sd-config.ts +2 -3
  214. package/src/utils/tsc-build.ts +9 -4
  215. package/src/utils/typecheck-non-package.ts +10 -5
  216. package/src/utils/vite-config.ts +2 -1
  217. package/src/utils/worker-events.ts +2 -1
  218. package/src/utils/worker-utils.ts +3 -1
  219. package/src/workers/client.worker.ts +4 -0
  220. package/src/workers/library-build.worker.ts +48 -18
  221. package/src/workers/ngtsc-build.worker.ts +48 -13
  222. package/src/workers/server-build.worker.ts +30 -23
  223. package/tests/angular/vite-angular-plugin-hmr-fallback.spec.ts +11 -7
  224. package/tests/angular/vite-angular-plugin-lint.spec.ts +6 -1
  225. package/tests/capacitor/capacitor-build.spec.ts +5 -0
  226. package/tests/capacitor/capacitor-icon.spec.ts +5 -0
  227. package/tests/capacitor/capacitor-init.spec.ts +5 -0
  228. package/tests/capacitor/capacitor-run.spec.ts +5 -0
  229. package/tests/capacitor/capacitor-workspace.spec.ts +5 -0
  230. package/tests/commands/typecheck.spec.ts +20 -31
  231. package/tests/electron/electron.spec.ts +5 -0
  232. package/tests/engines/base-engine.spec.ts +15 -21
  233. package/tests/engines/engine-lint-integration.spec.ts +5 -10
  234. package/tests/engines/ngtsc-engine.spec.ts +27 -41
  235. package/tests/engines/server-esbuild-engine.spec.ts +18 -29
  236. package/tests/engines/tsc-engine.spec.ts +14 -23
  237. package/tests/engines/vite-engine.spec.ts +10 -15
  238. package/tests/infra/result-collector.spec.ts +2 -2
  239. package/tests/orchestrators/build-orchestrator.spec.ts +19 -29
  240. package/tests/orchestrators/dev-watch-orchestrator.spec.ts +110 -95
  241. package/tests/utils/copy-src.spec.ts +25 -19
  242. package/tests/utils/diagnostic-utils.spec.ts +72 -0
  243. package/tests/utils/ngtsc-build-core-angular-compiler.spec.ts +2 -3
  244. package/tests/utils/output-path-rewriter.spec.ts +7 -6
  245. package/tests/utils/output-utils.spec.ts +5 -5
  246. package/tests/utils/rebuild-manager.spec.ts +1 -1
  247. package/tests/utils/sd-config.spec.ts +4 -0
  248. package/tests/utils/tsc-build.spec.ts +23 -5
  249. package/tests/workers/library-build-worker.spec.ts +113 -20
  250. package/tests/workers/ngtsc-build-lint.spec.ts +3 -6
  251. package/tests/workers/ngtsc-build-worker.spec.ts +17 -19
  252. package/tests/workers/server-build-lint.spec.ts +4 -1
  253. package/tests/workers/server-build-worker.spec.ts +19 -22
  254. package/tests/angular/migration-cleanup.spec.ts +0 -59
@@ -104,8 +104,10 @@ async function startWatch(info: ClientBuildInfo): Promise<ClientBuildResult> {
104
104
  pwa: info.pwa,
105
105
  });
106
106
 
107
+ logger.debug(`[${info.name}] Vite server 생성 시작`);
107
108
  viteServer = await createServer(viteConfig);
108
109
  await viteServer.listen();
110
+ logger.debug(`[${info.name}] Vite server listen 완료`);
109
111
 
110
112
  // 실제 포트 감지
111
113
  const address = viteServer.httpServer?.address();
@@ -139,11 +141,13 @@ async function startWatch(info: ClientBuildInfo): Promise<ClientBuildResult> {
139
141
  * dev server 중지. Vite server를 정리한다.
140
142
  */
141
143
  async function stopWatch(): Promise<void> {
144
+ logger.debug("Vite server 정리 시작");
142
145
  const serverToClose = viteServer;
143
146
  viteServer = undefined;
144
147
  if (serverToClose != null) {
145
148
  await serverToClose.close();
146
149
  }
150
+ logger.debug("Vite server 정리 완료");
147
151
  }
148
152
 
149
153
  /**
@@ -1,5 +1,5 @@
1
- import path from "path";
2
- import { createWorker, FsWatcher } from "@simplysm/core-node";
1
+ import type ts from "typescript";
2
+ import { createWorker, FsWatcher, pathx } from "@simplysm/core-node";
3
3
  import { err as errNs } from "@simplysm/core-common";
4
4
  import { consola } from "consola";
5
5
  import type { SdBuildPackageConfig } from "../sd-config.types";
@@ -26,14 +26,12 @@ export interface LibraryBuildInfo {
26
26
  }
27
27
 
28
28
  export interface LibraryBuildResult {
29
- js: { success: boolean; errors?: string[]; warnings?: string[] };
30
- dts: { success: boolean; errors?: string[]; diagnostics: SerializedDiagnostic[] };
29
+ build: { success: boolean; errors?: string[]; warnings?: string[]; diagnostics: SerializedDiagnostic[] };
31
30
  lint?: LintWithProgramResult;
32
31
  }
33
32
 
34
33
  export interface CombinedBuildEvent {
35
- js: { success: boolean; errors?: string[]; warnings?: string[] };
36
- dts: { success: boolean; errors?: string[] };
34
+ build: { success: boolean; errors?: string[]; warnings?: string[] };
37
35
  lint?: LintWithProgramResult;
38
36
  }
39
37
 
@@ -54,6 +52,7 @@ let fsWatcher: FsWatcher | undefined;
54
52
  async function cleanup(): Promise<void> {
55
53
  const watcherToClose = fsWatcher;
56
54
  fsWatcher = undefined;
55
+ lastSourceFilePaths = undefined;
57
56
  await watcherToClose?.close();
58
57
  }
59
58
 
@@ -70,28 +69,27 @@ async function build(info: LibraryBuildInfo): Promise<LibraryBuildResult> {
70
69
  cwd: info.cwd,
71
70
  output: info.output,
72
71
  env: info.output.env,
72
+ includeTests: info.output.includeTests,
73
73
  });
74
74
  logger.debug(`[${info.name}] library worker build 완료 (success: ${tscResult.success})`);
75
75
 
76
76
  // Run lint if enabled and program is available
77
77
  let lint: LintWithProgramResult | undefined;
78
78
  if (info.output.lint === true && tscResult.program != null) {
79
+ logger.debug(`[${info.name}] lint 시작`);
79
80
  const lintRunner = new LintWithProgramRunner({
80
81
  cwd: info.cwd,
81
82
  pkgName: info.name,
82
83
  });
83
84
  lint = await lintRunner.lint({ program: tscResult.program });
85
+ logger.debug(`[${info.name}] lint 완료`);
84
86
  }
85
87
 
86
88
  return {
87
- js: {
89
+ build: {
88
90
  success: tscResult.success,
89
91
  errors: tscResult.errors,
90
92
  warnings: undefined,
91
- },
92
- dts: {
93
- success: tscResult.success,
94
- errors: tscResult.errors,
95
93
  diagnostics: tscResult.diagnostics,
96
94
  },
97
95
  lint,
@@ -107,20 +105,36 @@ const guardStartWatch = createOnceGuard("startWatch");
107
105
  // Mutable state for watch mode
108
106
  let watchInfo: LibraryBuildInfo | undefined;
109
107
  let watchLintRunner: LintWithProgramRunner | undefined;
108
+ let lastSourceFilePaths: Set<string> | undefined;
109
+
110
+ function extractSourceFilePaths(program: ts.Program | undefined): Set<string> | undefined {
111
+ if (program == null) return undefined;
112
+ const paths = new Set<string>();
113
+ for (const sf of program.getSourceFiles()) {
114
+ paths.add(pathx.posix(sf.fileName));
115
+ }
116
+ return paths;
117
+ }
110
118
 
111
119
  async function rebuildAll(): Promise<CombinedBuildEvent> {
112
120
  const info = watchInfo!;
121
+ logger.debug(`[${info.name}] rebuildAll 시작`);
113
122
 
114
123
  const tscResult = runTscPackageBuild({
115
124
  pkgDir: info.pkgDir,
116
125
  cwd: info.cwd,
117
126
  output: info.output,
118
127
  env: info.output.env,
128
+ includeTests: info.output.includeTests,
119
129
  });
120
130
 
131
+ // Update source file paths for dependency filtering
132
+ lastSourceFilePaths = extractSourceFilePaths(tscResult.program) ?? lastSourceFilePaths;
133
+
121
134
  // Run lint if enabled and program is available
122
135
  let lint: LintWithProgramResult | undefined;
123
136
  if (info.output.lint === true && tscResult.program != null) {
137
+ logger.debug(`[${info.name}] lint 시작`);
124
138
  if (watchLintRunner == null) {
125
139
  watchLintRunner = new LintWithProgramRunner({
126
140
  cwd: info.cwd,
@@ -131,11 +145,12 @@ async function rebuildAll(): Promise<CombinedBuildEvent> {
131
145
  program: tscResult.program,
132
146
  affectedFiles: tscResult.affectedFiles,
133
147
  });
148
+ logger.debug(`[${info.name}] lint 완료`);
134
149
  }
135
150
 
151
+ logger.debug(`[${info.name}] rebuildAll 완료`);
136
152
  return {
137
- js: { success: tscResult.success, errors: tscResult.errors },
138
- dts: { success: tscResult.success, errors: tscResult.errors },
153
+ build: { success: tscResult.success, errors: tscResult.errors },
139
154
  lint,
140
155
  };
141
156
  }
@@ -153,18 +168,33 @@ async function startWatch(info: LibraryBuildInfo): Promise<void> {
153
168
  const { workspaceDeps, replaceDeps } = collectDeps(info.pkgDir, info.cwd, info.replaceDeps);
154
169
 
155
170
  // Start FsWatcher — own src/ + workspace deps' src/ + replaceDeps dist/
171
+ logger.debug(`[${info.name}] FsWatcher 시작`);
156
172
  const watchPaths = [
157
- path.join(info.pkgDir, "src", "**", "*.ts"),
158
- ...workspaceDeps.map((d) => path.join(info.cwd, "packages", d, "src", "**", "*.ts")),
173
+ pathx.posixResolve(info.pkgDir, "src", "**", "*.ts"),
174
+ ...workspaceDeps.map((d) => pathx.posixResolve(info.cwd, "packages", d, "src", "**", "*.ts")),
159
175
  ...replaceDeps.flatMap((pkg) => [
160
- path.join(info.cwd, "node_modules", ...pkg.split("/"), "dist", "**", "*.{js,mjs,cjs}"),
161
- path.join(info.pkgDir, "node_modules", ...pkg.split("/"), "dist", "**", "*.{js,mjs,cjs}"),
176
+ pathx.posixResolve(info.cwd, "node_modules", ...pkg.split("/"), "dist", "**", "*.{js,mjs,cjs}"),
177
+ pathx.posixResolve(info.pkgDir, "node_modules", ...pkg.split("/"), "dist", "**", "*.{js,mjs,cjs}"),
162
178
  ]),
163
179
  ];
164
180
  fsWatcher = await FsWatcher.watch(watchPaths);
165
181
 
166
- fsWatcher.onChange({ delay: 300 }, async () => {
182
+ fsWatcher.onChange({ delay: 300 }, async (changes) => {
167
183
  try {
184
+ const hasFileAddOrRemove = changes.some(
185
+ (c) => c.event === "add" || c.event === "unlink",
186
+ );
187
+
188
+ if (!hasFileAddOrRemove && lastSourceFilePaths != null) {
189
+ const hasRelevantChange = changes.some((c) =>
190
+ lastSourceFilePaths!.has(c.path),
191
+ );
192
+ if (!hasRelevantChange) {
193
+ logger.debug("변경된 파일이 빌드에 포함되지 않아 리빌드 건너뜀");
194
+ return;
195
+ }
196
+ }
197
+
168
198
  sender.send("buildStart", {});
169
199
  const result = await rebuildAll();
170
200
  sender.send("build", result);
@@ -1,6 +1,6 @@
1
1
  import path from "path";
2
2
  import ts from "typescript";
3
- import { createWorker, FsWatcher } from "@simplysm/core-node";
3
+ import { createWorker, FsWatcher, pathx } from "@simplysm/core-node";
4
4
  import { err as errNs } from "@simplysm/core-common";
5
5
  import { consola } from "consola";
6
6
  import { registerCleanupHandlers, createOnceGuard, applyDebugLevel } from "../utils/worker-utils";
@@ -22,6 +22,7 @@ import { LintWithProgramRunner, type LintWithProgramResult } from "../utils/lint
22
22
  import {
23
23
  parseTsconfig,
24
24
  getPackageSourceFiles,
25
+ getPackageFiles,
25
26
  getCompilerOptionsForEnv,
26
27
  } from "../utils/tsconfig";
27
28
  import { AngularCompiler, AngularSourceFileCache } from "../utils/angular-compiler";
@@ -50,6 +51,7 @@ let fsWatcher: FsWatcher | undefined;
50
51
  async function cleanup(): Promise<void> {
51
52
  const watcherToClose = fsWatcher;
52
53
  fsWatcher = undefined;
54
+ lastSourceFilePaths = undefined;
53
55
 
54
56
  if (watcherToClose != null) {
55
57
  await watcherToClose.close();
@@ -65,15 +67,17 @@ registerCleanupHandlers(cleanup, logger);
65
67
  async function build(info: NgtscBuildInfo): Promise<NgtscBuildResult> {
66
68
  logger.debug(`[${info.name}] ngtsc worker build 시작 (pkgDir: ${info.pkgDir})`);
67
69
  const { program, ...result } = await runNgtscBuild({ ...info, env: info.output.env });
68
- logger.debug(`[${info.name}] ngtsc worker build 완료 (dts.success: ${result.dts.success})`);
70
+ logger.debug(`[${info.name}] ngtsc worker build 완료 (build.success: ${result.build.success})`);
69
71
 
70
72
  // Run lint if enabled and program is available
71
73
  if (info.output.lint === true && program != null) {
74
+ logger.debug(`[${info.name}] lint 시작`);
72
75
  const lintRunner = new LintWithProgramRunner({
73
76
  cwd: info.cwd,
74
77
  pkgName: info.name,
75
78
  });
76
79
  result.lint = await lintRunner.lint({ program });
80
+ logger.debug(`[${info.name}] lint 완료`);
77
81
  }
78
82
 
79
83
  return result;
@@ -88,8 +92,17 @@ const guardStartWatch = createOnceGuard("startWatch");
88
92
  let watchInfo: NgtscBuildInfo | undefined;
89
93
  let currentScssDependencies: Map<string, Set<string>> | undefined;
90
94
  let watchLintRunner: LintWithProgramRunner | undefined;
95
+ let lastSourceFilePaths: Set<string> | undefined;
91
96
  const sideEffectScssRegistry = new Map<string, SideEffectScssEntry>();
92
97
 
98
+ function extractSourceFilePaths(program: ReturnType<AngularCompiler["getTsProgram"]>): Set<string> {
99
+ const paths = new Set<string>();
100
+ for (const sf of program.getSourceFiles()) {
101
+ paths.add(pathx.posix(sf.fileName));
102
+ }
103
+ return paths;
104
+ }
105
+
93
106
  /**
94
107
  * Perform a watch build (initial or incremental) using AngularCompiler.
95
108
  * Returns NgtscCombinedBuildEvent for sending to the engine.
@@ -105,8 +118,9 @@ async function performWatchBuild(
105
118
  affectedFileNames?: ReadonlySet<string>,
106
119
  hasScssChanges = true,
107
120
  ): Promise<NgtscCombinedBuildEvent> {
121
+ logger.debug(`[${info.name}] performWatchBuild 시작`);
108
122
  const pkgSrcDir = path.join(info.pkgDir, "src");
109
- const normalizedSrcDir = pkgSrcDir.replace(/\\/g, "/");
123
+ const normalizedSrcDir = pathx.posix(pkgSrcDir);
110
124
 
111
125
  // Collect diagnostics — workspace scope (no package-level filtering)
112
126
  const allDiagnostics = [...compiler.collectDiagnostics()].filter(
@@ -124,7 +138,7 @@ async function performWatchBuild(
124
138
  const loadPaths = buildScssLoadPaths(info);
125
139
  const emitResults = compiler.emitAffectedFiles({
126
140
  sourceFilter: (fileName: string) =>
127
- fileName.replace(/\\/g, "/").startsWith(normalizedSrcDir + "/"),
141
+ pathx.posix(fileName).startsWith(normalizedSrcDir + "/"),
128
142
  });
129
143
  writeEmitResults(emitResults, info.pkgDir, {
130
144
  loadPaths,
@@ -146,6 +160,7 @@ async function performWatchBuild(
146
160
  // Run lint if enabled
147
161
  let lint: LintWithProgramResult | undefined;
148
162
  if (info.output.lint === true) {
163
+ logger.debug(`[${info.name}] lint 시작`);
149
164
  if (watchLintRunner == null) {
150
165
  watchLintRunner = new LintWithProgramRunner({
151
166
  cwd: info.cwd,
@@ -156,11 +171,12 @@ async function performWatchBuild(
156
171
  program: compiler.getTsProgram(),
157
172
  affectedFiles: affectedFileNames,
158
173
  });
174
+ logger.debug(`[${info.name}] lint 완료`);
159
175
  }
160
176
 
177
+ logger.debug(`[${info.name}] performWatchBuild 완료`);
161
178
  return {
162
- js: { success: true },
163
- dts: {
179
+ build: {
164
180
  success: errorCount === 0 && scssErrors.length === 0 && globalScssErrors.length === 0,
165
181
  errors: allErrors.length > 0 ? allErrors : undefined,
166
182
  },
@@ -175,17 +191,16 @@ async function startWatch(info: NgtscBuildInfo): Promise<void> {
175
191
  try {
176
192
  // Parse tsconfig and prepare compiler options
177
193
  const parsedConfig = parseTsconfig(watchInfo.pkgDir);
178
- const sourceFiles = getPackageSourceFiles(watchInfo.pkgDir, parsedConfig);
194
+ const sourceFiles = watchInfo.output.includeTests === true
195
+ ? getPackageFiles(watchInfo.pkgDir, parsedConfig)
196
+ : getPackageSourceFiles(watchInfo.pkgDir, parsedConfig);
179
197
  const baseOptions =
180
198
  watchInfo.env != null
181
199
  ? getCompilerOptionsForEnv(parsedConfig.options, watchInfo.env, watchInfo.pkgDir)
182
200
  : parsedConfig.options;
183
201
  const compilerOptions = buildCompilerOptions(baseOptions, watchInfo.pkgDir, watchInfo.output);
184
202
 
185
- // Read angularCompilerOptions from root tsconfig
186
- const rootTsconfigPath = path.join(watchInfo.cwd, "tsconfig.json");
187
- const rootRawConfig = ts.readConfigFile(rootTsconfigPath, ts.sys.readFile);
188
- const angularOptions = rootRawConfig.config?.angularCompilerOptions ?? {};
203
+ const angularOptions = (parsedConfig.raw?.angularCompilerOptions ?? {}) as Record<string, unknown>;
189
204
 
190
205
  // SCSS closure variables
191
206
  const scssErrors: string[] = [];
@@ -204,6 +219,7 @@ async function startWatch(info: NgtscBuildInfo): Promise<void> {
204
219
  });
205
220
  // Initial build
206
221
  await compiler.initialize();
222
+ lastSourceFilePaths = extractSourceFilePaths(compiler.getTsProgram());
207
223
  const initialResult = await performWatchBuild(watchInfo, compiler, scssDependencies, scssErrors);
208
224
  sender.send("build", initialResult);
209
225
 
@@ -215,6 +231,7 @@ async function startWatch(info: NgtscBuildInfo): Promise<void> {
215
231
  );
216
232
 
217
233
  // Start FsWatcher
234
+ logger.debug(`[${watchInfo.name}] FsWatcher 시작`);
218
235
  const watchPaths = [
219
236
  path.join(watchInfo.pkgDir, "src", "**", "*.{ts,scss,css}"),
220
237
  path.join(watchInfo.pkgDir, "scss", "**", "*.{scss,css}"),
@@ -234,7 +251,9 @@ async function startWatch(info: NgtscBuildInfo): Promise<void> {
234
251
 
235
252
  fsWatcher.onChange({ delay: 300 }, async (changedFiles) => {
236
253
  try {
237
- sender.send("buildStart", {});
254
+ const hasFileAddOrRemove = changedFiles.some(
255
+ (c) => c.event === "add" || c.event === "unlink",
256
+ );
238
257
 
239
258
  // Collect modified files (all changed + SCSS dependency reverse-lookup)
240
259
  const modifiedFiles = new Set<string>();
@@ -254,6 +273,19 @@ async function startWatch(info: NgtscBuildInfo): Promise<void> {
254
273
  }
255
274
  }
256
275
 
276
+ // Dependency filter: skip rebuild if no relevant changes
277
+ if (!hasFileAddOrRemove && lastSourceFilePaths != null) {
278
+ const hasRelevantChange = [...modifiedFiles].some((p) =>
279
+ lastSourceFilePaths!.has(p),
280
+ );
281
+ if (!hasRelevantChange) {
282
+ logger.debug("변경된 파일이 빌드에 포함되지 않아 리빌드 건너뜀");
283
+ return;
284
+ }
285
+ }
286
+
287
+ sender.send("buildStart", {});
288
+
257
289
  // Clear SCSS errors for fresh rebuild
258
290
  scssErrors.length = 0;
259
291
  scssDependencies.clear();
@@ -261,10 +293,13 @@ async function startWatch(info: NgtscBuildInfo): Promise<void> {
261
293
  // Incremental rebuild via AngularCompiler.update()
262
294
  const updateResult = await compiler.update(modifiedFiles);
263
295
 
296
+ // Update source file paths after rebuild
297
+ lastSourceFilePaths = extractSourceFilePaths(compiler.getTsProgram());
298
+
264
299
  // Convert affected ts.SourceFile set to file name strings for incremental lint
265
300
  const affectedFileNames = new Set<string>();
266
301
  for (const sf of updateResult.affectedFiles) {
267
- affectedFileNames.add(sf.fileName.replace(/\\/g, "/"));
302
+ affectedFileNames.add(pathx.posix(sf.fileName));
268
303
  }
269
304
 
270
305
  const hasScssChanges = changedFiles.some(
@@ -69,8 +69,7 @@ export interface ServerWatchInfo {
69
69
  * Server build result (aligned with LibraryBuildResult + mainJsPath)
70
70
  */
71
71
  export interface ServerBuildResult {
72
- js: { success: boolean; errors?: string[]; warnings?: string[] };
73
- dts: { success: boolean; errors?: string[]; diagnostics: SerializedDiagnostic[] };
72
+ build: { success: boolean; errors?: string[]; warnings?: string[]; diagnostics: SerializedDiagnostic[] };
74
73
  lint?: LintWithProgramResult;
75
74
  mainJsPath: string;
76
75
  }
@@ -79,8 +78,7 @@ export interface ServerBuildResult {
79
78
  * Combined build event for watch mode
80
79
  */
81
80
  export interface ServerCombinedBuildEvent {
82
- js: { success: boolean; errors?: string[]; warnings?: string[] };
83
- dts: { success: boolean; errors?: string[] };
81
+ build: { success: boolean; errors?: string[]; warnings?: string[] };
84
82
  lint?: LintWithProgramResult;
85
83
  mainJsPath: string;
86
84
  }
@@ -324,7 +322,7 @@ registerCleanupHandlers(cleanup, logger);
324
322
  * One-time build (production)
325
323
  */
326
324
  async function build(info: ServerBuildInfo): Promise<ServerBuildResult> {
327
- const mainJsPath = path.join(info.pkgDir, "dist", "main.js");
325
+ const mainJsPath = pathx.posixResolve(info.pkgDir, "dist", "main.js");
328
326
  logger.debug(`[${info.name}] server worker build 시작 (js: ${info.output.js}, dts: ${info.output.dts})`);
329
327
 
330
328
  try {
@@ -369,6 +367,7 @@ async function build(info: ServerBuildInfo): Promise<ServerBuildResult> {
369
367
  output: { js: false, dts: info.output.dts },
370
368
  parsedConfig,
371
369
  env: info.output.env,
370
+ includeTests: info.output.includeTests,
372
371
  });
373
372
 
374
373
  const jsResult = esbuildPromise
@@ -378,11 +377,13 @@ async function build(info: ServerBuildInfo): Promise<ServerBuildResult> {
378
377
  // Run lint if enabled and program is available
379
378
  let lint: LintWithProgramResult | undefined;
380
379
  if (info.output.lint === true && tscResult.program != null) {
380
+ logger.debug(`[${info.name}] lint 시작`);
381
381
  const lintRunner = new LintWithProgramRunner({
382
382
  cwd: info.cwd,
383
383
  pkgName: info.name,
384
384
  });
385
385
  lint = await lintRunner.lint({ program: tscResult.program });
386
+ logger.debug(`[${info.name}] lint 완료`);
386
387
  }
387
388
 
388
389
  // Generate production artifacts only when JS output is requested
@@ -395,16 +396,13 @@ async function build(info: ServerBuildInfo): Promise<ServerBuildResult> {
395
396
  generateProductionFiles(info, external);
396
397
  }
397
398
 
398
- logger.debug(`[${info.name}] server worker build 완료 (js: ${jsResult.success}, dts: ${tscResult.success})`);
399
+ const allErrors = [...(jsResult.errors ?? []), ...(tscResult.errors ?? [])];
400
+ logger.debug(`[${info.name}] server worker build 완료 (js: ${jsResult.success}, tsc: ${tscResult.success})`);
399
401
  return {
400
- js: {
401
- success: jsResult.success,
402
- errors: jsResult.errors,
402
+ build: {
403
+ success: jsResult.success && tscResult.success,
404
+ errors: allErrors.length > 0 ? allErrors : undefined,
403
405
  warnings: jsResult.warnings,
404
- },
405
- dts: {
406
- success: tscResult.success,
407
- errors: tscResult.errors,
408
406
  diagnostics: tscResult.diagnostics,
409
407
  },
410
408
  lint,
@@ -418,8 +416,7 @@ async function build(info: ServerBuildInfo): Promise<ServerBuildResult> {
418
416
  logger.debug(`[${info.name}] 스택 트레이스:\n${stack}`);
419
417
  }
420
418
  return {
421
- js: { success: false, errors: [message] },
422
- dts: { success: false, errors: [message], diagnostics: [] },
419
+ build: { success: false, errors: [message], diagnostics: [] },
423
420
  mainJsPath,
424
421
  };
425
422
  }
@@ -436,7 +433,8 @@ let watchLintRunner: LintWithProgramRunner | undefined;
436
433
  */
437
434
  async function rebuildAll(): Promise<ServerCombinedBuildEvent> {
438
435
  const info = watchInfo!;
439
- const mainJsPath = path.join(info.pkgDir, "dist", "main.js");
436
+ logger.debug(`[${info.name}] rebuildAll 시작`);
437
+ const mainJsPath = pathx.posixResolve(info.pkgDir, "dist", "main.js");
440
438
  const parsedConfig = parseTsconfig(info.pkgDir);
441
439
 
442
440
  // esbuild rebuild (async)
@@ -468,11 +466,13 @@ async function rebuildAll(): Promise<ServerCombinedBuildEvent> {
468
466
  output: { js: false, dts: info.output.dts },
469
467
  parsedConfig,
470
468
  env: info.output.env,
469
+ includeTests: info.output.includeTests,
471
470
  });
472
471
 
473
472
  // Run lint if enabled and program is available
474
473
  let lint: LintWithProgramResult | undefined;
475
474
  if (info.output.lint === true && tscResult.program != null) {
475
+ logger.debug(`[${info.name}] lint 시작`);
476
476
  if (watchLintRunner == null) {
477
477
  watchLintRunner = new LintWithProgramRunner({
478
478
  cwd: info.cwd,
@@ -483,15 +483,21 @@ async function rebuildAll(): Promise<ServerCombinedBuildEvent> {
483
483
  program: tscResult.program,
484
484
  affectedFiles: tscResult.affectedFiles,
485
485
  });
486
+ logger.debug(`[${info.name}] lint 완료`);
486
487
  }
487
488
 
488
489
  const jsResult = esbuildPromise
489
490
  ? await esbuildPromise
490
491
  : { success: true, errors: undefined, warnings: undefined };
491
492
 
493
+ const allErrors = [...(jsResult.errors ?? []), ...(tscResult.errors ?? [])];
494
+ logger.debug(`[${info.name}] rebuildAll 완료`);
492
495
  return {
493
- js: { success: jsResult.success, errors: jsResult.errors, warnings: jsResult.warnings },
494
- dts: { success: tscResult.success, errors: tscResult.errors },
496
+ build: {
497
+ success: jsResult.success && tscResult.success,
498
+ errors: allErrors.length > 0 ? allErrors : undefined,
499
+ warnings: jsResult.warnings,
500
+ },
495
501
  lint,
496
502
  mainJsPath,
497
503
  };
@@ -541,6 +547,7 @@ async function startWatch(info: ServerWatchInfo): Promise<void> {
541
547
  }
542
548
 
543
549
  // Initial build: esbuild + tsc parallel
550
+ sender.send("buildStart", {});
544
551
  const initialResult = await rebuildAll();
545
552
 
546
553
  // Write .config.json on first build
@@ -560,17 +567,17 @@ async function startWatch(info: ServerWatchInfo): Promise<void> {
560
567
  // Server package itself + workspace dependency packages source
561
568
  const watchDirs = [
562
569
  info.pkgDir,
563
- ...workspaceDeps.map((d) => path.join(info.cwd, "packages", d)),
570
+ ...workspaceDeps.map((d) => pathx.posixResolve(info.cwd, "packages", d)),
564
571
  ];
565
572
  for (const dir of watchDirs) {
566
- watchPaths.push(path.join(dir, "src", "**", "*"));
573
+ watchPaths.push(pathx.posixResolve(dir, "src", "**", "*"));
567
574
  }
568
575
 
569
576
  // ReplaceDeps dependency packages dist
570
577
  for (const pkg of replaceDeps) {
571
- watchPaths.push(path.join(info.cwd, "node_modules", ...pkg.split("/"), "dist", "**", "*.{js,mjs,cjs}"));
578
+ watchPaths.push(pathx.posixResolve(info.cwd, "node_modules", ...pkg.split("/"), "dist", "**", "*.{js,mjs,cjs}"));
572
579
  watchPaths.push(
573
- path.join(info.pkgDir, "node_modules", ...pkg.split("/"), "dist", "**", "*.{js,mjs,cjs}"),
580
+ pathx.posixResolve(info.pkgDir, "node_modules", ...pkg.split("/"), "dist", "**", "*.{js,mjs,cjs}"),
574
581
  );
575
582
  }
576
583
 
@@ -627,7 +634,7 @@ async function startWatch(info: ServerWatchInfo): Promise<void> {
627
634
 
628
635
  // Filter by metafile inputs
629
636
  const metafileAbsPaths = new Set(
630
- Object.keys(lastMetafile.inputs).map((key) => pathx.norm(info.cwd, key)),
637
+ Object.keys(lastMetafile.inputs).map((key) => pathx.posixResolve(info.cwd, key)),
631
638
  );
632
639
 
633
640
  const hasRelevantChange = changes.some((c) => metafileAbsPaths.has(c.path));
@@ -138,8 +138,8 @@ describe("sdAngularPlugin CSS HMR compatibility", () => {
138
138
  await (plugin as any).buildEnd?.call({});
139
139
  });
140
140
 
141
- // Unit: .scss 파일은 위임하지 않고 Angular가 처리한다 (대조군)
142
- it("processes .scss files (does NOT delegate to Vite default)", async () => {
141
+ // Unit: .scss 파일이 TS 프로그램에 없으면 리빌드를 건너뛴다
142
+ it("skips .scss files not in the TypeScript program", async () => {
143
143
  const onBuildStart = vi.fn();
144
144
  const onBuild = vi.fn();
145
145
  const plugin = sdAngularPlugin({
@@ -151,6 +151,10 @@ describe("sdAngularPlugin CSS HMR compatibility", () => {
151
151
 
152
152
  await (plugin as any).buildStart?.call({});
153
153
 
154
+ // buildStart 완료 후 초기 빌드 결과 콜백 리셋
155
+ onBuildStart.mockClear();
156
+ onBuild.mockClear();
157
+
154
158
  const scssFilePath = path
155
159
  .join(FIXTURE_DIR, "src/styles.scss")
156
160
  .replace(/\\/g, "/");
@@ -163,12 +167,12 @@ describe("sdAngularPlugin CSS HMR compatibility", () => {
163
167
  read: () => Promise.resolve(""),
164
168
  });
165
169
 
166
- // .scss Angular가 처리하므로 undefined 아닌 배열 반환
167
- expect(Array.isArray(result)).toBe(true);
170
+ // .scss 파일이 TS 프로그램에 없으므로 undefined 반환 (리빌드 건너뜀)
171
+ expect(result).toBeUndefined();
168
172
 
169
- // Angular compiler update가 호출되어야 한다
170
- expect(onBuildStart).toHaveBeenCalled();
171
- expect(onBuild).toHaveBeenCalled();
173
+ // Angular compiler update가 호출되지 않아야 한다
174
+ expect(onBuildStart).not.toHaveBeenCalled();
175
+ expect(onBuild).not.toHaveBeenCalled();
172
176
 
173
177
  await (plugin as any).buildEnd?.call({});
174
178
  });
@@ -19,7 +19,12 @@ vi.mock("../../src/utils/lint-with-program", () => ({
19
19
  LintWithProgramRunner: MockLintWithProgramRunner,
20
20
  }));
21
21
 
22
- const mockTsProgram = { getSourceFiles: () => [] };
22
+ const mockTsProgram = {
23
+ getSourceFiles: () => [
24
+ { fileName: "/workspace/packages/client/src/main.ts" },
25
+ { fileName: "/workspace/packages/client/src/app.ts" },
26
+ ],
27
+ };
23
28
 
24
29
  const mockCompiler = {
25
30
  initialize: vi.fn().mockResolvedValue({ affectedFiles: new Set() }),
@@ -1,3 +1,4 @@
1
+ import path from "path";
1
2
  import { describe, it, expect, vi, beforeEach } from "vitest";
2
3
 
3
4
  //#region Mocks
@@ -29,6 +30,10 @@ vi.mock("@simplysm/core-node", () => ({
29
30
  exec: mockCpxExec,
30
31
  execSync: vi.fn().mockReturnValue({ stdout: "", stderr: "", exitCode: 0 }),
31
32
  },
33
+ pathx: {
34
+ posixResolve: (...args: string[]) => path.resolve(...args).replace(/\\/g, "/"),
35
+ posix: (p: string) => p.replace(/\\/g, "/"),
36
+ },
32
37
  }));
33
38
 
34
39
  // env mock
@@ -1,3 +1,4 @@
1
+ import path from "path";
1
2
  import { describe, it, expect, vi, beforeEach } from "vitest";
2
3
 
3
4
  //#region Mocks
@@ -27,6 +28,10 @@ vi.mock("@simplysm/core-node", () => ({
27
28
  exec: mockCpxExec,
28
29
  execSync: vi.fn().mockReturnValue({ stdout: "", stderr: "", exitCode: 0 }),
29
30
  },
31
+ pathx: {
32
+ posixResolve: (...args: string[]) => path.resolve(...args).replace(/\\/g, "/"),
33
+ posix: (p: string) => p.replace(/\\/g, "/"),
34
+ },
30
35
  }));
31
36
 
32
37
  // env mock
@@ -1,3 +1,4 @@
1
+ import path from "path";
1
2
  import { describe, it, expect, vi, beforeEach } from "vitest";
2
3
 
3
4
  //#region Mocks
@@ -28,6 +29,10 @@ vi.mock("@simplysm/core-node", () => ({
28
29
  exec: mockCpxExec,
29
30
  execSync: vi.fn().mockReturnValue({ stdout: "", stderr: "", exitCode: 0 }),
30
31
  },
32
+ pathx: {
33
+ posixResolve: (...args: string[]) => path.resolve(...args).replace(/\\/g, "/"),
34
+ posix: (p: string) => p.replace(/\\/g, "/"),
35
+ },
31
36
  }));
32
37
 
33
38
  let mockEnv: Record<string, unknown> = {};
@@ -1,3 +1,4 @@
1
+ import path from "path";
1
2
  import { describe, it, expect, vi, beforeEach } from "vitest";
2
3
 
3
4
  //#region Mocks
@@ -29,6 +30,10 @@ vi.mock("@simplysm/core-node", () => ({
29
30
  exec: mockCpxExec,
30
31
  execSync: vi.fn().mockReturnValue({ stdout: "", stderr: "", exitCode: 0 }),
31
32
  },
33
+ pathx: {
34
+ posixResolve: (...args: string[]) => path.resolve(...args).replace(/\\/g, "/"),
35
+ posix: (p: string) => p.replace(/\\/g, "/"),
36
+ },
32
37
  }));
33
38
 
34
39
  // env mock
@@ -1,3 +1,4 @@
1
+ import path from "path";
1
2
  import { describe, it, expect, vi, beforeEach } from "vitest";
2
3
 
3
4
  //#region Mocks
@@ -28,6 +29,10 @@ vi.mock("@simplysm/core-node", () => ({
28
29
  exec: mockCpxExec,
29
30
  execSync: vi.fn().mockReturnValue({ stdout: "", stderr: "", exitCode: 0 }),
30
31
  },
32
+ pathx: {
33
+ posixResolve: (...args: string[]) => path.resolve(...args).replace(/\\/g, "/"),
34
+ posix: (p: string) => p.replace(/\\/g, "/"),
35
+ },
31
36
  }));
32
37
 
33
38
  let mockEnv: Record<string, unknown> = {};