@simplysm/sd-cli 14.1.9 → 14.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. package/dist/capacitor/capacitor-icon.js +2 -2
  2. package/dist/capacitor/capacitor-icon.js.map +1 -1
  3. package/dist/capacitor/capacitor-npm-config.d.ts +1 -1
  4. package/dist/capacitor/capacitor-npm-config.d.ts.map +1 -1
  5. package/dist/capacitor/capacitor-npm-config.js +11 -18
  6. package/dist/capacitor/capacitor-npm-config.js.map +1 -1
  7. package/dist/capacitor/capacitor.d.ts +1 -1
  8. package/dist/capacitor/capacitor.js +2 -2
  9. package/dist/capacitor/capacitor.js.map +1 -1
  10. package/dist/commands/check.d.ts.map +1 -1
  11. package/dist/commands/check.js +1 -0
  12. package/dist/commands/check.js.map +1 -1
  13. package/dist/commands/device.js +2 -2
  14. package/dist/commands/device.js.map +1 -1
  15. package/dist/commands/init/generators/root.d.ts.map +1 -1
  16. package/dist/commands/init/generators/root.js +0 -1
  17. package/dist/commands/init/generators/root.js.map +1 -1
  18. package/dist/commands/init/init-client.js +1 -1
  19. package/dist/commands/init/init-client.js.map +1 -1
  20. package/dist/commands/init/init.js +2 -2
  21. package/dist/commands/init/init.js.map +1 -1
  22. package/dist/commands/publish/deployment-phase.d.ts.map +1 -1
  23. package/dist/commands/publish/deployment-phase.js +1 -0
  24. package/dist/commands/publish/deployment-phase.js.map +1 -1
  25. package/dist/commands/publish/npm-publisher.js +3 -3
  26. package/dist/commands/publish/npm-publisher.js.map +1 -1
  27. package/dist/commands/publish/post-publish-phase.d.ts.map +1 -1
  28. package/dist/commands/publish/post-publish-phase.js +1 -0
  29. package/dist/commands/publish/post-publish-phase.js.map +1 -1
  30. package/dist/commands/publish/publish-command.d.ts.map +1 -1
  31. package/dist/commands/publish/publish-command.js +7 -12
  32. package/dist/commands/publish/publish-command.js.map +1 -1
  33. package/dist/deps/replace-deps/collect-deps.js +4 -4
  34. package/dist/deps/replace-deps/collect-deps.js.map +1 -1
  35. package/dist/deps/replace-deps/replace-deps-resolve.d.ts +4 -12
  36. package/dist/deps/replace-deps/replace-deps-resolve.d.ts.map +1 -1
  37. package/dist/deps/replace-deps/replace-deps-resolve.js +13 -49
  38. package/dist/deps/replace-deps/replace-deps-resolve.js.map +1 -1
  39. package/dist/deps/replace-deps/replace-deps.d.ts +2 -2
  40. package/dist/deps/replace-deps/replace-deps.js +3 -3
  41. package/dist/deps/server-externals/server-production-files.d.ts +3 -3
  42. package/dist/deps/server-externals/server-production-files.d.ts.map +1 -1
  43. package/dist/deps/server-externals/server-production-files.js +24 -17
  44. package/dist/deps/server-externals/server-production-files.js.map +1 -1
  45. package/dist/electron/electron.d.ts.map +1 -1
  46. package/dist/electron/electron.js +6 -11
  47. package/dist/electron/electron.js.map +1 -1
  48. package/dist/engines/BaseEngine.d.ts +1 -0
  49. package/dist/engines/BaseEngine.d.ts.map +1 -1
  50. package/dist/engines/BaseEngine.js +2 -1
  51. package/dist/engines/BaseEngine.js.map +1 -1
  52. package/dist/esbuild/esbuild-config.d.ts +6 -2
  53. package/dist/esbuild/esbuild-config.d.ts.map +1 -1
  54. package/dist/esbuild/esbuild-config.js +4 -3
  55. package/dist/esbuild/esbuild-config.js.map +1 -1
  56. package/dist/esbuild/esbuild-tsc-plugin.d.ts.map +1 -1
  57. package/dist/esbuild/esbuild-tsc-plugin.js +3 -1
  58. package/dist/esbuild/esbuild-tsc-plugin.js.map +1 -1
  59. package/dist/orchestrators/BaseOrchestrator.d.ts.map +1 -1
  60. package/dist/orchestrators/BaseOrchestrator.js +1 -0
  61. package/dist/orchestrators/BaseOrchestrator.js.map +1 -1
  62. package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
  63. package/dist/orchestrators/BuildOrchestrator.js +3 -5
  64. package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
  65. package/dist/orchestrators/DevOrchestrator.d.ts.map +1 -1
  66. package/dist/orchestrators/DevOrchestrator.js +1 -0
  67. package/dist/orchestrators/DevOrchestrator.js.map +1 -1
  68. package/dist/orchestrators/ServerRuntimeManager.d.ts.map +1 -1
  69. package/dist/orchestrators/ServerRuntimeManager.js +4 -0
  70. package/dist/orchestrators/ServerRuntimeManager.js.map +1 -1
  71. package/dist/orchestrators/TypecheckOrchestrator.d.ts.map +1 -1
  72. package/dist/orchestrators/TypecheckOrchestrator.js +4 -6
  73. package/dist/orchestrators/TypecheckOrchestrator.js.map +1 -1
  74. package/dist/runtime/engine-watch-events.d.ts.map +1 -1
  75. package/dist/runtime/engine-watch-events.js +5 -0
  76. package/dist/runtime/engine-watch-events.js.map +1 -1
  77. package/dist/runtime/worker-events.d.ts +1 -0
  78. package/dist/runtime/worker-events.d.ts.map +1 -1
  79. package/dist/sd-cli-entry.d.ts.map +1 -1
  80. package/dist/sd-cli-entry.js +0 -4
  81. package/dist/sd-cli-entry.js.map +1 -1
  82. package/dist/sd-cli.js +2 -0
  83. package/dist/sd-cli.js.map +1 -1
  84. package/dist/typecheck/typecheck-non-package.d.ts.map +1 -1
  85. package/dist/typecheck/typecheck-non-package.js +10 -0
  86. package/dist/typecheck/typecheck-non-package.js.map +1 -1
  87. package/dist/utils/package-utils.d.ts +8 -6
  88. package/dist/utils/package-utils.d.ts.map +1 -1
  89. package/dist/utils/package-utils.js +26 -24
  90. package/dist/utils/package-utils.js.map +1 -1
  91. package/dist/utils/workspace-utils.d.ts +17 -0
  92. package/dist/utils/workspace-utils.d.ts.map +1 -0
  93. package/dist/utils/workspace-utils.js +95 -0
  94. package/dist/utils/workspace-utils.js.map +1 -0
  95. package/dist/workers/client.worker.d.ts +1 -0
  96. package/dist/workers/client.worker.d.ts.map +1 -1
  97. package/dist/workers/client.worker.js +8 -3
  98. package/dist/workers/client.worker.js.map +1 -1
  99. package/dist/workers/library-build.worker.d.ts +1 -0
  100. package/dist/workers/library-build.worker.d.ts.map +1 -1
  101. package/dist/workers/library-build.worker.js +3 -2
  102. package/dist/workers/library-build.worker.js.map +1 -1
  103. package/dist/workers/server-build.worker.d.ts +1 -0
  104. package/dist/workers/server-build.worker.d.ts.map +1 -1
  105. package/dist/workers/server-build.worker.js +12 -12
  106. package/dist/workers/server-build.worker.js.map +1 -1
  107. package/dist/workers/server-esbuild-context.d.ts.map +1 -1
  108. package/dist/workers/server-esbuild-context.js +4 -2
  109. package/dist/workers/server-esbuild-context.js.map +1 -1
  110. package/dist/workers/server-runtime.worker.d.ts +1 -0
  111. package/dist/workers/server-runtime.worker.d.ts.map +1 -1
  112. package/dist/workers/server-runtime.worker.js +9 -3
  113. package/dist/workers/server-runtime.worker.js.map +1 -1
  114. package/dist/workers/server-watch-manager.d.ts +1 -1
  115. package/dist/workers/server-watch-manager.d.ts.map +1 -1
  116. package/dist/workers/server-watch-manager.js +2 -2
  117. package/dist/workers/server-watch-manager.js.map +1 -1
  118. package/package.json +11 -11
  119. package/src/capacitor/capacitor-icon.ts +2 -2
  120. package/src/capacitor/capacitor-npm-config.ts +10 -19
  121. package/src/capacitor/capacitor.ts +2 -2
  122. package/src/commands/check.ts +1 -0
  123. package/src/commands/device.ts +2 -2
  124. package/src/commands/init/generators/root.ts +0 -1
  125. package/src/commands/init/init-client.ts +1 -1
  126. package/src/commands/init/init.ts +2 -2
  127. package/src/commands/init/templates/workspace-root/mise.toml.hbs +1 -1
  128. package/src/commands/publish/deployment-phase.ts +1 -0
  129. package/src/commands/publish/npm-publisher.ts +3 -3
  130. package/src/commands/publish/post-publish-phase.ts +1 -0
  131. package/src/commands/publish/publish-command.ts +7 -15
  132. package/src/deps/replace-deps/collect-deps.ts +4 -4
  133. package/src/deps/replace-deps/replace-deps-resolve.ts +13 -56
  134. package/src/deps/replace-deps/replace-deps.ts +3 -3
  135. package/src/deps/server-externals/server-production-files.ts +31 -18
  136. package/src/electron/electron.ts +7 -13
  137. package/src/engines/BaseEngine.ts +3 -2
  138. package/src/esbuild/esbuild-config.ts +12 -3
  139. package/src/esbuild/esbuild-tsc-plugin.ts +4 -1
  140. package/src/orchestrators/BaseOrchestrator.ts +1 -0
  141. package/src/orchestrators/BuildOrchestrator.ts +3 -5
  142. package/src/orchestrators/DevOrchestrator.ts +1 -0
  143. package/src/orchestrators/ServerRuntimeManager.ts +4 -0
  144. package/src/orchestrators/TypecheckOrchestrator.ts +4 -6
  145. package/src/runtime/engine-watch-events.ts +7 -1
  146. package/src/runtime/worker-events.ts +1 -0
  147. package/src/sd-cli-entry.ts +0 -9
  148. package/src/sd-cli.ts +2 -0
  149. package/src/typecheck/typecheck-non-package.ts +11 -0
  150. package/src/utils/package-utils.ts +30 -23
  151. package/src/utils/workspace-utils.ts +117 -0
  152. package/src/workers/client.worker.ts +9 -4
  153. package/src/workers/library-build.worker.ts +4 -3
  154. package/src/workers/server-build.worker.ts +13 -13
  155. package/src/workers/server-esbuild-context.ts +5 -2
  156. package/src/workers/server-runtime.worker.ts +10 -3
  157. package/src/workers/server-watch-manager.ts +3 -3
  158. package/tests/capacitor/capacitor-build.spec.ts +142 -142
  159. package/tests/capacitor/capacitor-init.spec.ts +181 -181
  160. package/tests/capacitor/capacitor-npm-config.acc.spec.ts +114 -114
  161. package/tests/capacitor/capacitor-npm-config.spec.ts +94 -94
  162. package/tests/commands/publish-manifest.acc.spec.ts +67 -0
  163. package/tests/deps/replace-deps/collect-deps.acc.spec.ts +16 -1
  164. package/tests/deps/replace-deps/replace-deps-resolve.acc.spec.ts +9 -5
  165. package/tests/deps/replace-deps/replace-deps-setup.acc.spec.ts +3 -3
  166. package/tests/deps/server-externals/server-production-files.spec.ts +68 -0
  167. package/tests/electron/electron.spec.ts +608 -608
  168. package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck-browser.tsbuildinfo +1 -1
  169. package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck-node.tsbuildinfo +1 -1
  170. package/tests/ts-compiler/fixtures/non-angular-pkg/.cache/typecheck.tsbuildinfo +1 -1
  171. package/tests/utils/engine-watch-events.spec.ts +17 -0
  172. package/tests/utils/esbuild-config.spec.ts +15 -0
  173. package/tests/utils/package-utils.spec.ts +36 -4
  174. package/tests/utils/replace-deps-watch.acc.spec.ts +4 -4
  175. package/tests/utils/replace-deps-watch.spec.ts +3 -3
  176. package/tests/utils/replace-deps.spec.ts +1 -35
  177. package/tests/utils/workspace-utils.spec.ts +87 -0
  178. package/tests/workers/library-build-worker.spec.ts +1 -1
  179. package/tests/workers/server-esbuild-context.spec.ts +4 -3
  180. package/dist/commands/reinstall.d.ts +0 -13
  181. package/dist/commands/reinstall.d.ts.map +0 -1
  182. package/dist/commands/reinstall.js +0 -56
  183. package/dist/commands/reinstall.js.map +0 -1
  184. package/src/commands/init/templates/workspace-root/pnpm-workspace.yaml +0 -5
  185. package/src/commands/reinstall.ts +0 -63
  186. package/tests/angular/angular-compiler-hmr-removal.verify.md +0 -16
  187. package/tests/angular/onbuild-lint-removal.verify.md +0 -8
  188. package/tests/angular/vite-angular-plugin-sdtscompiler.verify.md +0 -13
  189. package/tests/angular/vite-angular-plugin-vitest.verify.md +0 -20
  190. package/tests/capacitor/capacitor-android-exports.verify.md +0 -11
  191. package/tests/commands/publish-npm-local-split.verify.md +0 -9
  192. package/tests/commands/publish-responsibility-split.verify.md +0 -13
  193. package/tests/commands/publish-set.verify.md +0 -7
  194. package/tests/commands/publish-storage-split.verify.md +0 -8
  195. package/tests/commands/slice3-severity-cleanup.verify.md +0 -12
  196. package/tests/deps/deps-directory-separation.verify.md +0 -15
  197. package/tests/deps/replace-deps/replace-deps-perf.verify.md +0 -15
  198. package/tests/deps/server-externals/mise-toml-parse-intent.verify.md +0 -16
  199. package/tests/electron/electron-symlink-cleanup.verify.md +0 -8
  200. package/tests/engines/engine-duplicate-output-removal.verify.md +0 -10
  201. package/tests/engines/engine-typecheck-selection.verify.md +0 -8
  202. package/tests/engines/esbuild-client-engine.verify.md +0 -15
  203. package/tests/engines/normalize-result.verify.md +0 -9
  204. package/tests/engines/vite-dependency-cleanup.verify.md +0 -24
  205. package/tests/esbuild/esbuild-angular-compiler-plugin-hmr.verify.md +0 -23
  206. package/tests/esbuild/esbuild-angular-compiler-plugin-onload.verify.md +0 -21
  207. package/tests/esbuild/esbuild-angular-compiler-plugin-onstart-extraction.verify.md +0 -16
  208. package/tests/esbuild/esbuild-angular-compiler-plugin-sdtscompiler.verify.md +0 -15
  209. package/tests/esbuild/esbuild-angular-compiler-plugin-stylesheet.verify.md +0 -31
  210. package/tests/esbuild/esbuild-angular-compiler-plugin-worker.verify.md +0 -59
  211. package/tests/esbuild/esbuild-angular-compiler-plugin.verify.md +0 -21
  212. package/tests/esbuild/esbuild-postcss-plugin-chunking.verify.md +0 -17
  213. package/tests/esbuild/esbuild-tsc-plugin-imports.verify.md +0 -13
  214. package/tests/esbuild/esbuild-worker-plugin-node.verify.md +0 -12
  215. package/tests/esbuild/esbuild-worker-plugin.verify.md +0 -7
  216. package/tests/orchestrators/dist-delete-watcher.verify.md +0 -10
  217. package/tests/orchestrators/orchestrator-baseenv.verify.md +0 -10
  218. package/tests/orchestrators/orchestrator-diagnostic-formatting.verify.md +0 -10
  219. package/tests/orchestrators/orchestrator-initializemode-signature.verify.md +0 -9
  220. package/tests/orchestrators/slice1-stdout-to-consola.verify.md +0 -10
  221. package/tests/sd-cli-catch-all.verify.md +0 -7
  222. package/tests/sd-cli-log-tag.verify.md +0 -11
  223. package/tests/ts-compiler/SdTsCompiler-affected-files.verify.md +0 -8
  224. package/tests/ts-compiler/SdTsCompiler-crash-handling.verify.md +0 -24
  225. package/tests/ts-compiler/SdTsCompiler-diagnostics.verify.md +0 -12
  226. package/tests/ts-compiler/SdTsCompiler-emit.verify.md +0 -9
  227. package/tests/ts-compiler/SdTsCompiler.verify.md +0 -41
  228. package/tests/ts-compiler/scss-lint-integration.verify.md +0 -14
  229. package/tests/utils/copy-public-outdir.verify.md +0 -8
  230. package/tests/utils/dev-http-server.verify.md +0 -8
  231. package/tests/utils/engine-watch-events.verify.md +0 -17
  232. package/tests/utils/esbuild-client-config-integration.verify.md +0 -9
  233. package/tests/utils/esbuild-client-config-postcss.verify.md +0 -6
  234. package/tests/utils/esbuild-client-config.verify.md +0 -26
  235. package/tests/utils/esbuild-index-html.verify.md +0 -10
  236. package/tests/utils/esbuild-pwa.verify.md +0 -9
  237. package/tests/utils/esbuild-scss-plugin.verify.md +0 -8
  238. package/tests/utils/hmr-service.verify.md +0 -17
  239. package/tests/utils/lint-core-import-paths.verify.md +0 -10
  240. package/tests/utils/replace-deps-split.verify.md +0 -15
  241. package/tests/utils/replace-deps-watch.verify.md +0 -9
  242. package/tests/utils/server-production-files-import-paths.verify.md +0 -14
  243. package/tests/utils/vite-config-cleanup.verify.md +0 -7
  244. package/tests/workers/build-watch-paths-library.verify.md +0 -10
  245. package/tests/workers/build-watch-paths-ngtsc-server.verify.md +0 -12
  246. package/tests/workers/client-worker-browser-support.verify.md +0 -7
  247. package/tests/workers/client-worker-cleanup.verify.md +0 -8
  248. package/tests/workers/client-worker-initial-build-error.verify.md +0 -7
  249. package/tests/workers/client-worker-initial-build-warnings.verify.md +0 -7
  250. package/tests/workers/client-worker-mtime-incremental.verify.md +0 -10
  251. package/tests/workers/client-worker-onend-sync.verify.md +0 -7
  252. package/tests/workers/client-worker-refactor.verify.md +0 -22
  253. package/tests/workers/client-worker-ts-cache-invalidation.verify.md +0 -12
  254. package/tests/workers/dev-port-file.verify.md +0 -6
  255. package/tests/workers/ngtsc-build-rootnames-refresh.verify.md +0 -8
  256. package/tests/workers/server-build-context-dispose.verify.md +0 -8
  257. package/tests/workers/server-build-worker-plugin.verify.md +0 -9
  258. package/tests/workers/server-build-worker-refactoring.verify.md +0 -14
  259. package/tests/workers/server-esbuild-context-integration.verify.md +0 -10
  260. package/tests/workers/server-esbuild-context-tsc.verify.md +0 -7
