@simplysm/sd-cli 14.0.64 → 14.0.65

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 (79) hide show
  1. package/dist/capacitor/capacitor-android.d.ts +2 -0
  2. package/dist/capacitor/capacitor-android.d.ts.map +1 -1
  3. package/dist/capacitor/capacitor-android.js +13 -0
  4. package/dist/capacitor/capacitor-android.js.map +1 -1
  5. package/dist/capacitor/capacitor-npm-config.d.ts.map +1 -1
  6. package/dist/capacitor/capacitor-npm-config.js +2 -6
  7. package/dist/capacitor/capacitor-npm-config.js.map +1 -1
  8. package/dist/electron/electron.d.ts.map +1 -1
  9. package/dist/electron/electron.js +1 -2
  10. package/dist/electron/electron.js.map +1 -1
  11. package/package.json +8 -8
  12. package/src/capacitor/capacitor-android.ts +14 -0
  13. package/src/capacitor/capacitor-npm-config.ts +2 -6
  14. package/src/electron/electron.ts +1 -2
  15. package/tests/angular/ngtsc-build-core.acc.spec.ts +36 -94
  16. package/tests/capacitor/capacitor-android.spec.ts +65 -28
  17. package/tests/capacitor/capacitor-build.spec.ts +40 -385
  18. package/tests/capacitor/capacitor-config-writer.acc.spec.ts +3 -17
  19. package/tests/capacitor/capacitor-config-writer.spec.ts +3 -17
  20. package/tests/capacitor/capacitor-init.spec.ts +40 -636
  21. package/tests/capacitor/capacitor-npm-config.acc.spec.ts +38 -168
  22. package/tests/capacitor/capacitor-npm-config.spec.ts +33 -71
  23. package/tests/commands/check.spec.ts +25 -36
  24. package/tests/commands/deployment-phase.acc.spec.ts +17 -26
  25. package/tests/commands/git-phase.acc.spec.ts +13 -112
  26. package/tests/commands/lint.spec.ts +7 -24
  27. package/tests/commands/post-publish-phase.acc.spec.ts +5 -10
  28. package/tests/commands/typecheck.spec.ts +43 -65
  29. package/tests/electron/electron.spec.ts +22 -46
  30. package/tests/engines/base-engine.spec.ts +4 -13
  31. package/tests/engines/engine-selection.spec.ts +14 -17
  32. package/tests/engines/engine-typecheck-selection.acc.spec.ts +13 -16
  33. package/tests/engines/esbuild-client-engine.acc.spec.ts +36 -40
  34. package/tests/engines/esbuild-client-engine.spec.ts +4 -23
  35. package/tests/engines/ngtsc-engine.spec.ts +3 -10
  36. package/tests/engines/server-esbuild-engine.spec.ts +3 -10
  37. package/tests/engines/tsc-engine.spec.ts +3 -10
  38. package/tests/esbuild/esbuild-tsc-plugin.acc.spec.ts +3 -8
  39. package/tests/esbuild/esbuild-tsc-plugin.spec.ts +3 -8
  40. package/tests/orchestrators/build-orchestrator.spec.ts +57 -102
  41. package/tests/orchestrators/dev-orchestrator.spec.ts +68 -109
  42. package/tests/orchestrators/typecheck-orchestrator.spec.ts +25 -57
  43. package/tests/orchestrators/watch-orchestrator.spec.ts +73 -99
  44. package/tests/sd-cli-entry.spec.ts +17 -20
  45. package/tests/utils/angular-source-file-cache.spec.ts +4 -8
  46. package/tests/utils/copy-src.spec.ts +9 -20
  47. package/tests/utils/esbuild-client-config.acc.spec.ts +9 -15
  48. package/tests/utils/esbuild-client-config.spec.ts +12 -24
  49. package/tests/utils/esbuild-config.spec.ts +51 -42
  50. package/tests/utils/lint-core.spec.ts +13 -19
  51. package/tests/utils/lint-utils.spec.ts +8 -15
  52. package/tests/utils/lint-with-program.spec.ts +3 -7
  53. package/tests/utils/ngtsc-build-core.spec.ts +2 -99
  54. package/tests/utils/orchestrator-utils.spec.ts +7 -20
  55. package/tests/utils/output-utils.spec.ts +5 -11
  56. package/tests/utils/sd-config.spec.ts +4 -12
  57. package/tests/utils/typecheck-env.spec.ts +49 -77
  58. package/tests/utils/typecheck-non-package.spec.ts +23 -16
  59. package/tests/workers/build-watch-paths.acc.spec.ts +4 -10
  60. package/tests/workers/build-watch-paths.spec.ts +4 -9
  61. package/tests/workers/client-worker.acc.spec.ts +64 -137
  62. package/tests/workers/client-worker.spec.ts +63 -89
  63. package/tests/workers/library-build-lint.spec.ts +19 -30
  64. package/tests/workers/library-build-worker.spec.ts +28 -55
  65. package/tests/workers/server-esbuild-context.acc.spec.ts +6 -15
  66. package/tests/workers/server-esbuild-context.spec.ts +7 -16
  67. package/tests/workers/server-runtime-worker.spec.ts +8 -10
  68. package/tests/workers/shared-worker-lifecycle.acc.spec.ts +3 -5
  69. package/tests/workers/shared-worker-lifecycle.spec.ts +4 -5
  70. package/tests/capacitor/capacitor-icon.spec.ts +0 -285
  71. package/tests/capacitor/capacitor-run.spec.ts +0 -256
  72. package/tests/capacitor/capacitor-workspace.spec.ts +0 -203
  73. package/tests/commands/device.spec.ts +0 -237
  74. package/tests/commands/publish.spec.ts +0 -1183
  75. package/tests/utils/external-modules.spec.ts +0 -217
  76. package/tests/workers/server-build-lint.spec.ts +0 -201
  77. package/tests/workers/server-build-worker.spec.ts +0 -765
  78. package/tests/workers/server-watch-manager.acc.spec.ts +0 -162
  79. package/tests/workers/server-watch-manager.spec.ts +0 -199
