@simplysm/sd-cli 14.0.17 → 14.0.19

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 (49) hide show
  1. package/dist/angular/vite-angular-plugin.d.ts +2 -0
  2. package/dist/angular/vite-angular-plugin.d.ts.map +1 -1
  3. package/dist/angular/vite-angular-plugin.js +57 -28
  4. package/dist/angular/vite-angular-plugin.js.map +1 -1
  5. package/dist/capacitor/capacitor.d.ts +0 -1
  6. package/dist/capacitor/capacitor.d.ts.map +1 -1
  7. package/dist/capacitor/capacitor.js +12 -37
  8. package/dist/capacitor/capacitor.js.map +1 -1
  9. package/dist/commands/device.d.ts.map +1 -1
  10. package/dist/commands/device.js +3 -2
  11. package/dist/commands/device.js.map +1 -1
  12. package/dist/electron/electron.d.ts.map +1 -1
  13. package/dist/electron/electron.js +9 -4
  14. package/dist/electron/electron.js.map +1 -1
  15. package/dist/orchestrators/DevWatchOrchestrator.d.ts.map +1 -1
  16. package/dist/orchestrators/DevWatchOrchestrator.js +12 -0
  17. package/dist/orchestrators/DevWatchOrchestrator.js.map +1 -1
  18. package/dist/utils/vite-config.d.ts +1 -1
  19. package/dist/utils/vite-config.d.ts.map +1 -1
  20. package/dist/utils/vite-config.js +76 -26
  21. package/dist/utils/vite-config.js.map +1 -1
  22. package/dist/utils/vite-scope-watch-plugin.d.ts.map +1 -1
  23. package/dist/utils/vite-scope-watch-plugin.js +7 -1
  24. package/dist/utils/vite-scope-watch-plugin.js.map +1 -1
  25. package/dist/workers/server-runtime.worker.d.ts.map +1 -1
  26. package/dist/workers/server-runtime.worker.js +15 -0
  27. package/dist/workers/server-runtime.worker.js.map +1 -1
  28. package/package.json +9 -7
  29. package/src/angular/vite-angular-plugin.ts +88 -34
  30. package/src/capacitor/capacitor.ts +14 -46
  31. package/src/commands/device.ts +3 -2
  32. package/src/electron/electron.ts +11 -4
  33. package/src/orchestrators/DevWatchOrchestrator.ts +14 -0
  34. package/src/utils/vite-config.ts +83 -27
  35. package/src/utils/vite-scope-watch-plugin.ts +6 -1
  36. package/src/workers/server-runtime.worker.ts +15 -0
  37. package/tests/angular/linker-disk-cache.spec.ts +31 -25
  38. package/tests/angular/vite-angular-plugin-hmr-fallback.spec.ts +15 -15
  39. package/tests/angular/vite-angular-plugin-hmr.spec.ts +9 -9
  40. package/tests/angular/vite-angular-plugin-legacy-watch.spec.ts +108 -0
  41. package/tests/angular/vite-angular-plugin-lint.spec.ts +4 -4
  42. package/tests/angular/vite-angular-plugin-scss-hmr.spec.ts +10 -15
  43. package/tests/angular/vite-angular-plugin.spec.ts +80 -15
  44. package/tests/capacitor/capacitor-workspace.spec.ts +22 -12
  45. package/tests/commands/device.spec.ts +12 -7
  46. package/tests/electron/electron.spec.ts +27 -2
  47. package/tests/utils/vite-config.spec.ts +255 -133
  48. package/tests/utils/vite-scope-watch-plugin.spec.ts +22 -0
  49. package/tests/workers/server-runtime-worker.spec.ts +48 -4
