@simplysm/sd-cli 14.0.47 → 14.0.49

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 (200) hide show
  1. package/README.md +782 -0
  2. package/dist/angular/ngtsc-build-core.js +2 -2
  3. package/dist/angular/ngtsc-build-core.js.map +1 -1
  4. package/dist/angular/vite-angular-plugin.d.ts.map +1 -1
  5. package/dist/angular/vite-angular-plugin.js +3 -2
  6. package/dist/angular/vite-angular-plugin.js.map +1 -1
  7. package/dist/capacitor/capacitor-android.js +2 -2
  8. package/dist/capacitor/capacitor-android.js.map +1 -1
  9. package/dist/capacitor/capacitor-build.d.ts.map +1 -1
  10. package/dist/capacitor/capacitor-build.js +2 -1
  11. package/dist/capacitor/capacitor-build.js.map +1 -1
  12. package/dist/capacitor/capacitor-icon.d.ts.map +1 -1
  13. package/dist/capacitor/capacitor-icon.js +2 -1
  14. package/dist/capacitor/capacitor-icon.js.map +1 -1
  15. package/dist/capacitor/capacitor-npm-config.d.ts.map +1 -1
  16. package/dist/capacitor/capacitor-npm-config.js +2 -1
  17. package/dist/capacitor/capacitor-npm-config.js.map +1 -1
  18. package/dist/capacitor/capacitor.d.ts.map +1 -1
  19. package/dist/capacitor/capacitor.js +2 -1
  20. package/dist/capacitor/capacitor.js.map +1 -1
  21. package/dist/commands/device.js +2 -2
  22. package/dist/commands/device.js.map +1 -1
  23. package/dist/commands/replace-deps.js +2 -2
  24. package/dist/commands/replace-deps.js.map +1 -1
  25. package/dist/deps/replace-deps/collect-deps.js +2 -2
  26. package/dist/deps/replace-deps/collect-deps.js.map +1 -1
  27. package/dist/deps/replace-deps/replace-deps.d.ts.map +1 -1
  28. package/dist/deps/replace-deps/replace-deps.js +108 -81
  29. package/dist/deps/replace-deps/replace-deps.js.map +1 -1
  30. package/dist/deps/server-externals/server-production-files.js +2 -2
  31. package/dist/deps/server-externals/server-production-files.js.map +1 -1
  32. package/dist/electron/electron.d.ts.map +1 -1
  33. package/dist/electron/electron.js +2 -1
  34. package/dist/electron/electron.js.map +1 -1
  35. package/dist/engines/BaseEngine.d.ts.map +1 -1
  36. package/dist/engines/BaseEngine.js +2 -2
  37. package/dist/engines/BaseEngine.js.map +1 -1
  38. package/dist/engines/EsbuildClientEngine.d.ts.map +1 -1
  39. package/dist/engines/EsbuildClientEngine.js +2 -2
  40. package/dist/engines/EsbuildClientEngine.js.map +1 -1
  41. package/dist/engines/NgtscEngine.js +2 -2
  42. package/dist/engines/NgtscEngine.js.map +1 -1
  43. package/dist/engines/ServerEsbuildEngine.js +2 -2
  44. package/dist/engines/ServerEsbuildEngine.js.map +1 -1
  45. package/dist/engines/TscEngine.js +2 -2
  46. package/dist/engines/TscEngine.js.map +1 -1
  47. package/dist/engines/engine-factory.d.ts.map +1 -1
  48. package/dist/engines/engine-factory.js +2 -2
  49. package/dist/engines/engine-factory.js.map +1 -1
  50. package/dist/esbuild/esbuild-angular-compiler-plugin.d.ts.map +1 -1
  51. package/dist/esbuild/esbuild-angular-compiler-plugin.js +46 -18
  52. package/dist/esbuild/esbuild-angular-compiler-plugin.js.map +1 -1
  53. package/dist/esbuild/esbuild-config.js +2 -2
  54. package/dist/esbuild/esbuild-config.js.map +1 -1
  55. package/dist/lint/lint-with-program.js +2 -2
  56. package/dist/lint/lint-with-program.js.map +1 -1
  57. package/dist/runtime/lazy-logger.d.ts +14 -0
  58. package/dist/runtime/lazy-logger.d.ts.map +1 -0
  59. package/dist/runtime/lazy-logger.js +23 -0
  60. package/dist/runtime/lazy-logger.js.map +1 -0
  61. package/dist/sd-cli-entry.js +2 -2
  62. package/dist/sd-cli-entry.js.map +1 -1
  63. package/dist/sd-cli.js +2 -2
  64. package/dist/sd-cli.js.map +1 -1
  65. package/dist/ts-compiler/SdTsCompiler.d.ts +11 -0
  66. package/dist/ts-compiler/SdTsCompiler.d.ts.map +1 -1
  67. package/dist/ts-compiler/SdTsCompiler.js +223 -116
  68. package/dist/ts-compiler/SdTsCompiler.js.map +1 -1
  69. package/dist/typecheck/typecheck-non-package.js +2 -2
  70. package/dist/typecheck/typecheck-non-package.js.map +1 -1
  71. package/dist/typecheck/typecheck-serialization.d.ts +31 -9
  72. package/dist/typecheck/typecheck-serialization.d.ts.map +1 -1
  73. package/dist/typecheck/typecheck-serialization.js +62 -22
  74. package/dist/typecheck/typecheck-serialization.js.map +1 -1
  75. package/dist/utils/output-utils.js +2 -2
  76. package/dist/utils/output-utils.js.map +1 -1
  77. package/dist/utils/package-classify.js +2 -2
  78. package/dist/utils/package-classify.js.map +1 -1
  79. package/dist/utils/package-utils.js +2 -2
  80. package/dist/utils/package-utils.js.map +1 -1
  81. package/dist/utils/sd-config.js +2 -2
  82. package/dist/utils/sd-config.js.map +1 -1
  83. package/dist/utils/tsconfig.d.ts.map +1 -1
  84. package/dist/utils/tsconfig.js +3 -5
  85. package/dist/utils/tsconfig.js.map +1 -1
  86. package/package.json +5 -5
  87. package/src/angular/ngtsc-build-core.ts +3 -3
  88. package/src/angular/vite-angular-plugin.ts +3 -2
  89. package/src/capacitor/capacitor-android.ts +2 -2
  90. package/src/capacitor/capacitor-build.ts +2 -1
  91. package/src/capacitor/capacitor-icon.ts +2 -1
  92. package/src/capacitor/capacitor-npm-config.ts +2 -1
  93. package/src/capacitor/capacitor.ts +2 -1
  94. package/src/commands/device.ts +2 -2
  95. package/src/commands/replace-deps.ts +2 -2
  96. package/src/deps/replace-deps/collect-deps.ts +2 -2
  97. package/src/deps/replace-deps/replace-deps.ts +119 -85
  98. package/src/deps/server-externals/server-production-files.ts +2 -2
  99. package/src/electron/electron.ts +2 -1
  100. package/src/engines/BaseEngine.ts +2 -2
  101. package/src/engines/EsbuildClientEngine.ts +2 -2
  102. package/src/engines/NgtscEngine.ts +2 -2
  103. package/src/engines/ServerEsbuildEngine.ts +2 -2
  104. package/src/engines/TscEngine.ts +2 -2
  105. package/src/engines/engine-factory.ts +2 -2
  106. package/src/esbuild/esbuild-angular-compiler-plugin.ts +60 -19
  107. package/src/esbuild/esbuild-config.ts +2 -2
  108. package/src/lint/lint-with-program.ts +2 -2
  109. package/src/runtime/lazy-logger.ts +23 -0
  110. package/src/sd-cli-entry.ts +2 -2
  111. package/src/sd-cli.ts +2 -2
  112. package/src/ts-compiler/SdTsCompiler.ts +280 -138
  113. package/src/typecheck/typecheck-non-package.ts +2 -2
  114. package/src/typecheck/typecheck-serialization.ts +100 -26
  115. package/src/utils/output-utils.ts +2 -2
  116. package/src/utils/package-classify.ts +2 -2
  117. package/src/utils/package-utils.ts +2 -2
  118. package/src/utils/sd-config.ts +2 -2
  119. package/src/utils/tsconfig.ts +3 -4
  120. package/tests/angular/angular-compiler-hmr-removal.verify.md +12 -12
  121. package/tests/angular/onbuild-lint-removal.verify.md +4 -4
  122. package/tests/angular/vite-angular-plugin-sdtscompiler.verify.md +9 -9
  123. package/tests/angular/vite-angular-plugin-vitest.verify.md +16 -16
  124. package/tests/capacitor/capacitor-android-exports.verify.md +7 -7
  125. package/tests/commands/publish-npm-local-split.verify.md +5 -5
  126. package/tests/commands/publish-responsibility-split.verify.md +9 -9
  127. package/tests/commands/publish-set.verify.md +3 -3
  128. package/tests/commands/publish-storage-split.verify.md +4 -4
  129. package/tests/commands/slice3-severity-cleanup.verify.md +8 -8
  130. package/tests/deps/deps-directory-separation.verify.md +11 -11
  131. package/tests/deps/replace-deps/replace-deps-perf.verify.md +6 -6
  132. package/tests/deps/server-externals/mise-toml-parse-intent.verify.md +8 -8
  133. package/tests/electron/electron-symlink-cleanup.verify.md +4 -4
  134. package/tests/engines/engine-duplicate-output-removal.verify.md +6 -6
  135. package/tests/engines/engine-typecheck-selection.verify.md +4 -4
  136. package/tests/engines/esbuild-client-engine.verify.md +11 -11
  137. package/tests/engines/normalize-result.verify.md +5 -5
  138. package/tests/engines/vite-dependency-cleanup.verify.md +11 -11
  139. package/tests/esbuild/esbuild-angular-compiler-plugin-hmr.verify.md +10 -10
  140. package/tests/esbuild/esbuild-angular-compiler-plugin-onload.verify.md +17 -17
  141. package/tests/esbuild/esbuild-angular-compiler-plugin-onstart-extraction.verify.md +12 -12
  142. package/tests/esbuild/esbuild-angular-compiler-plugin-sdtscompiler.verify.md +11 -11
  143. package/tests/esbuild/esbuild-angular-compiler-plugin-stylesheet.verify.md +13 -13
  144. package/tests/esbuild/esbuild-angular-compiler-plugin-worker.verify.md +32 -32
  145. package/tests/esbuild/esbuild-angular-compiler-plugin.verify.md +9 -9
  146. package/tests/esbuild/esbuild-postcss-plugin-chunking.verify.md +3 -3
  147. package/tests/esbuild/esbuild-tsc-plugin-imports.verify.md +9 -9
  148. package/tests/esbuild/esbuild-worker-plugin-node.verify.md +7 -7
  149. package/tests/esbuild/esbuild-worker-plugin.spec.ts +8 -0
  150. package/tests/esbuild/esbuild-worker-plugin.verify.md +3 -3
  151. package/tests/orchestrators/dist-delete-watcher.verify.md +6 -6
  152. package/tests/orchestrators/orchestrator-baseenv.verify.md +6 -6
  153. package/tests/orchestrators/orchestrator-diagnostic-formatting.verify.md +6 -6
  154. package/tests/orchestrators/orchestrator-initializemode-signature.verify.md +5 -5
  155. package/tests/orchestrators/slice1-stdout-to-consola.verify.md +6 -6
  156. package/tests/sd-cli-catch-all.verify.md +3 -3
  157. package/tests/sd-cli-log-tag.verify.md +7 -7
  158. package/tests/ts-compiler/SdTsCompiler-affected-files.verify.md +4 -4
  159. package/tests/ts-compiler/SdTsCompiler-diagnostics.verify.md +8 -8
  160. package/tests/ts-compiler/SdTsCompiler-emit.verify.md +5 -5
  161. package/tests/ts-compiler/SdTsCompiler.verify.md +20 -20
  162. package/tests/ts-compiler/scss-lint-integration.verify.md +10 -10
  163. package/tests/utils/copy-public-outdir.verify.md +4 -4
  164. package/tests/utils/dev-http-server.verify.md +4 -4
  165. package/tests/utils/engine-watch-events.verify.md +8 -8
  166. package/tests/utils/esbuild-client-config-integration.verify.md +5 -5
  167. package/tests/utils/esbuild-client-config-postcss.verify.md +2 -2
  168. package/tests/utils/esbuild-client-config.verify.md +16 -16
  169. package/tests/utils/esbuild-index-html.verify.md +6 -6
  170. package/tests/utils/esbuild-pwa.verify.md +5 -5
  171. package/tests/utils/esbuild-scss-plugin.verify.md +4 -4
  172. package/tests/utils/hmr-service.verify.md +10 -10
  173. package/tests/utils/lint-core-import-paths.verify.md +6 -6
  174. package/tests/utils/replace-deps-split.verify.md +11 -11
  175. package/tests/utils/replace-deps-watch.acc.spec.ts +85 -0
  176. package/tests/utils/replace-deps-watch.spec.ts +198 -1
  177. package/tests/utils/replace-deps-watch.verify.md +5 -5
  178. package/tests/utils/server-production-files-import-paths.verify.md +10 -10
  179. package/tests/utils/vite-config-cleanup.verify.md +3 -3
  180. package/tests/workers/build-watch-paths-library.verify.md +6 -6
  181. package/tests/workers/build-watch-paths-ngtsc-server.verify.md +8 -8
  182. package/tests/workers/client-worker-browser-support.verify.md +3 -3
  183. package/tests/workers/client-worker-cleanup.verify.md +4 -4
  184. package/tests/workers/client-worker-initial-build-error.verify.md +3 -3
  185. package/tests/workers/client-worker-initial-build-warnings.verify.md +3 -3
  186. package/tests/workers/client-worker-mtime-incremental.verify.md +6 -6
  187. package/tests/workers/client-worker-onend-sync.verify.md +3 -3
  188. package/tests/workers/client-worker-refactor.verify.md +18 -18
  189. package/tests/workers/client-worker-ts-cache-invalidation.verify.md +8 -8
  190. package/tests/workers/dev-port-file.verify.md +3 -3
  191. package/tests/workers/ngtsc-build-rootnames-refresh.verify.md +4 -4
  192. package/tests/workers/server-build-context-dispose.verify.md +4 -4
  193. package/tests/workers/server-build-worker-plugin.verify.md +5 -5
  194. package/tests/workers/server-build-worker-refactoring.verify.md +10 -10
  195. package/tests/workers/server-esbuild-context-integration.verify.md +6 -6
  196. package/tests/workers/server-esbuild-context-tsc.verify.md +3 -3
  197. package/dist/sd-cli/tests/angular/fixtures/packages/basic-app/tests/test.fixture.d.ts +0 -3
  198. package/dist/sd-cli/tests/angular/fixtures/packages/basic-app/tests/test.fixture.d.ts.map +0 -1
  199. package/dist/sd-cli/tests/angular/fixtures/packages/basic-app/tests/test.fixture.js +0 -9
  200. package/dist/sd-cli/tests/angular/fixtures/packages/basic-app/tests/test.fixture.js.map +0 -1