@@ -1,181 +1,181 @@
1
- /* eslint-disable no-restricted-properties -- 테스트 환경변수 조작 필요 */
2
- import { describe, it, expect, vi, beforeAll, afterAll, beforeEach, afterEach } from "vitest";
3
- import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
4
- import { tmpdir } from "node:os";
5
- import path from "node:path";
6
- import { fsx, cpx } from "@simplysm/core-node";
7
-
8
- vi.mock("sharp", () => ({
9
- default: vi.fn().mockReturnValue({
10
- resize: vi.fn().mockReturnThis(),
11
- composite: vi.fn().mockReturnThis(),
12
- png: vi.fn().mockReturnThis(),
13
- toBuffer: vi.fn().mockResolvedValue(new Uint8Array([0])),
14
- toFile: vi.fn().mockResolvedValue(undefined),
15
- }),
16
- }));
17
-
18
- const mockFsxExists = vi.spyOn(fsx, "exists");
19
- const mockFsxRead = vi.spyOn(fsx, "read");
20
- vi.spyOn(fsx, "write").mockResolvedValue(undefined);
21
- const mockFsxReadJson = vi.spyOn(fsx, "readJson");
22
- vi.spyOn(fsx, "writeJson").mockResolvedValue(undefined);
23
- vi.spyOn(fsx, "mkdir").mockResolvedValue(undefined);
24
- vi.spyOn(fsx, "rm").mockResolvedValue(undefined);
25
- const mockFsxGlob = vi.spyOn(fsx, "glob");
26
- vi.spyOn(fsx, "copy").mockResolvedValue(undefined);
27
-
28
- vi.spyOn(cpx, "spawn").mockResolvedValue({ stdout: "", stderr: "", exitCode: 0 });
29
- vi.spyOn(cpx, "spawnSync").mockReturnValue({ stdout: "", stderr: "", exitCode: 0 });
30
-
31
- let tmpRoot: string;
32
- let PKG_PATH: string;
33
-
34
- beforeAll(() => {
35
- tmpRoot = mkdtempSync(path.join(tmpdir(), "cap-init-"));
36
- writeFileSync(path.join(tmpRoot, "pnpm-workspace.yaml"), "");
37
- PKG_PATH = path.join(tmpRoot, "pkg");
38
- // capacitor.ts가 .capacitor/.capacitor.lock 파일을 작성하므로 디렉토리 미리 생성
39
- mkdirSync(path.join(PKG_PATH, ".capacitor"), { recursive: true });
40
- });
41
-
42
- afterAll(() => {
43
- rmSync(tmpRoot, { recursive: true, force: true });
44
- });
45
-
46
- function setupDefaultMocks() {
47
- mockFsxExists.mockImplementation(((p: string) => {
48
- if (p.includes(".capacitor.lock")) return false;
49
- return true;
50
- }) as never);
51
-
52
- mockFsxReadJson.mockImplementation(((p: string) => {
53
- const normalized = p.replace(/\\/g, "/");
54
- if (normalized.includes(".capacitor/package.json")) {
55
- return {
56
- name: "com.test.app",
57
- version: "1.0.0",
58
- dependencies: {
59
- "@capacitor/core": "^7.0.0",
60
- "@capacitor/app": "^7.0.0",
61
- "@capacitor/android": "^7.0.0",
62
- },
63
- devDependencies: {
64
- "@capacitor/cli": "^7.0.0",
65
- "@capacitor/assets": "^3.0.0",
66
- },
67
- };
68
- }
69
- if (normalized.endsWith("package.json")) {
70
- return { name: "test-pkg", version: "1.0.0" };
71
- }
72
- return {};
73
- }) as never);
74
-
75
- mockFsxRead.mockImplementation(((p: string) => {
76
- if (p.includes("AndroidManifest.xml")) {
77
- return '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n<application>\n<activity android:name=".MainActivity">\n</activity>\n</application>\n</manifest>';
78
- }
79
- if (p.includes("build.gradle")) {
80
- return `android {
81
- defaultConfig {
82
- versionCode 1
83
- versionName "1.0"
84
- minSdkVersion rootProject.ext.minSdkVersion
85
- targetSdkVersion rootProject.ext.targetSdkVersion
86
- }
87
- buildTypes { release { } }
88
- }`;
89
- }
90
- if (p.includes("gradle.properties")) {
91
- return "org.gradle.jvmargs=-Xmx2048m";
92
- }
93
- return "";
94
- }) as never);
95
-
96
- mockFsxGlob.mockResolvedValue(["C:/Program Files/Amazon Corretto/jdk21.0.1"]);
97
- process.env["ANDROID_HOME"] = "C:/Android/Sdk";
98
- }
99
-
100
- let savedEnv: Record<string, string | undefined>;
101
- beforeEach(() => {
102
- savedEnv = { ...process.env };
103
- });
104
- afterEach(() => {
105
- process.env = savedEnv;
106
- });
107
-
108
- describe("Capacitor 설정 검증", () => {
109
- beforeEach(() => {
110
- vi.clearAllMocks();
111
- setupDefaultMocks();
112
- });
113
-
114
- it("유효한 appId를 허용한다", async () => {
115
- const { Capacitor } = await import("../../src/capacitor/capacitor.js");
116
- const instance = await Capacitor.create(PKG_PATH, {
117
- appId: "com.example.myapp",
118
- appName: "Test App",
119
- });
120
- expect(instance).toBeDefined();
121
- });
122
-
123
- it("잘못된 appId (숫자 시작)를 거부한다", async () => {
124
- const { Capacitor } = await import("../../src/capacitor/capacitor.js");
125
- await expect(
126
- Capacitor.create(PKG_PATH, { appId: "123.app", appName: "Test" }),
127
- ).rejects.toThrow("appId");
128
- });
129
-
130
- it("잘못된 appId (단일 세그먼트)를 거부한다", async () => {
131
- const { Capacitor } = await import("../../src/capacitor/capacitor.js");
132
- await expect(
133
- Capacitor.create(PKG_PATH, { appId: "myapp", appName: "Test" }),
134
- ).rejects.toThrow("appId");
135
- });
136
-
137
- it("잘못된 appName (특수문자)을 거부한다", async () => {
138
- const { Capacitor } = await import("../../src/capacitor/capacitor.js");
139
- await expect(
140
- Capacitor.create(PKG_PATH, { appId: "com.test.app", appName: "Test@App!" }),
141
- ).rejects.toThrow("appName");
142
- });
143
-
144
- it("한글 appName을 허용한다", async () => {
145
- const { Capacitor } = await import("../../src/capacitor/capacitor.js");
146
- const instance = await Capacitor.create(PKG_PATH, {
147
- appId: "com.test.app",
148
- appName: "내 앱",
149
- });
150
- expect(instance).toBeDefined();
151
- });
152
- });
153
-
154
- describe("Android 개발 도구 감지", () => {
155
- beforeEach(() => {
156
- vi.clearAllMocks();
157
- setupDefaultMocks();
158
- });
159
-
160
- it("Android SDK 미설치 시 에러가 발생한다", async () => {
161
- delete process.env["ANDROID_HOME"];
162
- mockFsxExists.mockImplementation(((p: string) => {
163
- const n = p.replace(/\\/g, "/");
164
- if (n.includes(".capacitor.lock")) return false;
165
- if (n.includes("Android/Sdk")) return false;
166
- if (n.includes("Android\\Sdk")) return false;
167
- if (n.includes("Program Files/Android")) return false;
168
- if (n.includes("C:/Android")) return false;
169
- return true;
170
- }) as never);
171
-
172
- const { Capacitor } = await import("../../src/capacitor/capacitor.js");
173
- const cap = await Capacitor.create(PKG_PATH, {
174
- appId: "com.test.app",
175
- appName: "Test App",
176
- platform: { android: {} },
177
- });
178
-
179
- await expect(cap.initialize()).rejects.toThrow("Android SDK");
180
- });
181
- });
1
+ /* eslint-disable no-restricted-properties -- 테스트 환경변수 조작 필요 */
2
+ import { describe, it, expect, vi, beforeAll, afterAll, beforeEach, afterEach } from "vitest";
3
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
4
+ import { tmpdir } from "node:os";
5
+ import path from "node:path";
6
+ import { fsx, cpx } from "@simplysm/core-node";
7
+
8
+ vi.mock("sharp", () => ({
9
+ default: vi.fn().mockReturnValue({
10
+ resize: vi.fn().mockReturnThis(),
11
+ composite: vi.fn().mockReturnThis(),
12
+ png: vi.fn().mockReturnThis(),
13
+ toBuffer: vi.fn().mockResolvedValue(new Uint8Array([0])),
14
+ toFile: vi.fn().mockResolvedValue(undefined),
15
+ }),
16
+ }));
17
+
18
+ const mockFsxExists = vi.spyOn(fsx, "exists");
19
+ const mockFsxRead = vi.spyOn(fsx, "read");
20
+ vi.spyOn(fsx, "write").mockResolvedValue(undefined);
21
+ const mockFsxReadJson = vi.spyOn(fsx, "readJson");
22
+ vi.spyOn(fsx, "writeJson").mockResolvedValue(undefined);
23
+ vi.spyOn(fsx, "mkdir").mockResolvedValue(undefined);
24
+ vi.spyOn(fsx, "rm").mockResolvedValue(undefined);
25
+ const mockFsxGlob = vi.spyOn(fsx, "glob");
26
+ vi.spyOn(fsx, "copy").mockResolvedValue(undefined);
27
+
28
+ vi.spyOn(cpx, "spawn").mockResolvedValue({ stdout: "", stderr: "", exitCode: 0 });
29
+ vi.spyOn(cpx, "spawnSync").mockReturnValue({ stdout: "", stderr: "", exitCode: 0 });
30
+
31
+ let tmpRoot: string;
32
+ let PKG_PATH: string;
33
+
34
+ beforeAll(() => {
35
+ tmpRoot = mkdtempSync(path.join(tmpdir(), "cap-init-"));
36
+ writeFileSync(path.join(tmpRoot, "package.json"), JSON.stringify({ private: true, workspaces: ["pkg"] }));
37
+ PKG_PATH = path.join(tmpRoot, "pkg");
38
+ // capacitor.ts가 .capacitor/.capacitor.lock 파일을 작성하므로 디렉토리 미리 생성
39
+ mkdirSync(path.join(PKG_PATH, ".capacitor"), { recursive: true });
40
+ });
41
+
42
+ afterAll(() => {
43
+ rmSync(tmpRoot, { recursive: true, force: true });
44
+ });
45
+
46
+ function setupDefaultMocks() {
47
+ mockFsxExists.mockImplementation(((p: string) => {
48
+ if (p.includes(".capacitor.lock")) return false;
49
+ return true;
50
+ }) as never);
51
+
52
+ mockFsxReadJson.mockImplementation(((p: string) => {
53
+ const normalized = p.replace(/\\/g, "/");
54
+ if (normalized.includes(".capacitor/package.json")) {
55
+ return {
56
+ name: "com.test.app",
57
+ version: "1.0.0",
58
+ dependencies: {
59
+ "@capacitor/core": "^7.0.0",
60
+ "@capacitor/app": "^7.0.0",
61
+ "@capacitor/android": "^7.0.0",
62
+ },
63
+ devDependencies: {
64
+ "@capacitor/cli": "^7.0.0",
65
+ "@capacitor/assets": "^3.0.0",
66
+ },
67
+ };
68
+ }
69
+ if (normalized.endsWith("package.json")) {
70
+ return { name: "test-pkg", version: "1.0.0" };
71
+ }
72
+ return {};
73
+ }) as never);
74
+
75
+ mockFsxRead.mockImplementation(((p: string) => {
76
+ if (p.includes("AndroidManifest.xml")) {
77
+ return '<manifest xmlns:android="http://schemas.android.com/apk/res/android">\n<application>\n<activity android:name=".MainActivity">\n</activity>\n</application>\n</manifest>';
78
+ }
79
+ if (p.includes("build.gradle")) {
80
+ return `android {
81
+ defaultConfig {
82
+ versionCode 1
83
+ versionName "1.0"
84
+ minSdkVersion rootProject.ext.minSdkVersion
85
+ targetSdkVersion rootProject.ext.targetSdkVersion
86
+ }
87
+ buildTypes { release { } }
88
+ }`;
89
+ }
90
+ if (p.includes("gradle.properties")) {
91
+ return "org.gradle.jvmargs=-Xmx2048m";
92
+ }
93
+ return "";
94
+ }) as never);
95
+
96
+ mockFsxGlob.mockResolvedValue(["C:/Program Files/Amazon Corretto/jdk21.0.1"]);
97
+ process.env["ANDROID_HOME"] = "C:/Android/Sdk";
98
+ }
99
+
100
+ let savedEnv: Record<string, string | undefined>;
101
+ beforeEach(() => {
102
+ savedEnv = { ...process.env };
103
+ });
104
+ afterEach(() => {
105
+ process.env = savedEnv;
106
+ });
107
+
108
+ describe("Capacitor 설정 검증", () => {
109
+ beforeEach(() => {
110
+ vi.clearAllMocks();
111
+ setupDefaultMocks();
112
+ });
113
+
114
+ it("유효한 appId를 허용한다", async () => {
115
+ const { Capacitor } = await import("../../src/capacitor/capacitor.js");
116
+ const instance = await Capacitor.create(PKG_PATH, {
117
+ appId: "com.example.myapp",
118
+ appName: "Test App",
119
+ });
120
+ expect(instance).toBeDefined();
121
+ });
122
+
123
+ it("잘못된 appId (숫자 시작)를 거부한다", async () => {
124
+ const { Capacitor } = await import("../../src/capacitor/capacitor.js");
125
+ await expect(
126
+ Capacitor.create(PKG_PATH, { appId: "123.app", appName: "Test" }),
127
+ ).rejects.toThrow("appId");
128
+ });
129
+
130
+ it("잘못된 appId (단일 세그먼트)를 거부한다", async () => {
131
+ const { Capacitor } = await import("../../src/capacitor/capacitor.js");
132
+ await expect(
133
+ Capacitor.create(PKG_PATH, { appId: "myapp", appName: "Test" }),
134
+ ).rejects.toThrow("appId");
135
+ });
136
+
137
+ it("잘못된 appName (특수문자)을 거부한다", async () => {
138
+ const { Capacitor } = await import("../../src/capacitor/capacitor.js");
139
+ await expect(
140
+ Capacitor.create(PKG_PATH, { appId: "com.test.app", appName: "Test@App!" }),
141
+ ).rejects.toThrow("appName");
142
+ });
143
+
144
+ it("한글 appName을 허용한다", async () => {
145
+ const { Capacitor } = await import("../../src/capacitor/capacitor.js");
146
+ const instance = await Capacitor.create(PKG_PATH, {
147
+ appId: "com.test.app",
148
+ appName: "내 앱",
149
+ });
150
+ expect(instance).toBeDefined();
151
+ });
152
+ });
153
+
154
+ describe("Android 개발 도구 감지", () => {
155
+ beforeEach(() => {
156
+ vi.clearAllMocks();
157
+ setupDefaultMocks();
158
+ });
159
+
160
+ it("Android SDK 미설치 시 에러가 발생한다", async () => {
161
+ delete process.env["ANDROID_HOME"];
162
+ mockFsxExists.mockImplementation(((p: string) => {
163
+ const n = p.replace(/\\/g, "/");
164
+ if (n.includes(".capacitor.lock")) return false;
165
+ if (n.includes("Android/Sdk")) return false;
166
+ if (n.includes("Android\\Sdk")) return false;
167
+ if (n.includes("Program Files/Android")) return false;
168
+ if (n.includes("C:/Android")) return false;
169
+ return true;
170
+ }) as never);
171
+
172
+ const { Capacitor } = await import("../../src/capacitor/capacitor.js");
173
+ const cap = await Capacitor.create(PKG_PATH, {
174
+ appId: "com.test.app",
175
+ appName: "Test App",
176
+ platform: { android: {} },
177
+ });
178
+
179
+ await expect(cap.initialize()).rejects.toThrow("Android SDK");
180
+ });
181
+ });
@@ -1,114 +1,114 @@
1
- import { describe, it, expect, vi, beforeAll, afterAll, beforeEach } from "vitest";
2
- import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
3
- import { tmpdir } from "node:os";
4
- import path from "node:path";
5
- import { fsx, cpx } from "@simplysm/core-node";
6
-
7
- const mockFsxExists = vi.spyOn(fsx, "exists");
8
- vi.spyOn(fsx, "read");
9
- vi.spyOn(fsx, "write").mockResolvedValue(undefined);
10
- const mockFsxReadJson = vi.spyOn(fsx, "readJson");
11
- vi.spyOn(fsx, "writeJson").mockResolvedValue(undefined);
12
- vi.spyOn(fsx, "mkdir").mockResolvedValue(undefined);
13
-
14
- const execaCalls: { command: string; args: string[]; options: unknown }[] = [];
15
- vi.spyOn(cpx, "spawn").mockImplementation(((cmd: string, args: string[], options: unknown) => {
16
- execaCalls.push({
17
- command: cmd,
18
- args,
19
- options,
20
- });
21
- return { stdout: "", stderr: "", exitCode: 0 };
22
- }) as never);
23
-
24
- //#endregion
25
-
26
- let tmpRoot: string;
27
- let CAP_PATH: string;
28
- let PKG_PATH: string;
29
-
30
- beforeAll(() => {
31
- tmpRoot = mkdtempSync(path.join(tmpdir(), "cap-npm-config-acc-"));
32
- writeFileSync(path.join(tmpRoot, "pnpm-workspace.yaml"), "");
33
- PKG_PATH = path.join(tmpRoot, "pkg");
34
- CAP_PATH = path.join(PKG_PATH, ".capacitor");
35
- });
36
-
37
- afterAll(() => {
38
- rmSync(tmpRoot, { recursive: true, force: true });
39
- });
40
-
41
- function setupDefaultMocks() {
42
- mockFsxExists.mockImplementation(((p: string) => {
43
- const n = p.replace(/\\/g, "/");
44
- if (n.includes(".capacitor.lock")) return false;
45
- return true;
46
- }) as never);
47
-
48
- mockFsxReadJson.mockImplementation(((p: string) => {
49
- const normalized = p.replace(/\\/g, "/");
50
- if (normalized.includes(".capacitor/package.json")) {
51
- return {
52
- name: "com.test.app",
53
- version: "1.0.0",
54
- dependencies: {
55
- "@capacitor/core": "^7",
56
- "@capacitor/app": "^7",
57
- "@capacitor/android": "^7",
58
- },
59
- devDependencies: {
60
- "@capacitor/cli": "^7",
61
- "@capacitor/assets": "^3",
62
- },
63
- };
64
- }
65
- return { name: "test-pkg", version: "1.0.0" };
66
- }) as never);
67
-
68
- execaCalls.length = 0;
69
- }
70
-
71
- describe("initCapNpmProject", () => {
72
- beforeEach(() => {
73
- vi.clearAllMocks();
74
- setupDefaultMocks();
75
- });
76
-
77
- it("의존성 미변경 + node_modules 존재 시 false를 반환하고 pnpm install을 실행하지 않는다", async () => {
78
- const { initCapNpmProject } = await import(
79
- "../../src/capacitor/capacitor-npm-config.js"
80
- );
81
-
82
- const changed = await initCapNpmProject(CAP_PATH, PKG_PATH, {
83
- appId: "com.test.app",
84
- appName: "Test App",
85
- platform: { android: {} },
86
- }, { name: "test-pkg", version: "1.0.0" }, ["android"], []);
87
-
88
- expect(changed).toBe(false);
89
- });
90
-
91
- it("node_modules가 없으면 true를 반환하고 pnpm install을 실행한다", async () => {
92
- mockFsxExists.mockImplementation(((p: string) => {
93
- const n = p.replace(/\\/g, "/");
94
- if (n.includes(".capacitor.lock")) return false;
95
- if (n.includes("node_modules")) return false;
96
- return true;
97
- }) as never);
98
-
99
- const { initCapNpmProject } = await import(
100
- "../../src/capacitor/capacitor-npm-config.js"
101
- );
102
-
103
- const changed = await initCapNpmProject(CAP_PATH, PKG_PATH, {
104
- appId: "com.test.app",
105
- appName: "Test App",
106
- platform: { android: {} },
107
- }, {
108
- name: "test-pkg",
109
- version: "1.0.0",
110
- }, ["android"], []);
111
-
112
- expect(changed).toBe(true);
113
- });
114
- });
1
+ import { describe, it, expect, vi, beforeAll, afterAll, beforeEach } from "vitest";
2
+ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import path from "node:path";
5
+ import { fsx, cpx } from "@simplysm/core-node";
6
+
7
+ const mockFsxExists = vi.spyOn(fsx, "exists");
8
+ vi.spyOn(fsx, "read");
9
+ vi.spyOn(fsx, "write").mockResolvedValue(undefined);
10
+ const mockFsxReadJson = vi.spyOn(fsx, "readJson");
11
+ vi.spyOn(fsx, "writeJson").mockResolvedValue(undefined);
12
+ vi.spyOn(fsx, "mkdir").mockResolvedValue(undefined);
13
+
14
+ const execaCalls: { command: string; args: string[]; options: unknown }[] = [];
15
+ vi.spyOn(cpx, "spawn").mockImplementation(((cmd: string, args: string[], options: unknown) => {
16
+ execaCalls.push({
17
+ command: cmd,
18
+ args,
19
+ options,
20
+ });
21
+ return { stdout: "", stderr: "", exitCode: 0 };
22
+ }) as never);
23
+
24
+ //#endregion
25
+
26
+ let tmpRoot: string;
27
+ let CAP_PATH: string;
28
+ let PKG_PATH: string;
29
+
30
+ beforeAll(() => {
31
+ tmpRoot = mkdtempSync(path.join(tmpdir(), "cap-npm-config-acc-"));
32
+ writeFileSync(path.join(tmpRoot, "package.json"), JSON.stringify({ private: true, workspaces: ["pkg"] }));
33
+ PKG_PATH = path.join(tmpRoot, "pkg");
34
+ CAP_PATH = path.join(PKG_PATH, ".capacitor");
35
+ });
36
+
37
+ afterAll(() => {
38
+ rmSync(tmpRoot, { recursive: true, force: true });
39
+ });
40
+
41
+ function setupDefaultMocks() {
42
+ mockFsxExists.mockImplementation(((p: string) => {
43
+ const n = p.replace(/\\/g, "/");
44
+ if (n.includes(".capacitor.lock")) return false;
45
+ return true;
46
+ }) as never);
47
+
48
+ mockFsxReadJson.mockImplementation(((p: string) => {
49
+ const normalized = p.replace(/\\/g, "/");
50
+ if (normalized.includes(".capacitor/package.json")) {
51
+ return {
52
+ name: "com.test.app",
53
+ version: "1.0.0",
54
+ dependencies: {
55
+ "@capacitor/core": "^7",
56
+ "@capacitor/app": "^7",
57
+ "@capacitor/android": "^7",
58
+ },
59
+ devDependencies: {
60
+ "@capacitor/cli": "^7",
61
+ "@capacitor/assets": "^3",
62
+ },
63
+ };
64
+ }
65
+ return { name: "test-pkg", version: "1.0.0" };
66
+ }) as never);
67
+
68
+ execaCalls.length = 0;
69
+ }
70
+
71
+ describe("initCapNpmProject", () => {
72
+ beforeEach(() => {
73
+ vi.clearAllMocks();
74
+ setupDefaultMocks();
75
+ });
76
+
77
+ it("의존성 미변경 + node_modules 존재 시 false를 반환하고 bun install을 실행하지 않는다", async () => {
78
+ const { initCapNpmProject } = await import(
79
+ "../../src/capacitor/capacitor-npm-config.js"
80
+ );
81
+
82
+ const changed = await initCapNpmProject(CAP_PATH, PKG_PATH, {
83
+ appId: "com.test.app",
84
+ appName: "Test App",
85
+ platform: { android: {} },
86
+ }, { name: "test-pkg", version: "1.0.0" }, ["android"], []);
87
+
88
+ expect(changed).toBe(false);
89
+ });
90
+
91
+ it("node_modules가 없으면 true를 반환하고 bun install을 실행한다", async () => {
92
+ mockFsxExists.mockImplementation(((p: string) => {
93
+ const n = p.replace(/\\/g, "/");
94
+ if (n.includes(".capacitor.lock")) return false;
95
+ if (n.includes("node_modules")) return false;
96
+ return true;
97
+ }) as never);
98
+
99
+ const { initCapNpmProject } = await import(
100
+ "../../src/capacitor/capacitor-npm-config.js"
101
+ );
102
+
103
+ const changed = await initCapNpmProject(CAP_PATH, PKG_PATH, {
104
+ appId: "com.test.app",
105
+ appName: "Test App",
106
+ platform: { android: {} },
107
+ }, {
108
+ name: "test-pkg",
109
+ version: "1.0.0",
110
+ }, ["android"], []);
111
+
112
+ expect(changed).toBe(true);
113
+ });
114
+ });