@simplysm/sd-cli 14.0.8 → 14.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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 +11 -13
  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
 
@@ -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");
@@ -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);
@@ -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);
@@ -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,10 +145,9 @@ 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에 출력된다"
@@ -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", () => ({
@@ -50,7 +50,8 @@ vi.mock("@simplysm/core-node", () => ({
50
50
  })),
51
51
  },
52
52
  pathx: {
53
- norm: vi.fn((...args: string[]) => path.resolve(...args).replace(/\\/g, "/")),
53
+ posix: vi.fn((p: string) => p.replace(/\\/g, "/")),
54
+ posixResolve: vi.fn((...args: string[]) => path.resolve(...args).replace(/\\/g, "/")),
54
55
  },
55
56
  cpx: {
56
57
  exec: vi.fn().mockResolvedValue({ stdout: "", stderr: "", exitCode: 0 }),
@@ -212,9 +213,8 @@ describe("server-build.worker build()", () => {
212
213
  it("runs esbuild and tsc in parallel for server build", async () => {
213
214
  const result = await workerFns["build"](baseBuildInfo);
214
215
 
215
- expect(result.js.success).toBe(true);
216
- expect(result.dts.success).toBe(true);
217
- expect(result.mainJsPath).toBe(path.join(baseBuildInfo.pkgDir, "dist", "main.js"));
216
+ expect(result.build.success).toBe(true);
217
+ expect(result.mainJsPath).toBe(path.resolve(baseBuildInfo.pkgDir, "dist", "main.js").replace(/\\/g, "/"));
218
218
 
219
219
  // esbuild was called
220
220
  expect(esbuild.build).toHaveBeenCalled();
@@ -226,7 +226,7 @@ describe("server-build.worker build()", () => {
226
226
  });
227
227
 
228
228
  // Acceptance: type error detected
229
- it("reports typecheck error in dts field", async () => {
229
+ it("reports typecheck error in build field", async () => {
230
230
  mockRunTscPackageBuild.mockReturnValueOnce({
231
231
  success: false,
232
232
  errors: ["TS2345: type error"] as any,
@@ -237,14 +237,13 @@ describe("server-build.worker build()", () => {
237
237
 
238
238
  const result = await workerFns["build"](baseBuildInfo);
239
239
 
240
- expect(result.js.success).toBe(true);
241
- expect(result.dts.success).toBe(false);
242
- expect(result.dts.errors).toContain("TS2345: type error");
243
- expect(result.dts.diagnostics).toHaveLength(1);
240
+ expect(result.build.success).toBe(false);
241
+ expect(result.build.errors).toContain("TS2345: type error");
242
+ expect(result.build.diagnostics).toHaveLength(1);
244
243
  });
245
244
 
246
245
  // Acceptance: esbuild error detected
247
- it("reports esbuild error in js field", async () => {
246
+ it("reports esbuild error in build field", async () => {
248
247
  vi.mocked(esbuild.build).mockResolvedValueOnce({
249
248
  errors: [{ text: "syntax error" }],
250
249
  warnings: [],
@@ -253,9 +252,8 @@ describe("server-build.worker build()", () => {
253
252
 
254
253
  const result = await workerFns["build"](baseBuildInfo);
255
254
 
256
- expect(result.js.success).toBe(false);
257
- expect(result.js.errors).toContain("syntax error");
258
- expect(result.dts.success).toBe(true);
255
+ expect(result.build.success).toBe(false);
256
+ expect(result.build.errors).toContain("syntax error");
259
257
  });
260
258
 
261
259
  // Unit: .d.ts files are NOT generated (emit=false)
@@ -273,8 +271,8 @@ describe("server-build.worker build()", () => {
273
271
 
274
272
  const result = await workerFns["build"](baseBuildInfo);
275
273
 
276
- expect(result.js.success).toBe(false);
277
- expect(result.js.errors).toContain("esbuild crash");
274
+ expect(result.build.success).toBe(false);
275
+ expect(result.build.errors).toContain("esbuild crash");
278
276
  });
279
277
 
280
278
  // Unit: tsconfig parsed and passed to tsc
@@ -446,9 +444,9 @@ describe("server-build.worker build()", () => {
446
444
  });
447
445
 
448
446
  const result = await workerFns["build"](baseBuildInfo);
449
- expect(result.js.success).toBe(false);
450
- expect(result.js.errors[0]).toContain("unknown-dep");
451
- expect(result.js.errors[0]).toContain("not found in pnpm-lock.yaml");
447
+ expect(result.build.success).toBe(false);
448
+ expect(result.build.errors[0]).toContain("unknown-dep");
449
+ expect(result.build.errors[0]).toContain("not found in pnpm-lock.yaml");
452
450
  });
453
451
 
454
452
  // Unit: uses locked version for native module externals
@@ -545,13 +543,12 @@ describe("server-build.worker startWatch()", () => {
545
543
  });
546
544
 
547
545
  // Acceptance: initial build with typecheck
548
- it("sends build event with js+dts results after initial build", async () => {
546
+ it("sends build event with build results after initial build", async () => {
549
547
  await workerFns["startWatch"](watchInfo);
550
548
 
551
549
  expect(mockSend).toHaveBeenCalledWith("build", expect.objectContaining({
552
- js: expect.objectContaining({ success: true }),
553
- dts: expect.objectContaining({ success: true }),
554
- mainJsPath: path.join(watchInfo.pkgDir, "dist", "main.js"),
550
+ build: expect.objectContaining({ success: true }),
551
+ mainJsPath: path.resolve(watchInfo.pkgDir, "dist", "main.js").replace(/\\/g, "/"),
555
552
  }));
556
553
  });
557
554