@@ -16,6 +16,7 @@ vi.mock("@simplysm/core-node", () => ({
16
16
  vi.mock("fs", () => ({
17
17
  default: {
18
18
  existsSync: vi.fn(() => true),
19
+ realpathSync: vi.fn((p: string) => p.replace("/symlink/", "/real/")),
19
20
  },
20
21
  }));
21
22
 
@@ -133,6 +134,27 @@ describe("sdScopeWatchPlugin", () => {
133
134
  expect(FsWatcher.watch).not.toHaveBeenCalled();
134
135
  });
135
136
 
137
+ // Scenario: symlink 경로를 realpath로 해결하여 감시한다
138
+ it("resolves symlink paths to realpath for watch directories", async () => {
139
+ const plugin = sdScopeWatchPlugin({
140
+ pkgDir: "/packages/my-client",
141
+ replaceDeps: [
142
+ { packageName: "@scope/core", sourcePath: "/packages/core" },
143
+ ],
144
+ });
145
+
146
+ const mockServer = {
147
+ watcher: { emit: vi.fn() },
148
+ httpServer: { on: vi.fn() },
149
+ };
150
+
151
+ await (plugin as any).configureServer?.(mockServer);
152
+
153
+ // fs.realpathSync가 dist 경로에 대해 호출되었는지 확인
154
+ const fsModule = (await import("fs")).default;
155
+ expect(fsModule.realpathSync).toHaveBeenCalled();
156
+ });
157
+
136
158
  // Unit: server close cleans up watcher
137
159
  it("registers cleanup on server httpServer close", async () => {
138
160
  const plugin = sdScopeWatchPlugin({
@@ -1,4 +1,5 @@
1
1
  import { describe, it, expect, vi, beforeEach, afterEach, beforeAll, afterAll } from "vitest";
2
+ import fs from "fs";
2
3
  import path from "path";
3
4
  import os from "os";
4
5
  import fsp from "fs/promises";
@@ -82,8 +83,9 @@ vi.mock("net", () => ({
82
83
  // Import triggers createWorker
83
84
  await import("../../src/workers/server-runtime.worker");
84
85
 
85
- // Create a temp mock main.js that exports globalThis.__sdCliTestServer
86
- const mockMainJsPath = path.join(os.tmpdir(), `sd-cli-test-main-${Date.now()}.mjs`);
86
+ // Create a temp directory with mock main.js that exports globalThis.__sdCliTestServer
87
+ const mockMainDir = path.join(os.tmpdir(), `sd-cli-test-server-${Date.now()}`);
88
+ const mockMainJsPath = path.join(mockMainDir, "main.mjs");
87
89
 
88
90
  const mockRegister = vi.fn().mockResolvedValue(undefined);
89
91
 
@@ -96,6 +98,7 @@ const mockServer = {
96
98
 
97
99
  beforeAll(async () => {
98
100
  (globalThis as any).__sdCliTestServer = mockServer;
101
+ await fsp.mkdir(mockMainDir, { recursive: true });
99
102
  await fsp.writeFile(
100
103
  mockMainJsPath,
101
104
  "export const server = globalThis.__sdCliTestServer;\n",
@@ -103,7 +106,7 @@ beforeAll(async () => {
103
106
  });
104
107
 
105
108
  afterAll(async () => {
106
- await fsp.unlink(mockMainJsPath).catch(() => {});
109
+ await fsp.rm(mockMainDir, { recursive: true, force: true }).catch(() => {});
107
110
  delete (globalThis as any).__sdCliTestServer;
108
111
  });
109
112
 
@@ -152,7 +155,7 @@ describe("server-runtime.worker start", () => {
152
155
  portCheckIndex = 0;
153
156
  });
154
157
 
155
- afterEach(() => {
158
+ afterEach(async () => {
156
159
  // Restore modified env vars
157
160
  for (const [key, value] of Object.entries(savedEnv)) {
158
161
  if (value === undefined) {
@@ -161,6 +164,8 @@ describe("server-runtime.worker start", () => {
161
164
  process.env[key] = value;
162
165
  }
163
166
  }
167
+ // .dev-port 정리
168
+ await fsp.unlink(path.join(mockMainDir, ".dev-port")).catch(() => {});
164
169
  });
165
170
 
166
171
  function trackEnv(key: string): void {
@@ -268,6 +273,45 @@ describe("server-runtime.worker start", () => {
268
273
  expect(mockRegister).not.toHaveBeenCalled();
269
274
  });
270
275
 
276
+ // Acceptance: Scenario "서버 listen 완료 후 .dev-port 기록"
277
+ it("writes .dev-port file with server port after listen", async () => {
278
+ portCheckResults = [true];
279
+ mockServer.options.port = 3000;
280
+
281
+ await workerFns["start"]({ mainJsPath: mockMainJsPath });
282
+
283
+ const portFile = path.join(mockMainDir, ".dev-port");
284
+ const content = await fsp.readFile(portFile, "utf-8");
285
+ expect(content).toBe("3000");
286
+ });
287
+
288
+ // Unit: 포트 충돌로 다른 포트 사용 시 실제 포트 기록
289
+ it("writes actual port to .dev-port when port auto-incremented", async () => {
290
+ portCheckResults = [false, false, true]; // 3000, 3001 taken, 3002 available
291
+ mockServer.options.port = 3000;
292
+
293
+ await workerFns["start"]({ mainJsPath: mockMainJsPath });
294
+
295
+ const portFile = path.join(mockMainDir, ".dev-port");
296
+ const content = await fsp.readFile(portFile, "utf-8");
297
+ expect(content).toBe("3002");
298
+ });
299
+
300
+ // Unit: cleanup 시 .dev-port 삭제
301
+ it("removes .dev-port file during cleanup", async () => {
302
+ portCheckResults = [true];
303
+ await workerFns["start"]({ mainJsPath: mockMainJsPath });
304
+
305
+ const portFile = path.join(mockMainDir, ".dev-port");
306
+ expect(fs.existsSync(portFile)).toBe(true);
307
+
308
+ const { registerCleanupHandlers } = await import("../../src/utils/worker-utils");
309
+ const cleanupFn = vi.mocked(registerCleanupHandlers).mock.calls[0][0];
310
+ await cleanupFn();
311
+
312
+ expect(fs.existsSync(portFile)).toBe(false);
313
+ });
314
+
271
315
  it("sends error event when main.js does not export server", async () => {
272
316
  // Create a temp file without server export
273
317
  const noServerPath = path.join(os.tmpdir(), `sd-cli-test-no-server-${Date.now()}.mjs`);