@@ -2,38 +2,87 @@ import ts from "typescript";
2
2
  import { fsx } from "@simplysm/core-node";
3
3
 
4
4
  /**
5
- * Worker로 전달할 있는 직렬화된 Diagnostic
5
+ * DiagnosticMessageChain을 worker 경계로 넘기기 위한 직렬화 구조.
6
+ * (chain 구조를 그대로 보존하여 formatter가 원본 들여쓰기/순서대로 출력하게 함)
7
+ */
8
+ export interface SerializedMessageChain {
9
+ messageText: string;
10
+ category: number;
11
+ code: number;
12
+ next?: SerializedMessageChain[];
13
+ }
14
+
15
+ /**
16
+ * Worker로 전달할 수 있는 직렬화된 Diagnostic.
17
+ * ts.Diagnostic의 모든 사용자 가시 필드(detail/relatedInformation/flag)를 보존한다.
6
18
  */
7
19
  export interface SerializedDiagnostic {
8
20
  category: number;
9
21
  code: number;
10
- messageText: string;
22
+ /** messageText chain(overload 에러 등)이거나 단순 문자열. chain이면 구조 그대로 보존 */
23
+ messageText: string | SerializedMessageChain;
11
24
  file?: {
12
25
  fileName: string;
13
26
  };
14
27
  start?: number;
15
28
  length?: number;
29
+ relatedInformation?: SerializedDiagnosticRelatedInformation[];
30
+ /** true 또는 ts가 넘기는 (빈) 객체. formatter가 인식. */
31
+ reportsUnnecessary?: boolean;
32
+ reportsDeprecated?: boolean;
33
+ source?: string;
34
+ }
35
+
36
+ /** ts.DiagnosticRelatedInformation에 대응. file/start/length와 messageText만 가진 축약 구조. */
37
+ export interface SerializedDiagnosticRelatedInformation {
38
+ category: number;
39
+ code: number;
40
+ messageText: string | SerializedMessageChain;
41
+ file?: { fileName: string };
42
+ start?: number;
43
+ length?: number;
44
+ }
45
+
46
+ function serializeMessageChain(chain: ts.DiagnosticMessageChain): SerializedMessageChain {
47
+ return {
48
+ messageText: chain.messageText,
49
+ category: chain.category,
50
+ code: chain.code,
51
+ next: chain.next?.map(serializeMessageChain),
52
+ };
53
+ }
54
+
55
+ function serializeMessageText(
56
+ messageText: string | ts.DiagnosticMessageChain,
57
+ ): string | SerializedMessageChain {
58
+ if (typeof messageText === "string") return messageText;
59
+ return serializeMessageChain(messageText);
16
60
  }
