@simplysm/sd-cli 14.0.11 → 14.0.12

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 (263) hide show
  1. package/README.md +58 -253
  2. package/dist/angular/client-transform-stylesheet.js +1 -1
  3. package/dist/angular/client-transform-stylesheet.js.map +1 -1
  4. package/dist/angular/vite-angular-plugin.d.ts +1 -1
  5. package/dist/angular/vite-angular-plugin.d.ts.map +1 -1
  6. package/dist/angular/vite-angular-plugin.js +60 -34
  7. package/dist/angular/vite-angular-plugin.js.map +1 -1
  8. package/dist/angular/vite-postcss-inline-plugin.d.ts +1 -1
  9. package/dist/angular/vite-postcss-inline-plugin.js +1 -1
  10. package/dist/capacitor/capacitor.d.ts +14 -2
  11. package/dist/capacitor/capacitor.d.ts.map +1 -1
  12. package/dist/capacitor/capacitor.js +131 -17
  13. package/dist/capacitor/capacitor.js.map +1 -1
  14. package/dist/commands/build.d.ts +3 -10
  15. package/dist/commands/build.d.ts.map +1 -1
  16. package/dist/commands/build.js +3 -10
  17. package/dist/commands/build.js.map +1 -1
  18. package/dist/commands/check.js +3 -3
  19. package/dist/commands/check.js.map +1 -1
  20. package/dist/commands/dev.d.ts +3 -9
  21. package/dist/commands/dev.d.ts.map +1 -1
  22. package/dist/commands/dev.js +3 -9
  23. package/dist/commands/dev.js.map +1 -1
  24. package/dist/commands/device.d.ts +3 -3
  25. package/dist/commands/device.js +5 -5
  26. package/dist/commands/device.js.map +1 -1
  27. package/dist/commands/publish.d.ts +1 -1
  28. package/dist/commands/publish.d.ts.map +1 -1
  29. package/dist/commands/publish.js +18 -26
  30. package/dist/commands/publish.js.map +1 -1
  31. package/dist/commands/replace-deps.d.ts +3 -3
  32. package/dist/commands/replace-deps.d.ts.map +1 -1
  33. package/dist/commands/replace-deps.js +1 -1
  34. package/dist/commands/typecheck.d.ts +4 -3
  35. package/dist/commands/typecheck.d.ts.map +1 -1
  36. package/dist/commands/typecheck.js +5 -11
  37. package/dist/commands/typecheck.js.map +1 -1
  38. package/dist/commands/watch.d.ts +9 -9
  39. package/dist/commands/watch.js +9 -9
  40. package/dist/electron/electron.d.ts.map +1 -1
  41. package/dist/electron/electron.js +42 -3
  42. package/dist/electron/electron.js.map +1 -1
  43. package/dist/engines/BaseEngine.d.ts +1 -1
  44. package/dist/engines/BaseEngine.d.ts.map +1 -1
  45. package/dist/engines/BaseEngine.js +3 -1
  46. package/dist/engines/BaseEngine.js.map +1 -1
  47. package/dist/engines/NgtscEngine.d.ts +7 -7
  48. package/dist/engines/NgtscEngine.d.ts.map +1 -1
  49. package/dist/engines/NgtscEngine.js +3 -3
  50. package/dist/engines/ServerEsbuildEngine.d.ts +7 -7
  51. package/dist/engines/ServerEsbuildEngine.d.ts.map +1 -1
  52. package/dist/engines/ServerEsbuildEngine.js +3 -3
  53. package/dist/engines/TscEngine.d.ts +7 -7
  54. package/dist/engines/TscEngine.d.ts.map +1 -1
  55. package/dist/engines/TscEngine.js +3 -3
  56. package/dist/engines/ViteEngine.d.ts +1 -1
  57. package/dist/engines/ViteEngine.d.ts.map +1 -1
  58. package/dist/engines/ViteEngine.js +7 -12
  59. package/dist/engines/ViteEngine.js.map +1 -1
  60. package/dist/engines/index.d.ts +5 -5
  61. package/dist/engines/index.js +5 -5
  62. package/dist/engines/types.d.ts +20 -20
  63. package/dist/engines/types.d.ts.map +1 -1
  64. package/dist/infra/ResultCollector.d.ts +9 -9
  65. package/dist/infra/ResultCollector.js +8 -8
  66. package/dist/infra/SignalHandler.d.ts +7 -7
  67. package/dist/infra/SignalHandler.js +7 -7
  68. package/dist/infra/WorkerManager.d.ts +14 -14
  69. package/dist/infra/WorkerManager.js +14 -14
  70. package/dist/orchestrators/BuildOrchestrator.d.ts +25 -25
  71. package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
  72. package/dist/orchestrators/BuildOrchestrator.js +29 -29
  73. package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
  74. package/dist/orchestrators/DevWatchOrchestrator.d.ts +7 -7
  75. package/dist/orchestrators/DevWatchOrchestrator.d.ts.map +1 -1
  76. package/dist/orchestrators/DevWatchOrchestrator.js +34 -34
  77. package/dist/orchestrators/DevWatchOrchestrator.js.map +1 -1
  78. package/dist/sd-cli-entry.d.ts +2 -2
  79. package/dist/sd-cli-entry.d.ts.map +1 -1
  80. package/dist/sd-cli-entry.js +15 -8
  81. package/dist/sd-cli-entry.js.map +1 -1
  82. package/dist/sd-cli.d.ts +3 -3
  83. package/dist/sd-cli.js +16 -16
  84. package/dist/sd-cli.js.map +1 -1
  85. package/dist/sd-config.types.d.ts +105 -105
  86. package/dist/sd-config.types.d.ts.map +1 -1
  87. package/dist/utils/angular-compiler.js +5 -5
  88. package/dist/utils/angular-compiler.js.map +1 -1
  89. package/dist/utils/build-env.d.ts +1 -1
  90. package/dist/utils/build-env.js +1 -1
  91. package/dist/utils/concurrency.d.ts +7 -7
  92. package/dist/utils/concurrency.js +7 -7
  93. package/dist/utils/copy-public.d.ts +9 -9
  94. package/dist/utils/copy-public.js +17 -17
  95. package/dist/utils/copy-public.js.map +1 -1
  96. package/dist/utils/copy-src.d.ts +9 -9
  97. package/dist/utils/copy-src.js +11 -11
  98. package/dist/utils/copy-src.js.map +1 -1
  99. package/dist/utils/engine-stop.d.ts +8 -9
  100. package/dist/utils/engine-stop.d.ts.map +1 -1
  101. package/dist/utils/engine-stop.js +9 -10
  102. package/dist/utils/engine-stop.js.map +1 -1
  103. package/dist/utils/esbuild-config.d.ts +23 -23
  104. package/dist/utils/esbuild-config.d.ts.map +1 -1
  105. package/dist/utils/esbuild-config.js +25 -25
  106. package/dist/utils/esbuild-config.js.map +1 -1
  107. package/dist/utils/lint-with-program.d.ts +15 -15
  108. package/dist/utils/lint-with-program.d.ts.map +1 -1
  109. package/dist/utils/lint-with-program.js +29 -29
  110. package/dist/utils/lint-with-program.js.map +1 -1
  111. package/dist/utils/ngtsc-build-core.d.ts +8 -8
  112. package/dist/utils/ngtsc-build-core.d.ts.map +1 -1
  113. package/dist/utils/ngtsc-build-core.js +14 -14
  114. package/dist/utils/ngtsc-build-core.js.map +1 -1
  115. package/dist/utils/output-path-rewriter.d.ts +14 -14
  116. package/dist/utils/output-path-rewriter.js +18 -18
  117. package/dist/utils/output-path-rewriter.js.map +1 -1
  118. package/dist/utils/output-utils.d.ts +6 -6
  119. package/dist/utils/output-utils.js +11 -11
  120. package/dist/utils/output-utils.js.map +1 -1
  121. package/dist/utils/package-utils.d.ts +21 -21
  122. package/dist/utils/package-utils.d.ts.map +1 -1
  123. package/dist/utils/package-utils.js +56 -45
  124. package/dist/utils/package-utils.js.map +1 -1
  125. package/dist/utils/replace-deps.d.ts +25 -25
  126. package/dist/utils/replace-deps.d.ts.map +1 -1
  127. package/dist/utils/replace-deps.js +84 -65
  128. package/dist/utils/replace-deps.js.map +1 -1
  129. package/dist/utils/sd-config.d.ts +3 -3
  130. package/dist/utils/sd-config.js +3 -3
  131. package/dist/utils/tsc-build.d.ts +13 -13
  132. package/dist/utils/tsc-build.d.ts.map +1 -1
  133. package/dist/utils/tsc-build.js +9 -9
  134. package/dist/utils/tsc-build.js.map +1 -1
  135. package/dist/utils/tsconfig.d.ts +11 -9
  136. package/dist/utils/tsconfig.d.ts.map +1 -1
  137. package/dist/utils/tsconfig.js +11 -9
  138. package/dist/utils/tsconfig.js.map +1 -1
  139. package/dist/utils/typecheck-non-package.d.ts +5 -6
  140. package/dist/utils/typecheck-non-package.d.ts.map +1 -1
  141. package/dist/utils/typecheck-non-package.js +7 -8
  142. package/dist/utils/typecheck-non-package.js.map +1 -1
  143. package/dist/utils/typecheck-serialization.d.ts +8 -8
  144. package/dist/utils/typecheck-serialization.d.ts.map +1 -1
  145. package/dist/utils/typecheck-serialization.js +12 -16
  146. package/dist/utils/typecheck-serialization.js.map +1 -1
  147. package/dist/utils/vite-config.d.ts +8 -5
  148. package/dist/utils/vite-config.d.ts.map +1 -1
  149. package/dist/utils/vite-config.js +36 -29
  150. package/dist/utils/vite-config.js.map +1 -1
  151. package/dist/utils/vite-scope-watch-plugin.d.ts.map +1 -1
  152. package/dist/utils/vite-scope-watch-plugin.js +1 -1
  153. package/dist/utils/vite-scope-watch-plugin.js.map +1 -1
  154. package/dist/utils/worker-events.d.ts +12 -12
  155. package/dist/utils/worker-events.d.ts.map +1 -1
  156. package/dist/utils/worker-events.js +10 -10
  157. package/dist/utils/worker-events.js.map +1 -1
  158. package/dist/utils/worker-utils.d.ts +12 -13
  159. package/dist/utils/worker-utils.d.ts.map +1 -1
  160. package/dist/utils/worker-utils.js +12 -13
  161. package/dist/utils/worker-utils.js.map +1 -1
  162. package/dist/vitest-plugin.d.ts.map +1 -1
  163. package/dist/vitest-plugin.js +5 -7
  164. package/dist/vitest-plugin.js.map +1 -1
  165. package/dist/workers/client.worker.d.ts +4 -2
  166. package/dist/workers/client.worker.d.ts.map +1 -1
  167. package/dist/workers/client.worker.js +209 -1
  168. package/dist/workers/client.worker.js.map +1 -1
  169. package/dist/workers/library-build.worker.d.ts +1 -1
  170. package/dist/workers/library-build.worker.d.ts.map +1 -1
  171. package/dist/workers/library-build.worker.js +7 -7
  172. package/dist/workers/library-build.worker.js.map +1 -1
  173. package/dist/workers/lint.worker.d.ts +2 -2
  174. package/dist/workers/lint.worker.js +2 -2
  175. package/dist/workers/ngtsc-build.worker.js +30 -30
  176. package/dist/workers/ngtsc-build.worker.js.map +1 -1
  177. package/dist/workers/server-build.worker.d.ts +17 -17
  178. package/dist/workers/server-build.worker.d.ts.map +1 -1
  179. package/dist/workers/server-build.worker.js +46 -46
  180. package/dist/workers/server-build.worker.js.map +1 -1
  181. package/dist/workers/server-runtime.worker.d.ts +7 -7
  182. package/dist/workers/server-runtime.worker.d.ts.map +1 -1
  183. package/dist/workers/server-runtime.worker.js +17 -17
  184. package/dist/workers/server-runtime.worker.js.map +1 -1
  185. package/docs/config.md +340 -0
  186. package/docs/publish-configuration-types.md +87 -0
  187. package/docs/pwa-configuration-types.md +55 -0
  188. package/docs/vitest-plugin.md +47 -0
  189. package/package.json +9 -7
  190. package/src/angular/client-transform-stylesheet.ts +1 -1
  191. package/src/angular/vite-angular-plugin.ts +70 -37
  192. package/src/angular/vite-postcss-inline-plugin.ts +1 -1
  193. package/src/capacitor/capacitor.ts +159 -23
  194. package/src/commands/build.ts +3 -10
  195. package/src/commands/check.ts +3 -3
  196. package/src/commands/dev.ts +3 -9
  197. package/src/commands/device.ts +5 -5
  198. package/src/commands/publish.ts +30 -26
  199. package/src/commands/replace-deps.ts +3 -3
  200. package/src/commands/typecheck.ts +7 -13
  201. package/src/commands/watch.ts +9 -9
  202. package/src/electron/electron.ts +49 -4
  203. package/src/engines/BaseEngine.ts +4 -1
  204. package/src/engines/NgtscEngine.ts +7 -7
  205. package/src/engines/ServerEsbuildEngine.ts +7 -7
  206. package/src/engines/TscEngine.ts +7 -7
  207. package/src/engines/ViteEngine.ts +8 -13
  208. package/src/engines/index.ts +5 -5
  209. package/src/engines/types.ts +20 -20
  210. package/src/infra/ResultCollector.ts +9 -9
  211. package/src/infra/SignalHandler.ts +7 -7
  212. package/src/infra/WorkerManager.ts +14 -14
  213. package/src/orchestrators/BuildOrchestrator.ts +37 -37
  214. package/src/orchestrators/DevWatchOrchestrator.ts +36 -36
  215. package/src/sd-cli-entry.ts +15 -8
  216. package/src/sd-cli.ts +16 -16
  217. package/src/sd-config.types.ts +107 -107
  218. package/src/utils/angular-compiler.ts +5 -5
  219. package/src/utils/build-env.ts +1 -1
  220. package/src/utils/concurrency.ts +7 -7
  221. package/src/utils/copy-public.ts +17 -17
  222. package/src/utils/copy-src.ts +11 -11
  223. package/src/utils/engine-stop.ts +9 -10
  224. package/src/utils/esbuild-config.ts +29 -29
  225. package/src/utils/lint-with-program.ts +34 -34
  226. package/src/utils/ngtsc-build-core.ts +17 -17
  227. package/src/utils/output-path-rewriter.ts +18 -18
  228. package/src/utils/output-utils.ts +11 -11
  229. package/src/utils/package-utils.ts +57 -45
  230. package/src/utils/replace-deps.ts +92 -67
  231. package/src/utils/sd-config.ts +3 -3
  232. package/src/utils/tsc-build.ts +18 -18
  233. package/src/utils/tsconfig.ts +11 -9
  234. package/src/utils/typecheck-non-package.ts +7 -8
  235. package/src/utils/typecheck-serialization.ts +13 -15
  236. package/src/utils/vite-config.ts +45 -35
  237. package/src/utils/vite-scope-watch-plugin.ts +6 -1
  238. package/src/utils/worker-events.ts +16 -16
  239. package/src/utils/worker-utils.ts +12 -13
  240. package/src/vitest-plugin.ts +5 -8
  241. package/src/workers/client.worker.ts +236 -2
  242. package/src/workers/library-build.worker.ts +8 -8
  243. package/src/workers/lint.worker.ts +2 -2
  244. package/src/workers/ngtsc-build.worker.ts +31 -31
  245. package/src/workers/server-build.worker.ts +60 -60
  246. package/src/workers/server-runtime.worker.ts +22 -22
  247. package/tests/angular/vite-angular-plugin-hmr-fallback.spec.ts +1 -0
  248. package/tests/angular/vite-angular-plugin-hmr.spec.ts +78 -0
  249. package/tests/angular/vite-angular-plugin.spec.ts +67 -0
  250. package/tests/capacitor/capacitor-build.spec.ts +6 -4
  251. package/tests/capacitor/capacitor-icon.spec.ts +7 -5
  252. package/tests/capacitor/capacitor-init.spec.ts +120 -10
  253. package/tests/capacitor/capacitor-run.spec.ts +14 -17
  254. package/tests/capacitor/capacitor-workspace.spec.ts +5 -3
  255. package/tests/commands/check.spec.ts +2 -2
  256. package/tests/commands/publish.spec.ts +2 -2
  257. package/tests/commands/typecheck.spec.ts +8 -0
  258. package/tests/electron/electron.spec.ts +12 -10
  259. package/tests/engines/base-engine.spec.ts +37 -0
  260. package/tests/engines/vite-engine.spec.ts +115 -3
  261. package/tests/utils/vite-config.spec.ts +144 -90
  262. package/tests/workers/client-worker.spec.ts +690 -0
  263. package/tests/workers/server-build-worker.spec.ts +3 -3
