@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
@@ -2,9 +2,10 @@ import { describe, it, expect } from "vitest";
2
2
  import path from "path";
3
3
  import { createOutputPathRewriter, adjustMapSources, addJsExtensionToImports, rewriteScssImports } from "../../src/utils/output-path-rewriter";
4
4
 
5
- // Use path.resolve to get platform-correct absolute paths
5
+ // POSIX paths for assertions after migration, createOutputPathRewriter returns POSIX paths
6
6
  const pkgDir = path.resolve("/workspace/packages/my-pkg");
7
7
  const distDir = path.resolve(pkgDir, "dist");
8
+ const posixDistDir = distDir.replace(/\\/g, "/");
8
9
 
9
10
  describe("createOutputPathRewriter", () => {
10
11
  const rewrite = createOutputPathRewriter(pkgDir);
@@ -14,7 +15,7 @@ describe("createOutputPathRewriter", () => {
14
15
  const result = rewrite(nestedPath, "declare const x: number;");
15
16
 
16
17
  expect(result).not.toBeNull();
17
- expect(result![0]).toBe(path.join(distDir, "index.d.ts"));
18
+ expect(result![0]).toBe(posixDistDir + "/index.d.ts");
18
19
  expect(result![1]).toBe("declare const x: number;");
19
20
  });
20
21
 
@@ -23,7 +24,7 @@ describe("createOutputPathRewriter", () => {
23
24
  const result = rewrite(nestedPath, "declare const y: string;");
24
25
 
25
26
  expect(result).not.toBeNull();
26
- expect(result![0]).toBe(path.join(distDir, "utils", "helper.d.ts"));
27
+ expect(result![0]).toBe(posixDistDir + "/utils/helper.d.ts");
27
28
  });
28
29
 
29
30
  it("returns null for other packages' nested .d.ts", () => {
@@ -38,7 +39,7 @@ describe("createOutputPathRewriter", () => {
38
39
  const result = rewrite(flatPath, "declare const z: boolean;");
39
40
 
40
41
  expect(result).not.toBeNull();
41
- expect(result![0]).toBe(flatPath);
42
+ expect(result![0]).toBe(flatPath.replace(/\\/g, "/"));
42
43
  expect(result![1]).toBe("declare const z: boolean;");
43
44
  });
44
45
 
@@ -55,7 +56,7 @@ describe("createOutputPathRewriter", () => {
55
56
  const result = rewrite(nestedPath, mapContent);
56
57
 
57
58
  expect(result).not.toBeNull();
58
- expect(result![0]).toBe(path.join(distDir, "index.d.ts.map"));
59
+ expect(result![0]).toBe(posixDistDir + "/index.d.ts.map");
59
60
  // Sources path should be adjusted for the new location
60
61
  const parsedMap = JSON.parse(result![1]) as { sources: string[] };
61
62
  expect(parsedMap.sources).toBeDefined();
@@ -83,7 +84,7 @@ describe("adjustMapSources", () => {
83
84
 
84
85
  // The absolute source should be the same, just the relative path changes
85
86
  const absoluteFromOriginal = path.resolve(original, "..", "..", "..", "src", "index.ts");
86
- const expectedRelative = path.relative(target, absoluteFromOriginal);
87
+ const expectedRelative = path.relative(target, absoluteFromOriginal).replace(/\\/g, "/");
87
88
  expect(parsed.sources[0]).toBe(expectedRelative);
88
89
  });
89
90
 
@@ -25,8 +25,8 @@ describe("formatBuildMessages", () => {
25
25
  });
26
26
 
27
27
  it("handles multiple messages", () => {
28
- const result = formatBuildMessages("core", "dts", ["err1", "err2"]);
29
- expect(result).toContain("core (dts)");
28
+ const result = formatBuildMessages("core", "node", ["err1", "err2"]);
29
+ expect(result).toContain("core (node)");
30
30
  expect(result).toContain("→ err1");
31
31
  expect(result).toContain("→ err2");
32
32
  });
@@ -53,13 +53,13 @@ describe("printErrors", () => {
53
53
  expect(consola.error).toHaveBeenCalledOnce();
54
54
  });
55
55
 
56
- it("uses 'dts' as label for dts type errors", () => {
56
+ it("uses target as label for build type errors", () => {
57
57
  const results = new Map<string, BuildResult>([
58
- ["core:dts", { name: "core", target: "node", type: "dts", status: "error", message: "type error" }],
58
+ ["core:build", { name: "core", target: "node", type: "build", status: "error", message: "type error" }],
59
59
  ]);
60
60
  printErrors(results);
61
61
  const callArg = vi.mocked(consola.error).mock.calls[0][0] as string;
62
- expect(callArg).toContain("dts");
62
+ expect(callArg).toContain("node");
63
63
  });
64
64
 
65
65
  it("skips non-error results", () => {
@@ -2,7 +2,7 @@ import { describe, it, expect, vi } from "vitest";
2
2
  import { RebuildManager } from "../../src/utils/rebuild-manager";
3
3
 
4
4
  function createManager() {
5
- const logger = { start: vi.fn(), success: vi.fn(), error: vi.fn() };
5
+ const logger = { start: vi.fn(), success: vi.fn(), error: vi.fn(), debug: vi.fn() };
6
6
  const manager = new RebuildManager(logger as any);
7
7
  return { manager, logger };
8
8
  }
@@ -1,4 +1,5 @@
1
1
  import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import path from "path";
2
3
 
3
4
  const mockExists = vi.fn();
4
5
  const mockJitiImport = vi.fn();
@@ -7,6 +8,9 @@ vi.mock("@simplysm/core-node", () => ({
7
8
  fsx: {
8
9
  exists: (...args: unknown[]) => mockExists(...args),
9
10
  },
11
+ pathx: {
12
+ posixResolve: (...args: string[]) => path.resolve(...args).replace(/\\/g, "/"),
13
+ },
10
14
  }));
11
15
 
12
16
  vi.mock("jiti", () => ({
@@ -45,6 +45,7 @@ vi.mock("../../src/utils/typecheck-serialization", () => ({
45
45
  vi.mock("@simplysm/core-node", () => ({
46
46
  pathx: {
47
47
  isChildPath: vi.fn((filePath: string, parentDir: string) => filePath.startsWith(parentDir)),
48
+ posix: vi.fn((p: string) => p.replace(/\\/g, "/")),
48
49
  },
49
50
  }));
50
51
 
@@ -183,7 +184,7 @@ describe("runTscPackageBuild", () => {
183
184
  );
184
185
  });
185
186
 
186
- it("typecheck mode uses all package files as rootNames", async () => {
187
+ it("typecheck mode without includeTests uses only source files as rootNames", async () => {
187
188
  const tsModule = await import("typescript");
188
189
  const { runTscPackageBuild } = await import("../../src/utils/tsc-build");
189
190
 
@@ -193,7 +194,24 @@ describe("runTscPackageBuild", () => {
193
194
  output: { js: false, dts: false },
194
195
  });
195
196
 
196
- // createEmitAndSemanticDiagnosticsBuilderProgram(rootNames, options, host)
197
+ expect(vi.mocked(tsModule.default.createEmitAndSemanticDiagnosticsBuilderProgram)).toHaveBeenCalledWith(
198
+ [SRC_INDEX, SRC_UTIL],
199
+ expect.any(Object),
200
+ expect.any(Object),
201
+ );
202
+ });
203
+
204
+ it("typecheck mode with includeTests uses all package files as rootNames", async () => {
205
+ const tsModule = await import("typescript");
206
+ const { runTscPackageBuild } = await import("../../src/utils/tsc-build");
207
+
208
+ runTscPackageBuild({
209
+ pkgDir: PKG_DIR,
210
+ cwd: path.resolve("/"),
211
+ output: { js: false, dts: false },
212
+ includeTests: true,
213
+ });
214
+
197
215
  expect(vi.mocked(tsModule.default.createEmitAndSemanticDiagnosticsBuilderProgram)).toHaveBeenCalledWith(
198
216
  [SRC_INDEX, SRC_UTIL, TEST_INDEX],
199
217
  expect.any(Object),
@@ -459,8 +477,8 @@ describe("runTscPackageBuild", () => {
459
477
  );
460
478
  });
461
479
 
462
- // Unit: env suffix is NOT applied in emit mode
463
- it("does not add env suffix to tsBuildInfoFile in emit mode", async () => {
480
+ // Unit: env suffix IS applied in emit mode (distinguishes build artifacts by env)
481
+ it("adds env suffix to tsBuildInfoFile in emit mode", async () => {
464
482
  const { runTscPackageBuild } = await import("../../src/utils/tsc-build");
465
483
  runTscPackageBuild({
466
484
  pkgDir: PKG_DIR,
@@ -469,7 +487,7 @@ describe("runTscPackageBuild", () => {
469
487
  env: "node",
470
488
  });
471
489
  expect(capturedOptions!.tsBuildInfoFile).toBe(
472
- path.join(PKG_DIR, ".cache", "build.tsbuildinfo"),
490
+ path.join(PKG_DIR, ".cache", "build-node.tsbuildinfo"),
473
491
  );
474
492
  });
475
493
 
@@ -1,4 +1,5 @@
1
1
  import { describe, it, expect, vi, beforeEach } from "vitest";
2
+ import path from "path";
2
3
 
3
4
  //#region Mocks
4
5
 
@@ -9,13 +10,16 @@ let mockSend: ReturnType<typeof vi.fn>;
9
10
  const mockOnChange = vi.fn();
10
11
  const mockWatcherClose = vi.fn();
11
12
 
12
- // tsc build mock
13
+ // tsc build mock — default includes program with /pkg/src/index.ts
13
14
  const mockRunTscPackageBuild = vi.fn(() => ({
14
15
  success: true,
15
16
  errors: undefined,
16
17
  diagnostics: [],
17
18
  errorCount: 0,
18
19
  warningCount: 0,
20
+ program: {
21
+ getSourceFiles: () => [{ fileName: "/pkg/src/index.ts" }],
22
+ },
19
23
  }));
20
24
 
21
25
  vi.mock("@simplysm/core-node", () => ({
@@ -30,16 +34,21 @@ vi.mock("@simplysm/core-node", () => ({
30
34
  close: mockWatcherClose,
31
35
  })),
32
36
  },
37
+ pathx: {
38
+ posix: vi.fn((p: string) => p.replace(/\\/g, "/")),
39
+ posixResolve: vi.fn((...args: string[]) => path.resolve(...args).replace(/\\/g, "/")),
40
+ },
33
41
  }));
34
42
 
35
43
  vi.mock("@simplysm/core-common", () => ({
36
44
  err: { message: (e: any) => e?.message ?? String(e) },
37
45
  }));
38
46
 
47
+ const mockDebug = vi.fn();
39
48
  vi.mock("consola", () => ({
40
49
  consola: {
41
50
  withTag: vi.fn(() => ({
42
- debug: vi.fn(),
51
+ debug: mockDebug,
43
52
  warn: vi.fn(),
44
53
  })),
45
54
  },
@@ -71,6 +80,9 @@ beforeEach(async () => {
71
80
  diagnostics: [],
72
81
  errorCount: 0,
73
82
  warningCount: 0,
83
+ program: {
84
+ getSourceFiles: () => [{ fileName: "/pkg/src/index.ts" }],
85
+ },
74
86
  });
75
87
  mockCollectDeps.mockReturnValue({ workspaceDeps: [], replaceDeps: [] });
76
88
  // Re-import to get fresh workerFns
@@ -91,8 +103,7 @@ describe("library-build.worker build()", () => {
91
103
  it("runs tsc with output flags and returns combined result", async () => {
92
104
  const result = await workerFns["build"]({ ...buildInfo, output: { js: true, dts: true } });
93
105
 
94
- expect(result.js.success).toBe(true);
95
- expect(result.dts.success).toBe(true);
106
+ expect(result.build.success).toBe(true);
96
107
  expect(mockRunTscPackageBuild).toHaveBeenCalledWith(
97
108
  expect.objectContaining({ output: { js: true, dts: true } }),
98
109
  );
@@ -102,8 +113,7 @@ describe("library-build.worker build()", () => {
102
113
  it("passes dts-only output to tsc", async () => {
103
114
  const result = await workerFns["build"]({ ...buildInfo, output: { js: false, dts: true } });
104
115
 
105
- expect(result.js.success).toBe(true);
106
- expect(result.dts.success).toBe(true);
116
+ expect(result.build.success).toBe(true);
107
117
  expect(mockRunTscPackageBuild).toHaveBeenCalledWith(
108
118
  expect.objectContaining({ output: { js: false, dts: true } }),
109
119
  );
@@ -113,28 +123,30 @@ describe("library-build.worker build()", () => {
113
123
  it("runs typecheck only when both false", async () => {
114
124
  const result = await workerFns["build"]({ ...buildInfo, output: { js: false, dts: false } });
115
125
 
116
- expect(result.dts.success).toBe(true);
126
+ expect(result.build.success).toBe(true);
117
127
  expect(mockRunTscPackageBuild).toHaveBeenCalledWith(
118
128
  expect.objectContaining({ output: { js: false, dts: false } }),
119
129
  );
120
130
  });
121
131
 
122
- // Unit: tsc failure reflects in both js and dts results
123
- it("reports failure in both js and dts when tsc fails", async () => {
132
+ // Unit: tsc failure reflects in build result
133
+ it("reports failure in build when tsc fails", async () => {
124
134
  mockRunTscPackageBuild.mockReturnValueOnce({
125
135
  success: false,
126
136
  errors: ["TS2345: type error"] as any,
127
137
  diagnostics: [{ code: 2345, category: 1 }] as any,
128
138
  errorCount: 1,
129
139
  warningCount: 0,
140
+ program: {
141
+ getSourceFiles: () => [{ fileName: "/pkg/src/index.ts" }],
142
+ },
130
143
  });
131
144
 
132
145
  const result = await workerFns["build"]({ ...buildInfo, output: { js: true, dts: true } });
133
146
 
134
- expect(result.js.success).toBe(false);
135
- expect(result.js.errors).toContain("TS2345: type error");
136
- expect(result.dts.success).toBe(false);
137
- expect(result.dts.diagnostics).toHaveLength(1);
147
+ expect(result.build.success).toBe(false);
148
+ expect(result.build.errors).toContain("TS2345: type error");
149
+ expect(result.build.diagnostics).toHaveLength(1);
138
150
  });
139
151
 
140
152
  // Acceptance: env from BuildOutput is passed through to runTscPackageBuild
@@ -168,8 +180,7 @@ describe("library-build.worker startWatch()", () => {
168
180
  await workerFns["startWatch"]({ ...buildInfo, output: { js: true, dts: true } });
169
181
 
170
182
  expect(mockSend).toHaveBeenCalledWith("build", expect.objectContaining({
171
- js: expect.objectContaining({ success: true }),
172
- dts: expect.objectContaining({ success: true }),
183
+ build: expect.objectContaining({ success: true }),
173
184
  }));
174
185
  });
175
186
 
@@ -194,12 +205,11 @@ describe("library-build.worker startWatch()", () => {
194
205
  const onChangeCallback = mockOnChange.mock.calls[0][1];
195
206
  mockSend.mockClear();
196
207
 
197
- await onChangeCallback();
208
+ await onChangeCallback([{ event: "change", path: "/pkg/src/index.ts" }]);
198
209
 
199
210
  expect(mockSend).toHaveBeenCalledWith("buildStart", {});
200
211
  expect(mockSend).toHaveBeenCalledWith("build", expect.objectContaining({
201
- js: expect.objectContaining({ success: true }),
202
- dts: expect.objectContaining({ success: true }),
212
+ build: expect.objectContaining({ success: true }),
203
213
  }));
204
214
  });
205
215
 
@@ -221,7 +231,7 @@ describe("library-build.worker startWatch()", () => {
221
231
  const onChangeCallback = mockOnChange.mock.calls[0][1];
222
232
  mockSend.mockClear();
223
233
 
224
- await onChangeCallback();
234
+ await onChangeCallback([{ event: "change", path: "/pkg/src/index.ts" }]);
225
235
 
226
236
  expect(mockSend).toHaveBeenCalledWith("error", { message: "tsc crash" });
227
237
  });
@@ -273,7 +283,7 @@ describe("library-build.worker startWatch()", () => {
273
283
  const onChangeCallback = mockOnChange.mock.calls[0][1];
274
284
  mockRunTscPackageBuild.mockClear();
275
285
 
276
- await onChangeCallback();
286
+ await onChangeCallback([{ event: "change", path: "/pkg/src/index.ts" }]);
277
287
 
278
288
  expect(mockRunTscPackageBuild).toHaveBeenCalledWith(
279
289
  expect.objectContaining({ env: "browser" }),
@@ -281,6 +291,89 @@ describe("library-build.worker startWatch()", () => {
281
291
  });
282
292
  });
283
293
 
294
+ describe("library-build.worker startWatch() dependency filter", () => {
295
+ const createMockProgram = (fileNames: string[]) => ({
296
+ getSourceFiles: () => fileNames.map((f) => ({ fileName: f })),
297
+ });
298
+
299
+ const buildInfoWithProgram = () => {
300
+ mockRunTscPackageBuild.mockReturnValue({
301
+ success: true,
302
+ errors: undefined,
303
+ diagnostics: [],
304
+ errorCount: 0,
305
+ warningCount: 0,
306
+ program: createMockProgram(["/pkg/src/index.ts", "/pkg/src/utils.ts"]),
307
+ });
308
+ };
309
+
310
+ // Acceptance: Skip rebuild when changed file is not in program
311
+ it("skips rebuild when changed file is not in program source files", async () => {
312
+ buildInfoWithProgram();
313
+ await workerFns["startWatch"]({ ...buildInfo, output: { js: true, dts: true } });
314
+ const onChangeCallback = mockOnChange.mock.calls[0][1];
315
+ mockSend.mockClear();
316
+
317
+ await onChangeCallback([{ event: "change", path: "/other/src/unrelated.ts" }]);
318
+
319
+ expect(mockSend).not.toHaveBeenCalledWith("buildStart", {});
320
+ expect(mockSend).not.toHaveBeenCalledWith("build", expect.anything());
321
+ });
322
+
323
+ // Acceptance: Rebuild when changed file is in program
324
+ it("rebuilds when changed file is in program source files", async () => {
325
+ buildInfoWithProgram();
326
+ await workerFns["startWatch"]({ ...buildInfo, output: { js: true, dts: true } });
327
+ const onChangeCallback = mockOnChange.mock.calls[0][1];
328
+ mockSend.mockClear();
329
+
330
+ await onChangeCallback([{ event: "change", path: "/pkg/src/index.ts" }]);
331
+
332
+ expect(mockSend).toHaveBeenCalledWith("buildStart", {});
333
+ expect(mockSend).toHaveBeenCalledWith("build", expect.anything());
334
+ });
335
+
336
+ // Acceptance: Always rebuild on file add
337
+ it("always rebuilds on file add event regardless of program", async () => {
338
+ buildInfoWithProgram();
339
+ await workerFns["startWatch"]({ ...buildInfo, output: { js: true, dts: true } });
340
+ const onChangeCallback = mockOnChange.mock.calls[0][1];
341
+ mockSend.mockClear();
342
+
343
+ await onChangeCallback([{ event: "add", path: "/pkg/src/brand-new.ts" }]);
344
+
345
+ expect(mockSend).toHaveBeenCalledWith("buildStart", {});
346
+ expect(mockSend).toHaveBeenCalledWith("build", expect.anything());
347
+ });
348
+
349
+ // Acceptance: Always rebuild on file unlink
350
+ it("always rebuilds on file unlink event regardless of program", async () => {
351
+ buildInfoWithProgram();
352
+ await workerFns["startWatch"]({ ...buildInfo, output: { js: true, dts: true } });
353
+ const onChangeCallback = mockOnChange.mock.calls[0][1];
354
+ mockSend.mockClear();
355
+
356
+ await onChangeCallback([{ event: "unlink", path: "/pkg/src/old-file.ts" }]);
357
+
358
+ expect(mockSend).toHaveBeenCalledWith("buildStart", {});
359
+ expect(mockSend).toHaveBeenCalledWith("build", expect.anything());
360
+ });
361
+
362
+ // Acceptance: Debug log when skipping rebuild
363
+ it("logs debug message when skipping rebuild", async () => {
364
+ buildInfoWithProgram();
365
+ await workerFns["startWatch"]({ ...buildInfo, output: { js: true, dts: true } });
366
+ const onChangeCallback = mockOnChange.mock.calls[0][1];
367
+ mockDebug.mockClear();
368
+
369
+ await onChangeCallback([{ event: "change", path: "/other/src/unrelated.ts" }]);
370
+
371
+ expect(mockDebug).toHaveBeenCalledWith(
372
+ expect.stringContaining("빌드에 포함되지 않아 리빌드 건너뜀"),
373
+ );
374
+ });
375
+ });
376
+
284
377
  describe("library-build.worker stopWatch()", () => {
285
378
  it("cleans up FsWatcher", async () => {
286
379
  await workerFns["startWatch"]({ ...buildInfo, output: { js: true, dts: true } });
@@ -22,8 +22,7 @@ vi.mock("../../src/utils/lint-with-program", () => ({
22
22
  const mockTsProgram = { getSourceFiles: () => [] };
23
23
 
24
24
  const mockRunNgtscBuild = vi.fn().mockResolvedValue({
25
- js: { success: true },
26
- dts: { success: true, diagnostics: [] },
25
+ build: { success: true, diagnostics: [] },
27
26
  });
28
27
 
29
28
  vi.mock("../../src/utils/ngtsc-build-core", () => ({
@@ -119,8 +118,7 @@ beforeEach(() => {
119
118
  formattedOutput: "",
120
119
  });
121
120
  mockRunNgtscBuild.mockResolvedValue({
122
- js: { success: true },
123
- dts: { success: true, diagnostics: [] },
121
+ build: { success: true, diagnostics: [] },
124
122
  });
125
123
  });
126
124
 
@@ -128,8 +126,7 @@ describe("ngtsc-build.worker lint integration (Slice 4)", () => {
128
126
  describe("Scenario: ngtsc-build.worker runs lint after typecheck (one-time build)", () => {
129
127
  it("returns lint result when lint is enabled", async () => {
130
128
  mockRunNgtscBuild.mockResolvedValue({
131
- js: { success: true },
132
- dts: { success: true, diagnostics: [] },
129
+ build: { success: true, diagnostics: [] },
133
130
  program: mockTsProgram,
134
131
  });
135
132
 
@@ -11,14 +11,14 @@ describe("ngtsc-build-core: NgtscProgram AOT compilation", () => {
11
11
  beforeAll(() => {
12
12
  // Clean dist before tests
13
13
  if (fs.existsSync(distDir)) {
14
- fs.rmSync(distDir, { recursive: true, force: true });
14
+ fs.rmSync(distDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
15
15
  }
16
16
  });
17
17
 
18
18
  afterAll(() => {
19
19
  // Clean up dist after tests
20
20
  if (fs.existsSync(distDir)) {
21
- fs.rmSync(distDir, { recursive: true, force: true });
21
+ fs.rmSync(distDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
22
22
  }
23
23
  });
24
24
 
@@ -32,12 +32,11 @@ describe("ngtsc-build-core: NgtscProgram AOT compilation", () => {
32
32
  });
33
33
 
34
34
  // Debug: print errors if build failed
35
- if (!result.js.success) {
36
- console.error("JS errors:", result.js.errors);
37
- console.error("DTS errors:", result.dts.errors);
35
+ if (!result.build.success) {
36
+ console.error("Build errors:", result.build.errors);
38
37
  }
39
38
 
40
- expect(result.js.success).toBe(true);
39
+ expect(result.build.success).toBe(true);
41
40
 
42
41
  // Find the provider file output
43
42
  const providerJsPath = resolve(distDir, "core", "providers", "sd-theme-provider.js");
@@ -64,7 +63,7 @@ describe("ngtsc-build-core: NgtscProgram AOT compilation", () => {
64
63
  it("outputs .d.ts files with Angular type metadata", async () => {
65
64
  // Clean dist and run with dts: true
66
65
  if (fs.existsSync(distDir)) {
67
- fs.rmSync(distDir, { recursive: true, force: true });
66
+ fs.rmSync(distDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
68
67
  }
69
68
 
70
69
  const result = await runNgtscBuild({
@@ -74,7 +73,7 @@ describe("ngtsc-build-core: NgtscProgram AOT compilation", () => {
74
73
  output: { js: true, dts: true },
75
74
  });
76
75
 
77
- expect(result.dts.success).toBe(true);
76
+ expect(result.build.success).toBe(true);
78
77
 
79
78
  const providerDtsPath = resolve(distDir, "core", "providers", "sd-theme-provider.d.ts");
80
79
  expect(fs.existsSync(providerDtsPath)).toBe(true);
@@ -97,7 +96,7 @@ describe("ngtsc-build-core: NgtscProgram AOT compilation", () => {
97
96
  // Acceptance: Scenario "run()에서 dts: false면 .d.ts를 생략한다"
98
97
  it("omits .d.ts when output is {js: true, dts: false}", async () => {
99
98
  if (fs.existsSync(distDir)) {
100
- fs.rmSync(distDir, { recursive: true, force: true });
99
+ fs.rmSync(distDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
101
100
  }
102
101
 
103
102
  const result = await runNgtscBuild({
@@ -107,7 +106,7 @@ describe("ngtsc-build-core: NgtscProgram AOT compilation", () => {
107
106
  output: { js: true, dts: false },
108
107
  });
109
108
 
110
- expect(result.js.success).toBe(true);
109
+ expect(result.build.success).toBe(true);
111
110
 
112
111
  const jsExists = fs.existsSync(resolve(distDir, "core", "providers", "sd-theme-provider.js"));
113
112
  expect(jsExists).toBe(true);
@@ -120,7 +119,7 @@ describe("ngtsc-build-core: NgtscProgram AOT compilation", () => {
120
119
  // Acceptance: Scenario "TypeScript + Angular diagnostics를 통합 수집한다"
121
120
  it("collects diagnostics from both TypeScript and Angular compiler", async () => {
122
121
  if (fs.existsSync(distDir)) {
123
- fs.rmSync(distDir, { recursive: true, force: true });
122
+ fs.rmSync(distDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
124
123
  }
125
124
 
126
125
  const result = await runNgtscBuild({
@@ -131,8 +130,8 @@ describe("ngtsc-build-core: NgtscProgram AOT compilation", () => {
131
130
  });
132
131
 
133
132
  // Angular package should compile cleanly
134
- expect(result.dts.diagnostics).toBeDefined();
135
- expect(Array.isArray(result.dts.diagnostics)).toBe(true);
133
+ expect(result.build.diagnostics).toBeDefined();
134
+ expect(Array.isArray(result.build.diagnostics)).toBe(true);
136
135
  }, 60_000);
137
136
 
138
137
  // Acceptance: Scenario "타입 에러가 있어도 빌드 결과를 반환한다"
@@ -146,16 +145,15 @@ describe("ngtsc-build-core: NgtscProgram AOT compilation", () => {
146
145
  });
147
146
 
148
147
  // Verify result structure completeness
149
- expect(result.js).toHaveProperty("success");
150
- expect(result.dts).toHaveProperty("success");
151
- expect(result.dts).toHaveProperty("diagnostics");
152
- expect(Array.isArray(result.dts.diagnostics)).toBe(true);
148
+ expect(result.build).toHaveProperty("success");
149
+ expect(result.build).toHaveProperty("diagnostics");
150
+ expect(Array.isArray(result.build.diagnostics)).toBe(true);
153
151
  }, 60_000);
154
152
 
155
153
  // Acceptance: Scenario "scss/styles.scss가 CSS로 컴파일되어 dist에 출력된다"
156
154
  it("compiles scss/styles.scss to dist/styles.css", async () => {
157
155
  if (fs.existsSync(distDir)) {
158
- fs.rmSync(distDir, { recursive: true, force: true });
156
+ fs.rmSync(distDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
159
157
  }
160
158
 
161
159
  const result = await runNgtscBuild({
@@ -165,7 +163,7 @@ describe("ngtsc-build-core: NgtscProgram AOT compilation", () => {
165
163
  output: { js: true, dts: false },
166
164
  });
167
165
 
168
- expect(result.dts.success).toBe(true);
166
+ expect(result.build.success).toBe(true);
169
167
 
170
168
  const stylesCssPath = resolve(distDir, "styles.css");
171
169
  expect(fs.existsSync(stylesCssPath)).toBe(true);
@@ -87,7 +87,10 @@ vi.mock("@simplysm/core-node", () => ({
87
87
  },
88
88
  ),
89
89
  FsWatcher: { watch: vi.fn() },
90
- pathx: { norm: vi.fn((base: string, rel: string) => `${base}/${rel}`) },
90
+ pathx: {
91
+ posix: vi.fn((p: string) => p.replace(/\\/g, "/")),
92
+ posixResolve: vi.fn((...args: string[]) => args.join("/").replace(/\/+/g, "/").replace(/\\/g, "/")),
93
+ },
91
94
  }));
92
95
 
93
96
  vi.mock("fs", () => ({