17
61
 
18
62
  /**
19
63
  * Diagnostic을 직렬화 가능한 형태로 변환한다.
20
64
  * (Worker 스레드 간 structured clone 통신을 위해 순환 참조/함수를 제거)
65
+ * messageText chain, relatedInformation, reportsUnnecessary/Deprecated, source 등 모든 detail 보존.
21
66
  */
22
67
  export function serializeDiagnostic(diagnostic: ts.Diagnostic): SerializedDiagnostic {
23
- // DiagnosticMessageChain인 경우 모든 컨텍스트 정보를 보존하기 위해 전체 체인을 평탄화
24
- const messageText = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
25
-
26
68
  return {
27
69
  category: diagnostic.category,
28
70
  code: diagnostic.code,
29
- messageText,
30
- file: diagnostic.file
31
- ? {
32
- fileName: diagnostic.file.fileName,
33
- }
34
- : undefined,
71
+ messageText: serializeMessageText(diagnostic.messageText),
72
+ file: diagnostic.file != null ? { fileName: diagnostic.file.fileName } : undefined,
35
73
  start: diagnostic.start,
36
74
  length: diagnostic.length,
75
+ relatedInformation: diagnostic.relatedInformation?.map((ri) => ({
76
+ category: ri.category,
77
+ code: ri.code,
78
+ messageText: serializeMessageText(ri.messageText),
79
+ file: ri.file != null ? { fileName: ri.file.fileName } : undefined,
80
+ start: ri.start,
81
+ length: ri.length,
82
+ })),
83
+ reportsUnnecessary: diagnostic.reportsUnnecessary != null ? true : undefined,
84
+ reportsDeprecated: diagnostic.reportsDeprecated != null ? true : undefined,
85
+ source: diagnostic.source,
37
86
  };
38
87
  }
39
88
 