@@ -1,162 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from "vitest";
2
- import type { ConsolaInstance } from "consola";
3
-
4
- //#region Mocks
5
-
6
- const mockWatcherOnChange = vi.fn();
7
- const mockWatcherClose = vi.fn();
8
-
9
- vi.mock("@simplysm/core-node", () => ({
10
- FsWatcher: {
11
- watch: vi.fn(() =>
12
- Promise.resolve({ onChange: mockWatcherOnChange, close: mockWatcherClose }),
13
- ),
14
- },
15
- pathx: {
16
- posix: vi.fn((p: string) => p.replace(/\\/g, "/")),
17
- posixResolve: vi.fn((...args: string[]) => {
18
- // Simple path join for testing
19
- return args.join("/").replace(/\/+/g, "/");
20
- }),
21
- },
22
- }));
23
-
24
- vi.mock("fs", () => ({
25
- default: {
26
- realpathSync: vi.fn((p: string) => p),
27
- },
28
- }));
29
-
30
- vi.mock("../../src/workers/server-esbuild-context", () => ({
31
- hasContext: vi.fn(() => true),
32
- getMetafile: vi.fn(() => undefined),
33
- recreateContext: vi.fn(() => Promise.resolve()),
34
- }));
35
-
36
- vi.mock("../../src/workers/build-change-filter", async (importOriginal) => {
37
- const actual = await importOriginal<typeof import("../../src/workers/build-change-filter")>();
38
- return actual;
39
- });
40
-
41
- vi.mock("../../src/utils/tsconfig", () => ({
42
- parseTsconfig: vi.fn(() => ({
43
- options: { target: 1, module: 99 },
44
- fileNames: ["/workspace/packages/my-server/src/main.ts"],
45
- errors: [],
46
- })),
47
- getPackageSourceFiles: vi.fn(() => ["/workspace/packages/my-server/src/main.ts"]),
48
- }));
49
-
50
- vi.mock("../../src/deps/server-externals/server-production-files", () => ({
51
- collectAllExternals: vi.fn(() => ({ bundleExternals: [], prodDependencies: [] })),
52
- }));
53
-
54
- //#endregion
55
-
56
- const { FsWatcher } = await import("@simplysm/core-node");
57
- const esbuildCtx = await import("../../src/workers/server-esbuild-context");
58
- const { collectAllExternals } = await import("../../src/deps/server-externals/server-production-files");
59
- const { startServerWatchLoop } = await import("../../src/workers/server-watch-manager");
60
-
61
- const mockLogger = { debug: vi.fn(), warn: vi.fn() } as unknown as ConsolaInstance;
62
-
63
- function createConfig(overrides?: Partial<Parameters<typeof startServerWatchLoop>[0]>) {
64
- return {
65
- info: {
66
- name: "my-server",
67
- cwd: "/workspace",
68
- pkgDir: "/workspace/packages/my-server",
69
- output: { js: true, dts: false },
70
- externals: undefined as string[] | undefined,
71
- },
72
- watchPaths: ["/workspace/packages/my-server/src/**/*"],
73
- logger: mockLogger,
74
- initialExternals: [],
75
- onBuildStart: vi.fn(),
76
- onBuild: vi.fn(),
77
- onError: vi.fn(),
78
- rebuild: vi.fn(() =>
79
- Promise.resolve({
80
- build: { success: true },
81
- mainJsPath: "/workspace/packages/my-server/dist/main.js",
82
- }),
83
- ),
84
- ...overrides,
85
- };
86
- }
87
-
88
- describe("startServerWatchLoop", () => {
89
- beforeEach(() => {
90
- mockWatcherOnChange.mockClear();
91
- mockWatcherClose.mockClear();
92
- vi.mocked(FsWatcher.watch).mockClear();
93
- vi.mocked(esbuildCtx.hasContext).mockReturnValue(true);
94
- vi.mocked(esbuildCtx.getMetafile).mockReturnValue(undefined);
95
- vi.mocked(esbuildCtx.recreateContext).mockResolvedValue();
96
- vi.mocked(collectAllExternals).mockReturnValue({ bundleExternals: [], prodDependencies: [] });
97
- (mockLogger.debug as unknown as ReturnType<typeof vi.fn>).mockClear();
98
- });
99
-
100
- // Acceptance: 파일 추가 시 context 재생성 + 리빌드
101
- it("recreates esbuild context and triggers rebuild on file add", async () => {
102
- const config = createConfig();
103
- await startServerWatchLoop(config);
104
-
105
- // onChange 핸들러 추출
106
- const onChangeHandler = mockWatcherOnChange.mock.calls[0][1] as (
107
- changes: Array<{ event: string; path: string }>,
108
- ) => Promise<void>;
109
-
110
- await onChangeHandler([
111
- { event: "add", path: "/workspace/packages/my-server/src/new.ts" },
112
- ]);
113
-
114
- expect(config.onBuildStart).toHaveBeenCalledOnce();
115
- expect(esbuildCtx.recreateContext).toHaveBeenCalled();
116
- expect(config.rebuild).toHaveBeenCalledOnce();
117
- expect(config.onBuild).toHaveBeenCalledOnce();
118
- });
119
-
120
- // Acceptance: metafile 기반 필터링으로 불필요한 리빌드 건너뜀
121
- it("skips rebuild when changed file is not in metafile.inputs", async () => {
122
- vi.mocked(esbuildCtx.getMetafile).mockReturnValue({
123
- inputs: { "packages/my-server/src/main.ts": {} as any },
124
- outputs: {},
125
- });
126
-
127
- const config = createConfig();
128
- await startServerWatchLoop(config);
129
-
130
- const onChangeHandler = mockWatcherOnChange.mock.calls[0][1] as (
131
- changes: Array<{ event: string; path: string }>,
132
- ) => Promise<void>;
133
-
134
- await onChangeHandler([
135
- { event: "change", path: "/workspace/packages/my-server/src/unrelated.ts" },
136
- ]);
137
-
138
- expect(config.onBuildStart).not.toHaveBeenCalled();
139
- expect(config.rebuild).not.toHaveBeenCalled();
140
- });
141
-
142
- // Acceptance: onChange 에러 시 onError 콜백 호출
143
- it("calls onError when onChange handler throws", async () => {
144
- const config = createConfig({
145
- rebuild: vi.fn().mockRejectedValue(new Error("rebuild failed")),
146
- });
147
-
148
- vi.mocked(esbuildCtx.hasContext).mockReturnValue(false);
149
-
150
- await startServerWatchLoop(config);
151
-
152
- const onChangeHandler = mockWatcherOnChange.mock.calls[0][1] as (
153
- changes: Array<{ event: string; path: string }>,
154
- ) => Promise<void>;
155
-
156
- await onChangeHandler([
157
- { event: "change", path: "/workspace/packages/my-server/src/main.ts" },
158
- ]);
159
-
160
- expect(config.onError).toHaveBeenCalledWith("rebuild failed");
161
- });
162
- });
@@ -1,199 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from "vitest";
2
- import type { ConsolaInstance } from "consola";
3
-
4
- //#region Mocks
5
-
6
- const mockWatcherOnChange = vi.fn();
7
- const mockWatcherClose = vi.fn();
8
-
9
- vi.mock("@simplysm/core-node", () => ({
10
- FsWatcher: {
11
- watch: vi.fn(() =>
12
- Promise.resolve({ onChange: mockWatcherOnChange, close: mockWatcherClose }),
13
- ),
14
- },
15
- pathx: {
16
- posix: vi.fn((p: string) => p.replace(/\\/g, "/")),
17
- posixResolve: vi.fn((...args: string[]) => args.join("/").replace(/\/+/g, "/")),
18
- },
19
- }));
20
-
21
- vi.mock("fs", () => ({
22
- default: {
23
- realpathSync: vi.fn((p: string) => p),
24
- },
25
- }));
26
-
27
- vi.mock("../../src/workers/server-esbuild-context", () => ({
28
- hasContext: vi.fn(() => true),
29
- getMetafile: vi.fn(() => undefined),
30
- recreateContext: vi.fn(() => Promise.resolve()),
31
- }));
32
-
33
- vi.mock("../../src/workers/build-change-filter", async (importOriginal) => {
34
- const actual = await importOriginal<typeof import("../../src/workers/build-change-filter")>();
35
- return actual;
36
- });
37
-
38
- vi.mock("../../src/utils/tsconfig", () => ({
39
- parseTsconfig: vi.fn(() => ({
40
- options: {},
41
- fileNames: ["/workspace/packages/my-server/src/main.ts"],
42
- errors: [],
43
- })),
44
- getPackageSourceFiles: vi.fn(() => ["/workspace/packages/my-server/src/main.ts"]),
45
- }));
46
-
47
- vi.mock("../../src/deps/server-externals/server-production-files", () => ({
48
- collectAllExternals: vi.fn(() => ({ bundleExternals: [], prodDependencies: [] })),
49
- }));
50
-
51
- //#endregion
52
-
53
- const { FsWatcher } = await import("@simplysm/core-node");
54
- const esbuildCtx = await import("../../src/workers/server-esbuild-context");
55
- const { collectAllExternals } = await import("../../src/deps/server-externals/server-production-files");
56
- const { startServerWatchLoop } = await import("../../src/workers/server-watch-manager");
57
-
58
- const mockLogger = { debug: vi.fn(), warn: vi.fn() } as unknown as ConsolaInstance;
59
-
60
- function createConfig(overrides?: Record<string, unknown>) {
61
- return {
62
- info: {
63
- name: "my-server",
64
- cwd: "/workspace",
65
- pkgDir: "/workspace/packages/my-server",
66
- output: { js: true, dts: false },
67
- externals: undefined as string[] | undefined,
68
- },
69
- watchPaths: ["/workspace/packages/my-server/src/**/*"],
70
- logger: mockLogger,
71
- initialExternals: [],
72
- onBuildStart: vi.fn(),
73
- onBuild: vi.fn(),
74
- onError: vi.fn(),
75
- rebuild: vi.fn(() =>
76
- Promise.resolve({
77
- build: { success: true },
78
- mainJsPath: "/workspace/packages/my-server/dist/main.js",
79
- }),
80
- ),
81
- ...overrides,
82
- };
83
- }
84
-
85
- describe("startServerWatchLoop", () => {
86
- beforeEach(() => {
87
- mockWatcherOnChange.mockClear();
88
- vi.mocked(FsWatcher.watch).mockClear();
89
- vi.mocked(esbuildCtx.hasContext).mockReset().mockReturnValue(true);
90
- vi.mocked(esbuildCtx.getMetafile).mockReset().mockReturnValue(undefined);
91
- vi.mocked(esbuildCtx.recreateContext).mockReset().mockResolvedValue();
92
- vi.mocked(collectAllExternals).mockReset().mockReturnValue({ bundleExternals: [], prodDependencies: [] });
93
- (mockLogger.debug as unknown as ReturnType<typeof vi.fn>).mockClear();
94
- });
95
-
96
- it("creates FsWatcher and registers onChange with 300ms delay", async () => {
97
- const config = createConfig();
98
- await startServerWatchLoop(config);
99
-
100
- expect(FsWatcher.watch).toHaveBeenCalledWith(config.watchPaths);
101
- expect(mockWatcherOnChange).toHaveBeenCalledWith(
102
- { delay: 300 },
103
- expect.any(Function),
104
- );
105
- });
106
-
107
- it("returns FsWatcher instance", async () => {
108
- const config = createConfig();
109
- const watcher = await startServerWatchLoop(config);
110
-
111
- expect(watcher).toBeDefined();
112
- expect(watcher.onChange).toBeDefined();
113
- });
114
-
115
- describe("onChange: file add/remove", () => {
116
- it("recreates context when output.js is true", async () => {
117
- const config = createConfig();
118
- await startServerWatchLoop(config);
119
-
120
- const handler = mockWatcherOnChange.mock.calls[0][1] as Function;
121
- await handler([{ event: "add", path: "/workspace/packages/my-server/src/new.ts" }]);
122
-
123
- expect(esbuildCtx.recreateContext).toHaveBeenCalled();
124
- });
125
-
126
- it("skips context recreation when output.js is false", async () => {
127
- const config = createConfig({
128
- info: {
129
- name: "my-server",
130
- cwd: "/workspace",
131
- pkgDir: "/workspace/packages/my-server",
132
- output: { js: false, dts: true },
133
- },
134
- });
135
- await startServerWatchLoop(config);
136
-
137
- const handler = mockWatcherOnChange.mock.calls[0][1] as Function;
138
- await handler([{ event: "add", path: "/workspace/packages/my-server/src/new.ts" }]);
139
-
140
- expect(esbuildCtx.recreateContext).not.toHaveBeenCalled();
141
- expect(config.rebuild).toHaveBeenCalled();
142
- });
143
-
144
- it("re-collects externals when package.json changed", async () => {
145
- const config = createConfig();
146
- await startServerWatchLoop(config);
147
-
148
- const handler = mockWatcherOnChange.mock.calls[0][1] as Function;
149
- await handler([
150
- { event: "add", path: "/workspace/packages/my-server/package.json" },
151
- ]);
152
-
153
- expect(collectAllExternals).toHaveBeenCalled();
154
- });
155
- });
156
-
157
- describe("onChange: file change (metafile filtering)", () => {
158
- it("rebuilds unconditionally when no context exists", async () => {
159
- vi.mocked(esbuildCtx.hasContext).mockReturnValue(false);
160
- const config = createConfig();
161
- await startServerWatchLoop(config);
162
-
163
- const handler = mockWatcherOnChange.mock.calls[0][1] as Function;
164
- await handler([{ event: "change", path: "/workspace/packages/my-server/src/main.ts" }]);
165
-
166
- expect(config.onBuildStart).toHaveBeenCalled();
167
- expect(config.rebuild).toHaveBeenCalled();
168
- });
169
-
170
- it("rebuilds unconditionally when metafile is not available", async () => {
171
- vi.mocked(esbuildCtx.getMetafile).mockReturnValue(undefined);
172
- const config = createConfig();
173
- await startServerWatchLoop(config);
174
-
175
- const handler = mockWatcherOnChange.mock.calls[0][1] as Function;
176
- await handler([{ event: "change", path: "/workspace/packages/my-server/src/main.ts" }]);
177
-
178
- expect(config.rebuild).toHaveBeenCalled();
179
- });
180
-
181
- it("rebuilds when changed file is in metafile.inputs", async () => {
182
- vi.mocked(esbuildCtx.getMetafile).mockReturnValue({
183
- inputs: { "packages/my-server/src/main.ts": {} as any },
184
- outputs: {},
185
- });
186
- const config = createConfig();
187
- await startServerWatchLoop(config);
188
-
189
- const handler = mockWatcherOnChange.mock.calls[0][1] as Function;
190
- // pathx.posixResolve("/workspace", "packages/my-server/src/main.ts")
191
- // → "/workspace/packages/my-server/src/main.ts"
192
- await handler([
193
- { event: "change", path: "/workspace/packages/my-server/src/main.ts" },
194
- ]);
195
-
196
- expect(config.rebuild).toHaveBeenCalled();
197
- });
198
- });
199
- });