@@ -221,8 +221,8 @@ describe("createClientViteConfig", () => {
221
221
 
222
222
  // --- legacyModule (Feature 1.1) ---
223
223
 
224
- // Acceptance: Scenario "legacyModule 활성화한다"
225
- it("enables inlineDynamicImports and import.meta plugin when legacyModule is true", async () => {
224
+ // Acceptance: Scenario "legacyModule 활성화 시 inlineDynamicImports만 설정한다"
225
+ it("enables inlineDynamicImports without import.meta plugin when legacyModule is true", async () => {
226
226
  const config = await createClientViteConfig({
227
227
  ...createDefaultOptions(),
228
228
  legacyModule: true,
@@ -230,26 +230,22 @@ describe("createClientViteConfig", () => {
230
230
 
231
231
  // inlineDynamicImports가 활성화된다
232
232
  expect((config.build as any)?.rollupOptions?.output?.inlineDynamicImports).toBe(true);
233
- // import.meta 치환 플러그인이 활성화된다
233
+ // import.meta 치환 플러그인이 없다 (esbuild target이 자동 치환)
234
234
  const plugins = config.plugins as Array<{ name: string }>;
235
235
  const legacyPlugin = plugins.find((p) => p.name === "sd-legacy-import-meta");
236
- expect(legacyPlugin).toBeDefined();
236
+ expect(legacyPlugin).toBeUndefined();
237
237
  });
238
238
 
239
- // Acceptance: Scenario "legacyModule 설정하지 않는다"
240
- it("does not set inlineDynamicImports or import.meta plugin when legacyModule is not set", async () => {
239
+ // Acceptance: Scenario "legacyModule 미설정 시 코드 분할이 기본 동작한다"
240
+ it("does not set inlineDynamicImports when legacyModule is not set", async () => {
241
241
  const config = await createClientViteConfig(createDefaultOptions());
242
242
 
243
243
  // 코드 분할이 기본 동작한다
244
244
  expect(config.build?.rollupOptions).toBeUndefined();
245
- // import.meta가 그대로 유지된다
246
- const plugins = config.plugins as Array<{ name: string }>;
247
- const legacyPlugin = plugins.find((p) => p.name === "sd-legacy-import-meta");
248
- expect(legacyPlugin).toBeUndefined();
249
245
  });
250
246
 
251
- // Acceptance: Scenario "기존 splitting 옵션을 legacyModule로 마이그레이션한다"
252
- it("legacyModule: true provides inlineDynamicImports plus import.meta plugin (splitting replacement)", async () => {
247
+ // Acceptance: Scenario "legacyModule: true는 inlineDynamicImports를 활성화한다"
248
+ it("legacyModule: true provides inlineDynamicImports (splitting replacement)", async () => {
253
249
  const config = await createClientViteConfig({
254
250
  ...createDefaultOptions(),
255
251
  legacyModule: true,
@@ -257,95 +253,32 @@ describe("createClientViteConfig", () => {
257
253
 
258
254
  // 기존 splitting: false와 동일한 inlineDynamicImports 동작
259
255
  expect((config.build as any)?.rollupOptions?.output?.inlineDynamicImports).toBe(true);
260
- // 추가로 import.meta 치환이 활성화된다
261
- const plugins = config.plugins as Array<{ name: string }>;
262
- const legacyPlugin = plugins.find((p) => p.name === "sd-legacy-import-meta");
263
- expect(legacyPlugin).toBeDefined();
264
- });
265
-
266
- // Unit: enforce: "post" 설정 확인 (D4)
267
- it("sd-legacy-import-meta plugin has enforce: post", async () => {
268
- const config = await createClientViteConfig({
269
- ...createDefaultOptions(),
270
- legacyModule: true,
271
- });
272
-
273
- const plugins = config.plugins as Array<{ name: string; enforce?: string }>;
274
- const legacyPlugin = plugins.find((p) => p.name === "sd-legacy-import-meta");
275
- expect(legacyPlugin?.enforce).toBe("post");
276
256
  });
277
257
 
278
- // Acceptance: Scenario "사용자 코드의 import.meta.url을 치환한다"
279
- it("sd-legacy-import-meta plugin replaces import.meta.url with module URL", async () => {
280
- const config = await createClientViteConfig({
281
- ...createDefaultOptions(),
282
- legacyModule: true,
283
- });
284
-
285
- const plugins = config.plugins as Array<{ name: string; enforce?: string; transform?: Function }>;
286
- const legacyPlugin = plugins.find((p) => p.name === "sd-legacy-import-meta");
287
- expect(legacyPlugin).toBeDefined();
288
-
289
- const code = 'const url = import.meta.url;';
290
- const id = "/packages/my-client/src/app.ts";
291
- const result = legacyPlugin!.transform!(code, id);
258
+ // --- legacyModule esbuild.supported override (Feature 1.4) ---
292
259
 
293
- expect(result).toBeDefined();
294
- expect(result.code).toContain(JSON.stringify(id));
295
- expect(result.code).not.toContain("import.meta");
296
- });
297
-
298
- // Acceptance: Scenario "Vite가 주입한 import.meta.hot을 치환한다"
299
- it("sd-legacy-import-meta plugin replaces import.meta.hot injected by Vite", async () => {
260
+ // Acceptance: Scenario "legacyModule: true일 때 esbuild.supported에 import-meta/dynamic-import false 설정"
261
+ it("sets esbuild.supported to disable import-meta and dynamic-import when legacyModule is true", async () => {
300
262
  const config = await createClientViteConfig({
301
263
  ...createDefaultOptions(),
302
264
  legacyModule: true,
303
265
  });
304
266
 
305
- const plugins = config.plugins as Array<{ name: string; transform?: Function }>;
306
- const legacyPlugin = plugins.find((p) => p.name === "sd-legacy-import-meta");
307
-
308
- const code = 'import.meta.hot = createHotContext("/src/app.ts");';
309
- const id = "/packages/my-client/src/app.ts";
310
- const result = legacyPlugin!.transform!(code, id);
311
-
312
- expect(result).toBeDefined();
313
- expect(result.code).not.toContain("import.meta");
314
- });
315
-
316
- // Acceptance: Scenario "/@vite/client의 import.meta를 치환한다"
317
- it("sd-legacy-import-meta plugin replaces import.meta in /@vite/client", async () => {
318
- const config = await createClientViteConfig({
319
- ...createDefaultOptions(),
320
- legacyModule: true,
321
- });
322
-
323
- const plugins = config.plugins as Array<{ name: string; transform?: Function }>;
324
- const legacyPlugin = plugins.find((p) => p.name === "sd-legacy-import-meta");
325
-
326
- const code = 'const base = import.meta.url;';
327
- const id = "/@vite/client";
328
- const result = legacyPlugin!.transform!(code, id);
329
-
330
- expect(result).toBeDefined();
331
- expect(result.code).not.toContain("import.meta");
267
+ const esbuildOpts = config.esbuild as Record<string, unknown> | undefined;
268
+ expect(esbuildOpts?.["supported"]).toEqual(
269
+ expect.objectContaining({
270
+ "import-meta": false,
271
+ "dynamic-import": false,
272
+ }),
273
+ );
332
274
  });
333
275
 
334
- // Acceptance: Scenario "import.meta가 없는 모듈은 변환하지 않는다"
335
- it("sd-legacy-import-meta plugin returns undefined for modules without import.meta", async () => {
336
- const config = await createClientViteConfig({
337
- ...createDefaultOptions(),
338
- legacyModule: true,
339
- });
340
-
341
- const plugins = config.plugins as Array<{ name: string; transform?: Function }>;
342
- const legacyPlugin = plugins.find((p) => p.name === "sd-legacy-import-meta");
343
-
344
- const code = 'const x = 1 + 2;';
345
- const id = "/packages/my-client/src/utils.ts";
346
- const result = legacyPlugin!.transform!(code, id);
276
+ // Acceptance: Scenario "legacyModule 미설정 esbuild.supported 변경 없음"
277
+ it("does not set esbuild.supported when legacyModule is not specified", async () => {
278
+ const config = await createClientViteConfig(createDefaultOptions());
347
279
 
348
- expect(result).toBeUndefined();
280
+ const esbuildOpts = config.esbuild as Record<string, unknown> | undefined;
281
+ expect(esbuildOpts?.["supported"]).toBeUndefined();
349
282
  });
350
283
 
351
284
  // --- PWA (Feature 5.2) ---
@@ -505,6 +438,127 @@ describe("createClientViteConfig", () => {
505
438
  );
506
439
  });
507
440
 
441
+ // --- watch option (Feature 1.2: legacy dev mode) ---
442
+
443
+ // Acceptance: Scenario "watch: true 시 build.watch 설정 및 emptyOutDir: false"
444
+ it("sets build.watch and emptyOutDir: false when watch is true in build mode", async () => {
445
+ const config = await createClientViteConfig({
446
+ ...createDefaultOptions(),
447
+ mode: "build",
448
+ watch: true,
449
+ });
450
+
451
+ expect(config.build?.watch).toEqual({});
452
+ expect(config.build?.emptyOutDir).toBe(false);
453
+ expect(config.logLevel).toBeUndefined();
454
+ });
455
+
456
+ // Acceptance: Scenario "watch: true + replaceDeps 시 sdScopeWatchPlugin 포함"
457
+ it("includes sdScopeWatchPlugin when watch is true with replaceDeps in build mode", async () => {
458
+ const { sdScopeWatchPlugin } = await import("../../src/utils/vite-scope-watch-plugin");
459
+
460
+ const config = await createClientViteConfig({
461
+ ...createDefaultOptions(),
462
+ mode: "build",
463
+ watch: true,
464
+ replaceDeps: [{ packageName: "@scope/core", sourcePath: "/packages/core" }],
465
+ });
466
+
467
+ const plugins = config.plugins as Array<{ name: string }>;
468
+ const scopePlugin = plugins.find((p) => p.name === "sd-scope-watch-plugin");
469
+ expect(scopePlugin).toBeDefined();
470
+ expect(sdScopeWatchPlugin).toHaveBeenCalled();
471
+ });
472
+
473
+ // Acceptance: Scenario "watch 미설정 시 기존 build 동작 유지"
474
+ it("sets emptyOutDir: true and logLevel: silent when watch is not set in build mode", async () => {
475
+ const config = await createClientViteConfig(createDefaultOptions());
476
+
477
+ expect(config.build?.emptyOutDir).toBe(true);
478
+ expect(config.logLevel).toBe("silent");
479
+ expect(config.build?.watch).toBeUndefined();
480
+ });
481
+
482
+ // Unit: watch: true without replaceDeps does not add sdScopeWatchPlugin
483
+ it("does not add sdScopeWatchPlugin in watch mode without replaceDeps", async () => {
484
+ const config = await createClientViteConfig({
485
+ ...createDefaultOptions(),
486
+ mode: "build",
487
+ watch: true,
488
+ });
489
+
490
+ const plugins = config.plugins as Array<{ name: string }>;
491
+ const scopePlugin = plugins.find((p) => p.name === "sd-scope-watch-plugin");
492
+ expect(scopePlugin).toBeUndefined();
493
+ });
494
+
495
+ // Unit: watch: true still sets outDir
496
+ it("sets outDir in watch mode", async () => {
497
+ const config = await createClientViteConfig({
498
+ ...createDefaultOptions(),
499
+ mode: "build",
500
+ watch: true,
501
+ });
502
+
503
+ expect(config.build?.outDir).toContain("my-client");
504
+ expect(config.build?.outDir).toMatch(/dist$/);
505
+ });
506
+
507
+ // --- exclude (Feature 1.1: vite-exclude-passthrough) ---
508
+
509
+ // Acceptance: Scenario "exclude에 패키지를 지정하면 pre-bundling에서 제외된다"
510
+ it("sets optimizeDeps.exclude when exclude is provided", async () => {
511
+ const config = await createClientViteConfig({
512
+ ...createDefaultOptions(),
513
+ mode: "dev",
514
+ exclude: ["jeep-sqlite"],
515
+ });
516
+
517
+ expect(config.optimizeDeps?.exclude).toEqual(["jeep-sqlite"]);
518
+ });
519
+
520
+ // Acceptance: Scenario "exclude 미설정 시 기존 동작과 동일하다"
521
+ it("does not set optimizeDeps.exclude when exclude is not provided", async () => {
522
+ const config = await createClientViteConfig({
523
+ ...createDefaultOptions(),
524
+ mode: "dev",
525
+ });
526
+
527
+ expect(config.optimizeDeps?.exclude).toBeUndefined();
528
+ });
529
+
530
+ // Acceptance: Scenario "exclude와 replaceDeps가 모두 있으면 둘 다 제외된다"
531
+ it("sets optimizeDeps.exclude from exclude while sdScopeWatchPlugin handles replaceDeps", async () => {
532
+ const { sdScopeWatchPlugin } = await import("../../src/utils/vite-scope-watch-plugin");
533
+
534
+ const config = await createClientViteConfig({
535
+ ...createDefaultOptions(),
536
+ mode: "dev",
537
+ exclude: ["jeep-sqlite"],
538
+ replaceDeps: [{ packageName: "@scope/core", sourcePath: "/packages/core" }],
539
+ });
540
+
541
+ // Base config에 exclude 설정
542
+ expect(config.optimizeDeps?.exclude).toEqual(["jeep-sqlite"]);
543
+ // sdScopeWatchPlugin도 호출됨 (replaceDeps용 exclude는 plugin이 처리)
544
+ expect(sdScopeWatchPlugin).toHaveBeenCalled();
545
+ });
546
+
547
+ // Acceptance: Scenario "exclude만 있고 replaceDeps가 없으면 exclude만 제외된다"
548
+ it("sets optimizeDeps.exclude from exclude when no replaceDeps", async () => {
549
+ const config = await createClientViteConfig({
550
+ ...createDefaultOptions(),
551
+ mode: "dev",
552
+ exclude: ["jeep-sqlite"],
553
+ });
554
+
555
+ expect(config.optimizeDeps?.exclude).toEqual(["jeep-sqlite"]);
556
+ // sdScopeWatchPlugin은 호출되지 않음
557
+ const plugins = config.plugins as Array<{ name: string }>;
558
+ const scopePlugin = plugins.find((p) => p.name === "sd-scope-watch-plugin");
559
+ expect(scopePlugin).toBeUndefined();
560
+ });
561
+
508
562
  // Acceptance: Scenario "pwa 필드 미설정 시 기본값"
509
563
  it("uses default manifest values from pkgName when pwa is undefined", async () => {
510
564
  await createClientViteConfig(createDefaultOptions());