@@ -53,32 +102,57 @@ function getScriptKind(fileName: string): ts.ScriptKind {
53
102
  * @param fileCache - 파일 내용 캐시 (같은 파일의 중복 읽기 방지)
54
103
  * @returns 복원된 ts.Diagnostic 객체
55
104
  */
105
+ function deserializeMessageChain(chain: SerializedMessageChain): ts.DiagnosticMessageChain {
106
+ return {
107
+ messageText: chain.messageText,
108
+ category: chain.category,
109
+ code: chain.code,
110
+ next: chain.next?.map(deserializeMessageChain),
111
+ };
112
+ }
113
+
114
+ function deserializeMessageText(
115
+ messageText: string | SerializedMessageChain,
116
+ ): string | ts.DiagnosticMessageChain {
117
+ if (typeof messageText === "string") return messageText;
118
+ return deserializeMessageChain(messageText);
119
+ }
120
+
121
+ function loadFile(fileName: string, fileCache: Map<string, string>): ts.SourceFile {
122
+ if (!fileCache.has(fileName)) {
123
+ fileCache.set(fileName, fsx.existsSync(fileName) ? fsx.readSync(fileName) : "");
124
+ }
125
+ const content = fileCache.get(fileName)!;
126
+ const scriptKind = getScriptKind(fileName);
127
+ return ts.createSourceFile(fileName, content, ts.ScriptTarget.Latest, false, scriptKind);
128
+ }
129
+
56
130
  export function deserializeDiagnostic(
57
131
  serialized: SerializedDiagnostic,
58
132
  fileCache: Map<string, string>,
59
133
  ): ts.Diagnostic {
60
- let file: ts.SourceFile | undefined;
61
- if (serialized.file != null) {
62
- const fileName = serialized.file.fileName;
134
+ const file = serialized.file != null ? loadFile(serialized.file.fileName, fileCache) : undefined;
63
135
 
64
- // 캐시된 파일 내용 가져오기 (없으면 읽어서 캐시)
65
- // 파일이 삭제되었거나 접근 불가능하면 빈 내용으로 처리
66
- // (소스 코드 컨텍스트는 표시되지 않지만 진단 메시지는 정상 표시됨)
67
- if (!fileCache.has(fileName)) {
68
- fileCache.set(fileName, fsx.existsSync(fileName) ? fsx.readSync(fileName) : "");
69
- }
70
- const content = fileCache.get(fileName)!;
71
-
72
- const scriptKind = getScriptKind(fileName);
73
- file = ts.createSourceFile(fileName, content, ts.ScriptTarget.Latest, false, scriptKind);
74
- }
136
+ const relatedInformation: ts.DiagnosticRelatedInformation[] | undefined =
137
+ serialized.relatedInformation?.map((ri) => ({
138
+ category: ri.category,
139
+ code: ri.code,
140
+ messageText: deserializeMessageText(ri.messageText),
141
+ file: ri.file != null ? loadFile(ri.file.fileName, fileCache) : undefined,
142
+ start: ri.start,
143
+ length: ri.length,
144
+ }));
75
145
 
76
146
  return {
77
147
  category: serialized.category,
78
148
  code: serialized.code,
79
- messageText: serialized.messageText,
149
+ messageText: deserializeMessageText(serialized.messageText),
80
150
  file,
81
151
  start: serialized.start,
82
152
  length: serialized.length,
153
+ relatedInformation,
154
+ reportsUnnecessary: serialized.reportsUnnecessary === true ? {} : undefined,
155
+ reportsDeprecated: serialized.reportsDeprecated === true ? {} : undefined,
156
+ source: serialized.source,
83
157
  };
84
158
  }
@@ -1,8 +1,8 @@
1
1
  import { formatMessagesSync, type PartialMessage } from "esbuild";
2
- import { consola } from "consola";
2
+ import { createLazyLogger } from "../runtime/lazy-logger";
3
3
  import type { BuildResult } from "../runtime/ResultCollector";
4
4
 
5
- const logger = consola.withTag("sd:cli:output");
5
+ const logger = createLazyLogger("sd:cli:output");
6
6
 
7
7
  /**
8
8
  * esbuild Message 배열을 포맷된 문자열 배열로 변환한다.
@@ -1,6 +1,6 @@
1
1
  import path from "path";
2
- import { consola } from "consola";
3
2
  import { pathx } from "@simplysm/core-node";
3
+ import { createLazyLogger } from "../runtime/lazy-logger";
4
4
  import type {
5
5
  BuildTarget,
6
6
  SdBuildPackageConfig,
@@ -10,7 +10,7 @@ import type {
10
10
  SdServerPackageConfig,
11
11
  } from "../sd-config.types";
12
12
 
13
- const logger = consola.withTag("sd:cli:package-classify");
13
+ const logger = createLazyLogger("sd:cli:package-classify");
14
14
 
15
15
  /**
16
16
  * 패키지 config를 순회하며 null 필터링 + target 필터링을 수행한다.
@@ -1,14 +1,14 @@
1
1
  import path from "path";
2
2
  import fs from "fs";
3
- import { consola } from "consola";
4
3
  import { SdError } from "@simplysm/core-common";
5
4
  import { pathx } from "@simplysm/core-node";
5
+ import { createLazyLogger } from "../runtime/lazy-logger";
6
6
  import type {
7
7
  SdBuildPackageConfig,
8
8
  SdPackageConfig,
9
9
  } from "../sd-config.types";
10
10
 
11
- const logger = consola.withTag("sd:cli:package-utils");
11
+ const logger = createLazyLogger("sd:cli:package-utils");
12
12
 
13
13
  /**
14
14
  * import.meta.dirname에서 위로 탐색하여 package.json을 찾고 패키지 루트를 반환한다.
@@ -1,10 +1,10 @@
1
1
  import { createJiti } from "jiti";
2
2
  import { SdError } from "@simplysm/core-common";
3
3
  import { fsx, pathx } from "@simplysm/core-node";
4
- import { consola } from "consola";
4
+ import { createLazyLogger } from "../runtime/lazy-logger";
5
5
  import type { SdConfig, SdConfigParams } from "../sd-config.types";
6
6
 
7
- const logger = consola.withTag("sd:cli:sd-config");
7
+ const logger = createLazyLogger("sd:cli:sd-config");
8
8
 
9
9
  /**
10
10
  * sd.config.ts를 로드한다.
@@ -2,9 +2,9 @@ import path from "path";
2
2
  import fs from "fs";
3
3
  import ts from "typescript";
4
4
  import { pathx } from "@simplysm/core-node";
5
- import { consola } from "consola";
5
+ import { createLazyLogger } from "../runtime/lazy-logger";
6
6
 
7
- const logger = consola.withTag("sd:cli:tsconfig");
7
+ const logger = createLazyLogger("sd:cli:tsconfig");
8
8
 
9
9
  //#region TypecheckEnv
10
10
 
@@ -110,10 +110,9 @@ export function getPackageSourceFiles(
110
110
  const srcDir = path.join(pkgDir, "src");
111
111
  const files = parsedConfig.fileNames.filter((f) => {
112
112
  if (pathx.isChildPath(f, srcDir)) return true;
113
- if (f.endsWith(".fixture.ts")) return true;
114
113
  return false;
115
114
  });
116
- logger.debug(`소스 파일 필터링: ${parsedConfig.fileNames.length}개 중 ${files.length}개 (src/ + fixtures)`);
115
+ logger.debug(`소스 파일 필터링: ${parsedConfig.fileNames.length}개 중 ${files.length}개 (src/ only)`);
117
116
  return files;
118
117
  }
119
118
 
@@ -2,15 +2,15 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] enableHmr 프로퍼티가 AngularCompilerOptions에서 제거됨: `angular-compiler.ts` 인터페이스에 `enableHmr` 없음 확인
6
- - [x] HMR_MODIFIED_FILE_LIMIT 상수가 제거됨: `angular-compiler.ts`에서 해당 상수 없음 확인
7
- - [x] collectHmrCandidates import가 제거됨: `angular-compiler.ts`에서 `hmr-candidates` import 없음 확인
8
- - [x] stale source file 수집 로직이 제거됨: `angular-compiler.ts`에서 `staleSourceFiles`, `useHmr` 변수 없음 확인
9
- - [x] enableHmr 프로퍼티가 AngularBuildPipelineOptions에서 제거됨: `angular-build-pipeline.ts` 인터페이스에 `enableHmr` 없음 확인
10
- - [x] templateUpdates 프로퍼티가 PipelineResult에서 제거됨: `angular-build-pipeline.ts` 인터페이스에 `templateUpdates` 없음 확인
11
- - [x] vite-angular-plugin.ts의 `enableHmr: false` 제거됨: Pipeline 생성 시 `enableHmr` 옵션 없음 확인
12
- - [x] hmr-candidates.ts 파일 삭제됨: `src/utils/hmr-candidates.ts` 파일 존재하지 않음
13
- - [x] angular-compiler-hmr.spec.ts 삭제됨: `tests/angular/angular-compiler-hmr.spec.ts` 파일 존재하지 않음
14
- - [x] hmr-candidates.spec.ts 삭제됨: `tests/angular/hmr-candidates.spec.ts` 파일 존재하지 않음
15
- - [x] client.worker.ts 변경 없음: `client.worker.ts`는 `createCompilerPlugin` 경로를 사용하며 AngularCompiler를 직접 참조하지 않음
16
- - [x] hmr-service.ts, hmr-client-script.ts, esbuild-client-config.ts 변경 없음: client.worker.ts 경로의 HMR 인프라는 그대로 유지됨
5
+ - enableHmr 프로퍼티가 AngularCompilerOptions에서 제거됨: `angular-compiler.ts` 인터페이스에 `enableHmr` 없음 확인
6
+ - HMR_MODIFIED_FILE_LIMIT 상수가 제거됨: `angular-compiler.ts`에서 해당 상수 없음 확인
7
+ - collectHmrCandidates import가 제거됨: `angular-compiler.ts`에서 `hmr-candidates` import 없음 확인
8
+ - stale source file 수집 로직이 제거됨: `angular-compiler.ts`에서 `staleSourceFiles`, `useHmr` 변수 없음 확인
9
+ - enableHmr 프로퍼티가 AngularBuildPipelineOptions에서 제거됨: `angular-build-pipeline.ts` 인터페이스에 `enableHmr` 없음 확인
10
+ - templateUpdates 프로퍼티가 PipelineResult에서 제거됨: `angular-build-pipeline.ts` 인터페이스에 `templateUpdates` 없음 확인
11
+ - vite-angular-plugin.ts의 `enableHmr: false` 제거됨: Pipeline 생성 시 `enableHmr` 옵션 없음 확인
12
+ - hmr-candidates.ts 파일 삭제됨: `src/utils/hmr-candidates.ts` 파일 존재하지 않음
13
+ - angular-compiler-hmr.spec.ts 삭제됨: `tests/angular/angular-compiler-hmr.spec.ts` 파일 존재하지 않음
14
+ - hmr-candidates.spec.ts 삭제됨: `tests/angular/hmr-candidates.spec.ts` 파일 존재하지 않음
15
+ - client.worker.ts 변경 없음: `client.worker.ts`는 `createCompilerPlugin` 경로를 사용하며 AngularCompiler를 직접 참조하지 않음
16
+ - hmr-service.ts, hmr-client-script.ts, esbuild-client-config.ts 변경 없음: client.worker.ts 경로의 HMR 인프라는 그대로 유지됨
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] `SdAngularPluginOptions.onBuild` 타입에서 `lint?` 필드가 제거됨: `vite-angular-plugin.ts:32-35` — `result` 타입이 `{ success: boolean; errors?: string[]; warnings?: string[] }` 으로 변경됨, `lint?` 없음
6
- - [x] `CreateClientViteConfigOptions.onBuild` 타입에서 `lint?` 필드가 제거됨: `vite-config.ts:34-37` — 동일하게 `lint?` 없음
7
- - [x] `vite-angular-plugin.ts`에서 `LintWithProgramResult` import 제거됨: import 목록에 해당 import 없음
8
- - [x] `vite-angular-plugin.ts`의 3개 `onBuild` 호출 지점(buildStart:321, handleHotUpdate:409, handleHotUpdate:433)에서 lint 미전달 — 기존에도 전달하지 않았으므로 변경 없음, 타입 정합
5
+ - `SdAngularPluginOptions.onBuild` 타입에서 `lint?` 필드가 제거됨: `vite-angular-plugin.ts:32-35` — `result` 타입이 `{ success: boolean; errors?: string[]; warnings?: string[] }` 으로 변경됨, `lint?` 없음
6
+ - `CreateClientViteConfigOptions.onBuild` 타입에서 `lint?` 필드가 제거됨: `vite-config.ts:34-37` — 동일하게 `lint?` 없음
7
+ - `vite-angular-plugin.ts`에서 `LintWithProgramResult` import 제거됨: import 목록에 해당 import 없음
8
+ - `vite-angular-plugin.ts`의 3개 `onBuild` 호출 지점(buildStart:321, handleHotUpdate:409, handleHotUpdate:433)에서 lint 미전달 — 기존에도 전달하지 않았으므로 변경 없음, 타입 정합
@@ -2,12 +2,12 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] AngularBuildPipeline import 제거: `vite-angular-plugin.ts:6` — `SdTsCompiler` import으로 교체, `AngularBuildPipeline` 미사용
6
- - [x] SdTsCompiler 인스턴스 생성: `:69-81` — `new SdTsCompiler({ pkgDir, cwd, output: { js: true, dts: false }, sourceFileCache, compilerOptionsTransformer })` 올바르게 구성
7
- - [x] compileAsync 호출: `:90` — `sdTsCompiler.compileAsync(modifiedFiles)` 호출, modifiedFiles는 pendingWatchChanges에서 수집
8
- - [x] emitResults → emittedFilesBySource 매핑: `:93-95` — `pathx.posix(sourceFileName)` 키로 저장
9
- - [x] transform 훅: `:107-124` — `emittedFilesBySource.get(normalizedId)` 조회, 인라인 소스맵 분리 유지
10
- - [x] buildEnd에서 sdTsCompiler 참조 해제: `:127` — `sdTsCompiler = undefined`
11
- - [x] watch 모드 증분 빌드: `:61-66` — pendingWatchChanges를 modifiedFiles로 전달, compileAsync에서 증분 처리
12
- - [x] 이미 초기화됐고 변경 없으면 건너뜀: `:84-87` — `emittedFilesBySource.size > 0 && modifiedFiles == null` 조건
13
- - [x] 기존 테스트 회귀: vite-angular-plugin.spec.ts 6개, vite-angular-plugin-vitest.spec.ts + legacy-watch.spec.ts 5개 모두 통과
5
+ - AngularBuildPipeline import 제거: `vite-angular-plugin.ts:6` — `SdTsCompiler` import으로 교체, `AngularBuildPipeline` 미사용
6
+ - SdTsCompiler 인스턴스 생성: `:69-81` — `new SdTsCompiler({ pkgDir, cwd, output: { js: true, dts: false }, sourceFileCache, compilerOptionsTransformer })` 올바르게 구성
7
+ - compileAsync 호출: `:90` — `sdTsCompiler.compileAsync(modifiedFiles)` 호출, modifiedFiles는 pendingWatchChanges에서 수집
8
+ - emitResults → emittedFilesBySource 매핑: `:93-95` — `pathx.posix(sourceFileName)` 키로 저장
9
+ - transform 훅: `:107-124` — `emittedFilesBySource.get(normalizedId)` 조회, 인라인 소스맵 분리 유지
10
+ - buildEnd에서 sdTsCompiler 참조 해제: `:127` — `sdTsCompiler = undefined`
11
+ - watch 모드 증분 빌드: `:61-66` — pendingWatchChanges를 modifiedFiles로 전달, compileAsync에서 증분 처리
12
+ - 이미 초기화됐고 변경 없으면 건너뜀: `:84-87` — `emittedFilesBySource.size > 0 && modifiedFiles == null` 조건
13
+ - 기존 테스트 회귀: vite-angular-plugin.spec.ts 6개, vite-angular-plugin-vitest.spec.ts + legacy-watch.spec.ts 5개 모두 통과
@@ -2,19 +2,19 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] vite-config.ts 삭제됨: `ls packages/sd-cli/src/utils/vite-config.ts` → 파일 없음 확인
6
- - [x] vite-scope-watch-plugin.ts 삭제됨: `ls packages/sd-cli/src/utils/vite-scope-watch-plugin.ts` → 파일 없음 확인
7
- - [x] vite-postcss-inline-plugin.ts 삭제됨: `ls packages/sd-cli/src/angular/vite-postcss-inline-plugin.ts` → 파일 없음 확인
8
- - [x] vite-pwa-plugin.ts 삭제됨: `ls packages/sd-cli/src/utils/vite-pwa-plugin.ts` → 파일 없음 확인
9
- - [x] vite-angular-plugin.ts에서 config() 훅 유지: config()는 isDev, pkgConfig, resolvedPkgDir 초기화에 필수. Vitest가 Vite plugin lifecycle을 호출하므로 유지. 단, optimizeDeps/define 반환값 제거됨
10
- - [x] vite-angular-plugin.ts에서 configResolved() 훅 유지: enableSourcemap 설정에 필요. 단, prebundleTransformer 생성 제거됨
11
- - [x] handleHotUpdate() 제거됨: HMR 배칭(pendingHmrFiles, hmrBatchTimer, processHmrBatch) 모두 제거됨
12
- - [x] configureServer() 제거됨: devServer, isDevServer, angularComponentMiddleware 모두 제거됨
13
- - [x] onBuildStart/onBuild 콜백 제거됨: SdAngularPluginOptions에서 onBuildStart, onBuild 필드 삭제됨. buildStart()에서 options.onBuild 호출 제거됨
14
- - [x] resolveReplaceDeps() 제거됨: scope watch 관련 replaceDepDistPaths, resolveReplaceDepEntries import 모두 제거됨
15
- - [x] watchChange(id) 유지됨: pendingWatchChanges에 파일 경로 수집. Vitest watch 모드에서 캐시 무효화에 사용
16
- - [x] buildStart() 유지됨: tsconfig 파싱, AngularSourceFileCache 생성/재사용, AngularBuildPipeline 초기화, 전체/증분 컴파일 수행. enableHmr: false로 고정 (Vitest에서 HMR 불필요)
17
- - [x] transform() 유지됨: .ts 파일에 대해 Pipeline emit JS 반환 + JavaScriptTransformer 적용. query param 제거 및 인라인 소스맵 분리 로직 유지
18
- - [x] buildEnd() 간소화됨: isDev 분기 제거. 항상 jsTransformer.close() + pipeline 해제. prebundleTransformer 제거
19
- - [x] Vite 타입 import 축소: `ModuleNode`, `ViteDevServer` import 제거됨. `Plugin` 타입만 유지
20
- - [x] 미사용 import 제거: `createHash`, `fsp`, `fs`, `IncomingMessage`, `ServerResponse`, `SdConfig`, `resolveReplaceDepEntries` 제거됨
5
+ - vite-config.ts 삭제됨: `ls packages/sd-cli/src/utils/vite-config.ts` → 파일 없음 확인
6
+ - vite-scope-watch-plugin.ts 삭제됨: `ls packages/sd-cli/src/utils/vite-scope-watch-plugin.ts` → 파일 없음 확인
7
+ - vite-postcss-inline-plugin.ts 삭제됨: `ls packages/sd-cli/src/angular/vite-postcss-inline-plugin.ts` → 파일 없음 확인
8
+ - vite-pwa-plugin.ts 삭제됨: `ls packages/sd-cli/src/utils/vite-pwa-plugin.ts` → 파일 없음 확인
9
+ - vite-angular-plugin.ts에서 config() 훅 유지: config()는 isDev, pkgConfig, resolvedPkgDir 초기화에 필수. Vitest가 Vite plugin lifecycle을 호출하므로 유지. 단, optimizeDeps/define 반환값 제거됨
10
+ - vite-angular-plugin.ts에서 configResolved() 훅 유지: enableSourcemap 설정에 필요. 단, prebundleTransformer 생성 제거됨
11
+ - handleHotUpdate() 제거됨: HMR 배칭(pendingHmrFiles, hmrBatchTimer, processHmrBatch) 모두 제거됨
12
+ - configureServer() 제거됨: devServer, isDevServer, angularComponentMiddleware 모두 제거됨
13
+ - onBuildStart/onBuild 콜백 제거됨: SdAngularPluginOptions에서 onBuildStart, onBuild 필드 삭제됨. buildStart()에서 options.onBuild 호출 제거됨
14
+ - resolveReplaceDeps() 제거됨: scope watch 관련 replaceDepDistPaths, resolveReplaceDepEntries import 모두 제거됨
15
+ - watchChange(id) 유지됨: pendingWatchChanges에 파일 경로 수집. Vitest watch 모드에서 캐시 무효화에 사용
16
+ - buildStart() 유지됨: tsconfig 파싱, AngularSourceFileCache 생성/재사용, AngularBuildPipeline 초기화, 전체/증분 컴파일 수행. enableHmr: false로 고정 (Vitest에서 HMR 불필요)
17
+ - transform() 유지됨: .ts 파일에 대해 Pipeline emit JS 반환 + JavaScriptTransformer 적용. query param 제거 및 인라인 소스맵 분리 로직 유지
18
+ - buildEnd() 간소화됨: isDev 분기 제거. 항상 jsTransformer.close() + pipeline 해제. prebundleTransformer 제거
19
+ - Vite 타입 import 축소: `ModuleNode`, `ViteDevServer` import 제거됨. `Plugin` 타입만 유지
20
+ - 미사용 import 제거: `createHash`, `fsp`, `fs`, `IncomingMessage`, `ServerResponse`, `SdConfig`, `resolveReplaceDepEntries` 제거됨
@@ -2,10 +2,10 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] configureAndroid이 capacitor-android.ts에서 export된다: line 13 `export async function configureAndroid`
6
- - [x] findJava21이 capacitor-android.ts에서 export된다: line 53 `export async function findJava21`
7
- - [x] findAndroidSdk가 capacitor-android.ts에서 export된다: line 76 `export async function findAndroidSdk`
8
- - [x] 내부 configure 함수들(_configureJavaHomePath 등)은 export되지 않는다: `^export` 검색 결과 3개만 확인
9
- - [x] Capacitor 클래스의 _validateTools가 findAndroidSdk/findJava21을 import하여 사용한다: line 8 import, line 217/229 호출
10
- - [x] Capacitor 클래스에서 9개 Android 설정 private 메서드가 삭제되었다: `_configureAndroid` 등 검색 결과 0건
11
- - [x] capacitor.ts에서 env import가 제거되었다: `import.*env.*from` 검색 결과 0건
5
+ - configureAndroid이 capacitor-android.ts에서 export된다: line 13 `export async function configureAndroid`
6
+ - findJava21이 capacitor-android.ts에서 export된다: line 53 `export async function findJava21`
7
+ - findAndroidSdk가 capacitor-android.ts에서 export된다: line 76 `export async function findAndroidSdk`
8
+ - 내부 configure 함수들(_configureJavaHomePath 등)은 export되지 않는다: `^export` 검색 결과 3개만 확인
9
+ - Capacitor 클래스의 _validateTools가 findAndroidSdk/findJava21을 import하여 사용한다: line 8 import, line 217/229 호출
10
+ - Capacitor 클래스에서 9개 Android 설정 private 메서드가 삭제되었다: `_configureAndroid` 등 검색 결과 0건
11
+ - capacitor.ts에서 env import가 제거되었다: `import.*env.*from` 검색 결과 0건
@@ -2,8 +2,8 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] npm 배포 로직(publishNpm)이 npm-publisher.ts에 위치: `src/commands/publish/npm-publisher.ts:9`
6
- - [x] 로컬 복사 로직(publishToLocal)이 local-publisher.ts에 위치: `src/commands/publish/local-publisher.ts:9`
7
- - [x] index.ts의 publishPackage가 각 publisher 호출로 교체됨: `src/commands/publish/index.ts:163-171` — type별 분기가 publishNpm, publishToLocal, publishToStorage 호출
8
- - [x] export 경로 불변: `import { runPublish } from "./commands/publish"` — sd-cli-entry.ts에서 동일 경로로 resolve됨 (commands/publish/index.ts)
9
- - [x] 버전 업그레이드, Git, 빌드 로직은 index.ts에 유지: upgradeVersion(:99), Git commit/tag/push(:487-499), runBuild 호출(:459)
5
+ - npm 배포 로직(publishNpm)이 npm-publisher.ts에 위치: `src/commands/publish/npm-publisher.ts:9`
6
+ - 로컬 복사 로직(publishToLocal)이 local-publisher.ts에 위치: `src/commands/publish/local-publisher.ts:9`
7
+ - index.ts의 publishPackage가 각 publisher 호출로 교체됨: `src/commands/publish/index.ts:163-171` — type별 분기가 publishNpm, publishToLocal, publishToStorage 호출
8
+ - export 경로 불변: `import { runPublish } from "./commands/publish"` — sd-cli-entry.ts에서 동일 경로로 resolve됨 (commands/publish/index.ts)
9
+ - 버전 업그레이드, Git, 빌드 로직은 index.ts에 유지: upgradeVersion(:99), Git commit/tag/push(:487-499), runBuild 호출(:459)
@@ -2,12 +2,12 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] version-upgrade.ts에 upgradeVersion, computePublishLevels, PackageJson이 export됨: `src/commands/publish/version-upgrade.ts` 확인 완료
6
- - [x] env-utils.ts에 replaceEnvVariables, waitWithCountdown이 export됨: `src/commands/publish/env-utils.ts` 확인 완료
7
- - [x] index.ts에서 추출 함수가 제거되고 import로 대체됨: `index.ts:14-15`에서 version-upgrade, env-utils import 확인
8
- - [x] index.ts export 불변 — runPublish, PublishOptions만 export: `index.ts:22` PublishOptions, `index.ts:76` runPublish 확인
9
- - [x] sd-cli-entry.ts의 import 경로 불변: `sd-cli-entry.ts:12` `import { runPublish } from "./commands/publish"` 유지
10
- - [x] 함수 시그니처 불변: upgradeVersion(cwd, allPkgPaths, dryRun), computePublishLevels(publishPkgs), replaceEnvVariables(str, version, projectPath), waitWithCountdown(message, seconds) 모두 원본과 동일
11
- - [x] index.ts LOC 축소: 639 → 455 LOC (목표 ~300 이하는 미달이나, 오케스트레이션 자체가 ~280 LOC이므로 적정)
12
- - [x] 총 LOC 보존: 631 total ≈ 639 original (import/export 차이)
13
- - [x] 기존 테스트 40개 전량 통과: vitest run 결과 40 passed
5
+ - version-upgrade.ts에 upgradeVersion, computePublishLevels, PackageJson이 export됨: `src/commands/publish/version-upgrade.ts` 확인 완료
6
+ - env-utils.ts에 replaceEnvVariables, waitWithCountdown이 export됨: `src/commands/publish/env-utils.ts` 확인 완료
7
+ - index.ts에서 추출 함수가 제거되고 import로 대체됨: `index.ts:14-15`에서 version-upgrade, env-utils import 확인
8
+ - index.ts export 불변 — runPublish, PublishOptions만 export: `index.ts:22` PublishOptions, `index.ts:76` runPublish 확인
9
+ - sd-cli-entry.ts의 import 경로 불변: `sd-cli-entry.ts:12` `import { runPublish } from "./commands/publish"` 유지
10
+ - 함수 시그니처 불변: upgradeVersion(cwd, allPkgPaths, dryRun), computePublishLevels(publishPkgs), replaceEnvVariables(str, version, projectPath), waitWithCountdown(message, seconds) 모두 원본과 동일
11
+ - index.ts LOC 축소: 639 → 455 LOC (목표 ~300 이하는 미달이나, 오케스트레이션 자체가 ~280 LOC이므로 적정)
12
+ - 총 LOC 보존: 631 total ≈ 639 original (import/export 차이)
13
+ - 기존 테스트 40개 전량 통과: vitest run 결과 40 passed
@@ -2,6 +2,6 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] Set 생성: `publish.ts:773` — `const publishedSet = new Set(publishedPackages)` 확인
6
- - [x] Set.has() 사용: `publish.ts:774` — `allPkgNames.filter(n => !publishedSet.has(n))` 확인
7
- - [x] 동작 동등성: `Array.includes()` → `Set.has()` 변환은 동일한 boolean 결과를 반환하���로 기능 동등
5
+ - Set 생성: `publish.ts:773` — `const publishedSet = new Set(publishedPackages)` 확인
6
+ - Set.has() 사용: `publish.ts:774` — `allPkgNames.filter(n => !publishedSet.has(n))` 확인
7
+ - 동작 동등성: `Array.includes()` → `Set.has()` 변환은 동일한 boolean 결과를 반환하���로 기능 동등
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] SSH 인증 로직(ensureSshAuth, testSshKeyAuth, registerSshPublicKey)이 storage-publisher.ts에 위치: `src/commands/publish/storage-publisher.ts:55` (ensureSshAuth), `:128` (testSshKeyAuth), `:157` (registerSshPublicKey)
6
- - [x] 스토리지 배포 로직(publishToStorage)이 storage-publisher.ts에 위치: `src/commands/publish/storage-publisher.ts:17`
7
- - [x] index.ts에서 ensureSshAuth와 publishToStorage를 import하여 사용: `src/commands/publish/index.ts:13`
8
- - [x] import 경로 "./commands/publish"가 디렉토리 구조 변환 후에도 동일하게 resolve: `publish/index.ts`가 Node.js 모듈 resolution에 의해 `commands/publish`로 resolve됨
5
+ - SSH 인증 로직(ensureSshAuth, testSshKeyAuth, registerSshPublicKey)이 storage-publisher.ts에 위치: `src/commands/publish/storage-publisher.ts:55` (ensureSshAuth), `:128` (testSshKeyAuth), `:157` (registerSshPublicKey)
6
+ - 스토리지 배포 로직(publishToStorage)이 storage-publisher.ts에 위치: `src/commands/publish/storage-publisher.ts:17`
7
+ - index.ts에서 ensureSshAuth와 publishToStorage를 import하여 사용: `src/commands/publish/index.ts:13`
8
+ - import 경로 "./commands/publish"가 디렉토리 구조 변환 후에도 동일하게 resolve: `publish/index.ts`가 Node.js 모듈 resolution에 의해 `commands/publish`로 resolve됨
@@ -2,11 +2,11 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] replace-deps.ts:5 — `const logger = consola.withTag("sd:cli:replace-deps")` 모듈-레벨 로거 추가 확인
6
- - [x] replace-deps.ts:24 — `consola.warn(...)` → `logger.warn(...)` 변경 확인
7
- - [x] deployment-phase.ts:66-70 — DRY-RUN 성공 메시지 `debug` → `info` 전환 확인: `dryRun ? logger.info("[DRY-RUN] ...") : logger.debug(...)`
8
- - [x] deployment-phase.ts:76-80 — DRY-RUN 재시도 메시지 `debug` → `info` 전환 확인: 동일 패턴
9
- - [x] deployment-phase.ts:102 — `logger.fail(...)` → `logger.error(...)` 전환 확인
10
- - [x] BuildOrchestrator.ts:251 — `this._logger.success("빌드 실행 완료")` 행 제거 확인: 250행 뒤에 바로 `return` 문
11
- - [x] BuildOrchestrator.ts:477 — `this._logger.info("빌드 완료")` → `this._logger.success("빌드 완료")` 전환 확인
12
- - [x] BuildOrchestrator.ts:232-233 — `this._logger.start("빌드 실행 중...")` 유지 확인: start(232)/success(477) 쌍 정상화
5
+ - replace-deps.ts:5 — `const logger = consola.withTag("sd:cli:replace-deps")` 모듈-레벨 로거 추가 확인
6
+ - replace-deps.ts:24 — `consola.warn(...)` → `logger.warn(...)` 변경 확인
7
+ - deployment-phase.ts:66-70 — DRY-RUN 성공 메시지 `debug` → `info` 전환 확인: `dryRun ? logger.info("[DRY-RUN] ...") : logger.debug(...)`
8
+ - deployment-phase.ts:76-80 — DRY-RUN 재시도 메시지 `debug` → `info` 전환 확인: 동일 패턴
9
+ - deployment-phase.ts:102 — `logger.fail(...)` → `logger.error(...)` 전환 확인
10
+ - BuildOrchestrator.ts:251 — `this._logger.success("빌드 실행 완료")` 행 제거 확인: 250행 뒤에 바로 `return` 문
11
+ - BuildOrchestrator.ts:477 — `this._logger.info("빌드 완료")` → `this._logger.success("빌드 완료")` 전환 확인
12
+ - BuildOrchestrator.ts:232-233 — `this._logger.start("빌드 실행 중...")` 유지 확인: start(232)/success(477) 쌍 정상화
@@ -2,14 +2,14 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] replace-deps/ 서브디렉토리에 3개 파일 존재: `collect-deps.ts`, `replace-deps.ts`, `replace-deps-resolve.ts` — glob으로 확인
6
- - [x] server-externals/ 서브디렉토리에 1개 파일 존재: `server-production-files.ts` — glob으로 확인
7
- - [x] deps/ 루트에 이전 파일 없음: `replace-deps/`, `server-externals/` 서브디렉토리만 존재
8
- - [x] collect-deps.ts 내부 import 수정: `../../utils/package-utils` — 코드 확인
9
- - [x] server-production-files.ts 내부 import 수정: `../../workers/server-build.worker`, `../../esbuild/esbuild-config` — 코드 확인
10
- - [x] replace-deps.ts → replace-deps-resolve.ts 상대 import 변경 없음: 같은 디렉토리 이동으로 `./replace-deps-resolve` 유지 — 코드 확인
11
- - [x] src/ 소비자 7건 import 경로 업데이트: grep으로 이전 경로 참조 0건 확인
12
- - [x] tests/ 소비자 전체 import 경로 업데이트: grep으로 이전 경로 참조 0건 확인
13
- - [x] typecheck 통과 (기존 에러 4건 제외): `pnpm typecheck` 실행 확인
14
- - [x] lint 통과: `pnpm lint sd-cli` 0 에러 확인
15
- - [x] 관련 테스트 통과: replace-deps-watch 2개 파일 5개 테스트 전체 통과 확인
5
+ - replace-deps/ 서브디렉토리에 3개 파일 존재: `collect-deps.ts`, `replace-deps.ts`, `replace-deps-resolve.ts` — glob으로 확인
6
+ - server-externals/ 서브디렉토리에 1개 파일 존재: `server-production-files.ts` — glob으로 확인
7
+ - deps/ 루트에 이전 파일 없음: `replace-deps/`, `server-externals/` 서브디렉토리만 존재
8
+ - collect-deps.ts 내부 import 수정: `../../utils/package-utils` — 코드 확인
9
+ - server-production-files.ts 내부 import 수정: `../../workers/server-build.worker`, `../../esbuild/esbuild-config` — 코드 확인
10
+ - replace-deps.ts → replace-deps-resolve.ts 상대 import 변경 없음: 같은 디렉토리 이동으로 `./replace-deps-resolve` 유지 — 코드 확인
11
+ - src/ 소비자 7건 import 경로 업데이트: grep으로 이전 경로 참조 0건 확인
12
+ - tests/ 소비자 전체 import 경로 업데이트: grep으로 이전 경로 참조 0건 확인
13
+ - typecheck 통과 (기존 에러 4건 제외): `pnpm typecheck` 실행 확인
14
+ - lint 통과: `pnpm lint sd-cli` 0 에러 확인
15
+ - 관련 테스트 통과: replace-deps-watch 2개 파일 5개 테스트 전체 통과 확인
@@ -4,12 +4,12 @@
4
4
 
5
5
  ### Slice 1: Set 중복 검사 + glob 병렬화
6
6
 
7
- - [x] `resolveAllReplaceDepEntries`에서 `entries.some()` 대신 `Set<string>` 사용 확인: `replace-deps-resolve.ts:143`에 `seenTargetPaths = new Set<string>()` 선언, `:205`에서 `seenTargetPaths.has(actualTargetPath)` + `seenTargetPaths.add(actualTargetPath)` 사용. 기존 `entries.some()` 제거됨.
8
- - [x] glob 병렬화 확인: `replace-deps-resolve.ts:167-171`에서 `Promise.all(Object.keys(replaceDeps).map(...))` 사용. 기존 순차 `for` 루프 제거됨. `:172-174`에서 `flatMap`으로 결과를 합침.
9
- - [x] `seenTargetPaths`가 while 루프 바깥에 선언되어 재귀 탐색 전체에 걸쳐 중복 방지가 유지됨 확인.
7
+ - `resolveAllReplaceDepEntries`에서 `entries.some()` 대신 `Set<string>` 사용 확인: `replace-deps-resolve.ts:143`에 `seenTargetPaths = new Set<string>()` 선언, `:205`에서 `seenTargetPaths.has(actualTargetPath)` + `seenTargetPaths.add(actualTargetPath)` 사용. 기존 `entries.some()` 제거됨.
8
+ - glob 병렬화 확인: `replace-deps-resolve.ts:167-171`에서 `Promise.all(Object.keys(replaceDeps).map(...))` 사용. 기존 순차 `for` 루프 제거됨. `:172-174`에서 `flatMap`으로 결과를 합침.
9
+ - `seenTargetPaths`가 while 루프 바깥에 선언되어 재귀 탐색 전체에 걸쳐 중복 방지가 유지됨 확인.
10
10
 
11
11
  ### Slice 2: watch onChange entries 사전 필터링
12
12
 
13
- - [x] `watchReplaceDeps`에서 사전 필터링 확인: `replace-deps.ts:240-242`에 `sourceEntries = entries.filter(e => e.resolvedSourcePath === entry.resolvedSourcePath)` 선언. watcher 생성 전에 필터링되어 클로저에 캡처됨.
14
- - [x] onChange 내부에서 `sourceEntries`만 순회 확인: `replace-deps.ts:252`에서 `for (const e of sourceEntries)` 사용. 기존 `for (const e of entries)` + `if (e.resolvedSourcePath !== entry.resolvedSourcePath) continue;` 패턴이 제거됨.
15
- - [x] `entries` 배열은 `resolveAllReplaceDepEntries` 호출 후 불변이므로, 필터링 결과가 watcher 생명주기 동안 유효함 확인 (`replace-deps.ts:202`에서 `entries` 할당 후 수정 없음).
13
+ - `watchReplaceDeps`에서 사전 필터링 확인: `replace-deps.ts:240-242`에 `sourceEntries = entries.filter(e => e.resolvedSourcePath === entry.resolvedSourcePath)` 선언. watcher 생성 전에 필터링되어 클로저에 캡처됨.
14
+ - onChange 내부에서 `sourceEntries`만 순회 확인: `replace-deps.ts:252`에서 `for (const e of sourceEntries)` 사용. 기존 `for (const e of entries)` + `if (e.resolvedSourcePath !== entry.resolvedSourcePath) continue;` 패턴이 제거됨.
15
+ - `entries` 배열은 `resolveAllReplaceDepEntries` 호출 후 불변이므로, 필터링 결과가 watcher 생명주기 동안 유효함 확인 (`replace-deps.ts:202`에서 `entries` 할당 후 수정 없음).
@@ -6,11 +6,11 @@
6
6
 
7
7
  ## 검증 항목
8
8
 
9
- - [x] **WHY 주석 존재**: `server-production-files.ts:114`에 `// mise.toml은 저장소에서 관리되는 설정 파일이므로, 파싱 실패 시 폴백하지 않고 예외를 전파하여 설정 오류를 즉시 드러낸다.` 주석이 `TOML.parse(miseContent)` 호출(`:115`) 직전에 존재함을 확인
10
- - [x] **명시적 크래시 의도 서술**: 주석이 "저장소에서 관리되는 설정 파일", "폴백하지 않고", "예외를 전파", "설정 오류를 즉시 드러낸다" 표현을 모두 포함하여 wbs에 명시된 WHY를 서술
11
- - [x] **WHAT 서술 지양**: "TOML을 파싱한다" 같은 코드 재서술이 아니라, 폴백을 의도적으로 하지 않는 이유(설정 오류 즉시 노출)를 설명
12
- - [x] **try-catch 미추가**: `:109-121` 블록 전체에 try 키워드 없음을 확인 — 파싱 예외는 상위로 전파됨
13
- - [x] **주석 스타일**: `//` 한 줄 주석 (JSDoc 아님)
14
- - [x] **주석 언어**: 한국어
15
- - [x] **기타 코드 미변경**: `git diff server-production-files.ts` 결과 라인 114의 주석 추가 1줄 외 변경 없음 (아래 명령 실행 결과 참조)
16
- - [x] **기존 테스트 통과**: `pnpm exec vitest run --project node packages/sd-cli/tests/workers/server-build-worker.spec.ts` 25/25 통과, 특히 `generates dist/mise.toml when packageManager=mise` 테스트(TOML.parse 경로 실행)가 통과하여 파싱 로직 회귀 없음을 확인. 참고: 전체 sd-cli 테스트(`packages/sd-cli/tests/`)에서 1건 실패(`esbuild-worker-plugin.acc.spec.ts:143`)가 있으나 이는 Feature 1.1 영역이며 본 Feature 1.3 변경(주석 1줄 추가)과 무관
9
+ - **WHY 주석 존재**: `server-production-files.ts:114`에 `// mise.toml은 저장소에서 관리되는 설정 파일이므로, 파싱 실패 시 폴백하지 않고 예외를 전파하여 설정 오류를 즉시 드러낸다.` 주석이 `TOML.parse(miseContent)` 호출(`:115`) 직전에 존재함을 확인
10
+ - **명시적 크래시 의도 서술**: 주석이 "저장소에서 관리되는 설정 파일", "폴백하지 않고", "예외를 전파", "설정 오류를 즉시 드러낸다" 표현을 모두 포함하여 wbs에 명시된 WHY를 서술
11
+ - **WHAT 서술 지양**: "TOML을 파싱한다" 같은 코드 재서술이 아니라, 폴백을 의도적으로 하지 않는 이유(설정 오류 즉시 노출)를 설명
12
+ - **try-catch 미추가**: `:109-121` 블록 전체에 try 키워드 없음을 확인 — 파싱 예외는 상위로 전파됨
13
+ - **주석 스타일**: `//` 한 줄 주석 (JSDoc 아님)
14
+ - **주석 언어**: 한국어
15
+ - **기타 코드 미변경**: `git diff server-production-files.ts` 결과 라인 114의 주석 추가 1줄 외 변경 없음 (아래 명령 실행 결과 참조)
16
+ - **기존 테스트 통과**: `pnpm exec vitest run --project node packages/sd-cli/tests/workers/server-build-worker.spec.ts` 25/25 통과, 특히 `generates dist/mise.toml when packageManager=mise` 테스트(TOML.parse 경로 실행)가 통과하여 파싱 로직 회귀 없음을 확인. 참고: 전체 sd-cli 테스트(`packages/sd-cli/tests/`)에서 1건 실패(`esbuild-worker-plugin.acc.spec.ts:143`)가 있으나 이는 Feature 1.1 영역이며 본 Feature 1.3 변경(주석 1줄 추가)과 무관
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] try-catch-finally 구조 적용: `electron.ts:348-358` — try 블록에서 writeFile/symlink/lstat 수행, finally에서 정리
6
- - [x] finally에서 testLink, testTarget 각각 unlink: `finally { try { fs.unlinkSync(testLink); } catch {} try { fs.unlinkSync(testTarget); } catch {} }` 확인
7
- - [x] 성공 시에도 파일 정리: try 블록 return 후 finally가 실행되므로 정리 보장
8
- - [x] 실패 시에도 파일 정리: catch 블록 return 후 finally가 실행되므로 정리 보장
5
+ - try-catch-finally 구조 적용: `electron.ts:348-358` — try 블록에서 writeFile/symlink/lstat 수행, finally에서 정리
6
+ - finally에서 testLink, testTarget 각각 unlink: `finally { try { fs.unlinkSync(testLink); } catch {} try { fs.unlinkSync(testTarget); } catch {} }` 확인
7
+ - 성공 시에도 파일 정리: try 블록 return 후 finally가 실행되므로 정리 보장
8
+ - 실패 시에도 파일 정리: catch 블록 return 후 finally가 실행되므로 정리 보장
@@ -2,9 +2,9 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] esbuild-client-config.ts logLevel이 모든 모드에서 "silent"인지: `esbuild-client-config.ts:191` — `logLevel: "silent"` 확인. 기존 `isDev ? "warning" : "silent"` 삼항 연산자 제거됨
6
- - [x] EsbuildClientEngine에 중복 error 핸들러가 없는지: `EsbuildClientEngine.ts:103-110` — setupWatchEvents만 error 이벤트 처리. 기존 `worker.on("error", ...)` 핸들러(logger.error 호출) 제거됨
7
- - [x] EsbuildClientEngine 초기 빌드 실패 시 logger.error 미호출: `EsbuildClientEngine.ts:129-138` — `!result.success` 분기에서 `resultCollector.add()`만 호출. logger.error 줄 제거됨
8
- - [x] BaseEngine에 logger.warn() 블록이 없는지: `BaseEngine.ts:166-180` — build 이벤트 핸들러에 lint 결과 보고만 존재. warnings에 대한 logger.warn() 블록 제거됨
9
- - [x] BaseEngine startWatch 실패 시 logger.debug 사용: `BaseEngine.ts:182-183` — `logger.debug(...)` 확인. 기존 `logger.error(...)` → `logger.debug(...)` 변경됨
10
- - [x] BaseEngine lint 결과 보고 로직 유지: `BaseEngine.ts:170-179` — `event.lint != null` 조건의 ResultCollector 보고 로직이 그대로 유지됨
5
+ - esbuild-client-config.ts logLevel이 모든 모드에서 "silent"인지: `esbuild-client-config.ts:191` — `logLevel: "silent"` 확인. 기존 `isDev ? "warning" : "silent"` 삼항 연산자 제거됨
6
+ - EsbuildClientEngine에 중복 error 핸들러가 없는지: `EsbuildClientEngine.ts:103-110` — setupWatchEvents만 error 이벤트 처리. 기존 `worker.on("error", ...)` 핸들러(logger.error 호출) 제거됨
7
+ - EsbuildClientEngine 초기 빌드 실패 시 logger.error 미호출: `EsbuildClientEngine.ts:129-138` — `!result.success` 분기에서 `resultCollector.add()`만 호출. logger.error 줄 제거됨
8
+ - BaseEngine에 logger.warn() 블록이 없는지: `BaseEngine.ts:166-180` — build 이벤트 핸들러에 lint 결과 보고만 존재. warnings에 대한 logger.warn() 블록 제거됨
9
+ - BaseEngine startWatch 실패 시 logger.debug 사용: `BaseEngine.ts:182-183` — `logger.debug(...)` 확인. 기존 `logger.error(...)` → `logger.debug(...)` 변경됨
10
+ - BaseEngine lint 결과 보고 로직 유지: `BaseEngine.ts:170-179` — `event.lint != null` 조건의 ResultCollector 보고 로직이 그대로 유지됨
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] target 변환 로직 제거됨: `TypecheckOrchestrator.ts:133-142`에서 `config.target === "client" ? { target: "browser" as const } : config` 코드가 제거되고, 원본 `config`가 그대로 `_typecheckTasks`에 저장됨
6
- - [x] createTypecheckEngine 호출: `TypecheckOrchestrator.ts:209`에서 `createBuildEngine` 대신 `createTypecheckEngine`을 호출함
7
- - [x] import 변경: `TypecheckOrchestrator.ts:7`에서 `createBuildEngine` 대신 `createTypecheckEngine`을 import함
8
- - [x] createTypecheckEngine 내부 변환: `engines/index.ts`의 `createTypecheckEngine`이 client target을 `{ target: "browser" }`로 변환하여 `createBuildEngine`에 위임함
5
+ - target 변환 로직 제거됨: `TypecheckOrchestrator.ts:133-142`에서 `config.target === "client" ? { target: "browser" as const } : config` 코드가 제거되고, 원본 `config`가 그대로 `_typecheckTasks`에 저장됨
6
+ - createTypecheckEngine 호출: `TypecheckOrchestrator.ts:209`에서 `createBuildEngine` 대신 `createTypecheckEngine`을 호출함
7
+ - import 변경: `TypecheckOrchestrator.ts:7`에서 `createBuildEngine` 대신 `createTypecheckEngine`을 import함
8
+ - createTypecheckEngine 내부 변환: `engines/index.ts`의 `createTypecheckEngine`이 client target을 `{ target: "browser" }`로 변환하여 `createBuildEngine`에 위임함