@simplysm/sd-cli 14.0.48 → 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 (75) hide show
  1. package/package.json +5 -5
  2. package/tests/angular/angular-compiler-hmr-removal.verify.md +12 -12
  3. package/tests/angular/onbuild-lint-removal.verify.md +4 -4
  4. package/tests/angular/vite-angular-plugin-sdtscompiler.verify.md +9 -9
  5. package/tests/angular/vite-angular-plugin-vitest.verify.md +16 -16
  6. package/tests/capacitor/capacitor-android-exports.verify.md +7 -7
  7. package/tests/commands/publish-npm-local-split.verify.md +5 -5
  8. package/tests/commands/publish-responsibility-split.verify.md +9 -9
  9. package/tests/commands/publish-set.verify.md +3 -3
  10. package/tests/commands/publish-storage-split.verify.md +4 -4
  11. package/tests/commands/slice3-severity-cleanup.verify.md +8 -8
  12. package/tests/deps/deps-directory-separation.verify.md +11 -11
  13. package/tests/deps/replace-deps/replace-deps-perf.verify.md +6 -6
  14. package/tests/deps/server-externals/mise-toml-parse-intent.verify.md +8 -8
  15. package/tests/electron/electron-symlink-cleanup.verify.md +4 -4
  16. package/tests/engines/engine-duplicate-output-removal.verify.md +6 -6
  17. package/tests/engines/engine-typecheck-selection.verify.md +4 -4
  18. package/tests/engines/esbuild-client-engine.verify.md +11 -11
  19. package/tests/engines/normalize-result.verify.md +5 -5
  20. package/tests/engines/vite-dependency-cleanup.verify.md +11 -11
  21. package/tests/esbuild/esbuild-angular-compiler-plugin-hmr.verify.md +10 -10
  22. package/tests/esbuild/esbuild-angular-compiler-plugin-onload.verify.md +17 -17
  23. package/tests/esbuild/esbuild-angular-compiler-plugin-onstart-extraction.verify.md +12 -12
  24. package/tests/esbuild/esbuild-angular-compiler-plugin-sdtscompiler.verify.md +11 -11
  25. package/tests/esbuild/esbuild-angular-compiler-plugin-stylesheet.verify.md +13 -13
  26. package/tests/esbuild/esbuild-angular-compiler-plugin-worker.verify.md +32 -32
  27. package/tests/esbuild/esbuild-angular-compiler-plugin.verify.md +9 -9
  28. package/tests/esbuild/esbuild-postcss-plugin-chunking.verify.md +3 -3
  29. package/tests/esbuild/esbuild-tsc-plugin-imports.verify.md +9 -9
  30. package/tests/esbuild/esbuild-worker-plugin-node.verify.md +7 -7
  31. package/tests/esbuild/esbuild-worker-plugin.verify.md +3 -3
  32. package/tests/orchestrators/dist-delete-watcher.verify.md +6 -6
  33. package/tests/orchestrators/orchestrator-baseenv.verify.md +6 -6
  34. package/tests/orchestrators/orchestrator-diagnostic-formatting.verify.md +6 -6
  35. package/tests/orchestrators/orchestrator-initializemode-signature.verify.md +5 -5
  36. package/tests/orchestrators/slice1-stdout-to-consola.verify.md +6 -6
  37. package/tests/sd-cli-catch-all.verify.md +3 -3
  38. package/tests/sd-cli-log-tag.verify.md +7 -7
  39. package/tests/ts-compiler/SdTsCompiler-affected-files.verify.md +4 -4
  40. package/tests/ts-compiler/SdTsCompiler-diagnostics.verify.md +8 -8
  41. package/tests/ts-compiler/SdTsCompiler-emit.verify.md +5 -5
  42. package/tests/ts-compiler/SdTsCompiler.verify.md +20 -20
  43. package/tests/ts-compiler/scss-lint-integration.verify.md +10 -10
  44. package/tests/utils/copy-public-outdir.verify.md +4 -4
  45. package/tests/utils/dev-http-server.verify.md +4 -4
  46. package/tests/utils/engine-watch-events.verify.md +8 -8
  47. package/tests/utils/esbuild-client-config-integration.verify.md +5 -5
  48. package/tests/utils/esbuild-client-config-postcss.verify.md +2 -2
  49. package/tests/utils/esbuild-client-config.verify.md +16 -16
  50. package/tests/utils/esbuild-index-html.verify.md +6 -6
  51. package/tests/utils/esbuild-pwa.verify.md +5 -5
  52. package/tests/utils/esbuild-scss-plugin.verify.md +4 -4
  53. package/tests/utils/hmr-service.verify.md +10 -10
  54. package/tests/utils/lint-core-import-paths.verify.md +6 -6
  55. package/tests/utils/replace-deps-split.verify.md +11 -11
  56. package/tests/utils/replace-deps-watch.verify.md +5 -5
  57. package/tests/utils/server-production-files-import-paths.verify.md +10 -10
  58. package/tests/utils/vite-config-cleanup.verify.md +3 -3
  59. package/tests/workers/build-watch-paths-library.verify.md +6 -6
  60. package/tests/workers/build-watch-paths-ngtsc-server.verify.md +8 -8
  61. package/tests/workers/client-worker-browser-support.verify.md +3 -3
  62. package/tests/workers/client-worker-cleanup.verify.md +4 -4
  63. package/tests/workers/client-worker-initial-build-error.verify.md +3 -3
  64. package/tests/workers/client-worker-initial-build-warnings.verify.md +3 -3
  65. package/tests/workers/client-worker-mtime-incremental.verify.md +6 -6
  66. package/tests/workers/client-worker-onend-sync.verify.md +3 -3
  67. package/tests/workers/client-worker-refactor.verify.md +18 -18
  68. package/tests/workers/client-worker-ts-cache-invalidation.verify.md +8 -8
  69. package/tests/workers/dev-port-file.verify.md +3 -3
  70. package/tests/workers/ngtsc-build-rootnames-refresh.verify.md +4 -4
  71. package/tests/workers/server-build-context-dispose.verify.md +4 -4
  72. package/tests/workers/server-build-worker-plugin.verify.md +5 -5
  73. package/tests/workers/server-build-worker-refactoring.verify.md +10 -10
  74. package/tests/workers/server-esbuild-context-integration.verify.md +6 -6
  75. package/tests/workers/server-esbuild-context-tsc.verify.md +3 -3
@@ -4,14 +4,14 @@
4
4
 
5
5
  ### Slice 1: BaseEngine 적용
6
6
 
7
- - [x] BaseEngine lint 결과 보고 유지: `BaseEngine.ts:148-157` — build 이벤트에서 `event.lint`가 있으면 lint BuildResult를 ResultCollector에 추가. 기존 로직 그대로 유지됨.
8
- - [x] BaseEngine 경고 로깅 유지: `BaseEngine.ts:144-146` — `event.build.warnings`가 있으면 `logger.warn` 호출. 기존 로직 그대로 유지됨.
9
- - [x] setupWatchEvents가 index.ts의 public export에 포함되지 않음: 내부 유틸리티이므로 패키지 외부 API 불변. `engines/index.ts`의 export 목록에 engine-watch-events 없음 확인.
10
- - [x] resolveInitialBuild가 _callStartWatch catch에서 호출됨: `BaseEngine.ts:162-164` — `this._callStartWatch(output).catch(() => { resolveInitialBuild(); })`. 기존의 `isInitialBuild` 가드와 동등한 동작.
7
+ - BaseEngine lint 결과 보고 유지: `BaseEngine.ts:148-157` — build 이벤트에서 `event.lint`가 있으면 lint BuildResult를 ResultCollector에 추가. 기존 로직 그대로 유지됨.
8
+ - BaseEngine 경고 로깅 유지: `BaseEngine.ts:144-146` — `event.build.warnings`가 있으면 `logger.warn` 호출. 기존 로직 그대로 유지됨.
9
+ - setupWatchEvents가 index.ts의 public export에 포함되지 않음: 내부 유틸리티이므로 패키지 외부 API 불변. `engines/index.ts`의 export 목록에 engine-watch-events 없음 확인.
10
+ - resolveInitialBuild가 _callStartWatch catch에서 호출됨: `BaseEngine.ts:162-164` — `this._callStartWatch(output).catch(() => { resolveInitialBuild(); })`. 기존의 `isInitialBuild` 가드와 동등한 동작.
11
11
 
12
12
  ### Slice 2: EsbuildClientEngine 적용
13
13
 
14
- - [x] EsbuildClientEngine이 waitForInitialBuild() 미사용: `EsbuildClientEngine.ts:103-111` — setupWatchEvents 호출 후 반환값 사용 안 함. 111행에 "waitForInitialBuild 미사용" 주석 확인.
15
- - [x] serverReady 이벤트 처리 유지: `EsbuildClientEngine.ts:97-101` — serverReady 핸들러가 setupWatchEvents 전에 등록됨. `this.port = event.port` 로직 그대로.
16
- - [x] error 로깅 유지: `EsbuildClientEngine.ts:113-117` — setupWatchEvents 이후 별도 error 핸들러에서 `logger.error` 호출. 기존 동작 보존.
17
- - [x] worker.startWatch() await 패턴 유지: `EsbuildClientEngine.ts:119-130` — 기존과 동일하게 `await this._worker!.startWatch(...)` 로 완료 감지.
14
+ - EsbuildClientEngine이 waitForInitialBuild() 미사용: `EsbuildClientEngine.ts:103-111` — setupWatchEvents 호출 후 반환값 사용 안 함. 111행에 "waitForInitialBuild 미사용" 주석 확인.
15
+ - serverReady 이벤트 처리 유지: `EsbuildClientEngine.ts:97-101` — serverReady 핸들러가 setupWatchEvents 전에 등록됨. `this.port = event.port` 로직 그대로.
16
+ - error 로깅 유지: `EsbuildClientEngine.ts:113-117` — setupWatchEvents 이후 별도 error 핸들러에서 `logger.error` 호출. 기존 동작 보존.
17
+ - worker.startWatch() await 패턴 유지: `EsbuildClientEngine.ts:119-130` — 기존과 동일하게 `await this._worker!.startWatch(...)` 로 완료 감지.
@@ -2,8 +2,8 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] `@angular/build/private`에서 `createCompilerPlugin`, `SourceFileCache`, `CompilerPluginOptions`, `BundleStylesheetOptions` import가 없다: grep 결과 `@angular/build/private` 매치 없음
6
- - [x] `createAngularCompilerPlugin`이 `./esbuild-angular-compiler-plugin.js`에서 import되어 있다: line 10에서 import, line 119에서 호출 확인
7
- - [x] `ClientSourceFileCache`가 `AngularSourceFileCache`를 확장하고 `typeScriptFileCache`, `loadResultCache` 프로퍼티를 가진다: line 46-49에서 `extends AngularSourceFileCache` + 두 프로퍼티 확인
8
- - [x] `ClientEsbuildResult.sourceFileCache` 타입이 `ClientSourceFileCache`이다: line 53 확인
9
- - [x] `client.worker.ts`의 `sourceFileCache.loadResultCache.watchFiles`, `sourceFileCache.typeScriptFileCache.keys()`, `sourceFileCache.invalidate()` 접근이 새 구조와 타입 호환된다: typecheck 0 에러로 타입 호환성 확인됨
5
+ - `@angular/build/private`에서 `createCompilerPlugin`, `SourceFileCache`, `CompilerPluginOptions`, `BundleStylesheetOptions` import가 없다: grep 결과 `@angular/build/private` 매치 없음
6
+ - `createAngularCompilerPlugin`이 `./esbuild-angular-compiler-plugin.js`에서 import되어 있다: line 10에서 import, line 119에서 호출 확인
7
+ - `ClientSourceFileCache`가 `AngularSourceFileCache`를 확장하고 `typeScriptFileCache`, `loadResultCache` 프로퍼티를 가진다: line 46-49에서 `extends AngularSourceFileCache` + 두 프로퍼티 확인
8
+ - `ClientEsbuildResult.sourceFileCache` 타입이 `ClientSourceFileCache`이다: line 53 확인
9
+ - `client.worker.ts`의 `sourceFileCache.loadResultCache.watchFiles`, `sourceFileCache.typeScriptFileCache.keys()`, `sourceFileCache.invalidate()` 접근이 새 구조와 타입 호환된다: typecheck 0 에러로 타입 호환성 확인됨
@@ -2,5 +2,5 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] postcssConfigPath가 CreateClientEsbuildOptions 인터페이스에서 제거됨: `esbuild-client-config.ts`에서 `postcssConfigPath` 검색 결과 없음 (No matches found). `client.worker.ts`에서도 2곳 모두 제거 확인.
6
- - [x] createScssPlugin에 로딩된 PostCSS 인스턴스가 전달됨: `esbuild-client-config.ts:118`에서 `postcssPlugins: loadedPostcssPlugins`로 `createScssPlugin`에 전달 확인.
5
+ - postcssConfigPath가 CreateClientEsbuildOptions 인터페이스에서 제거됨: `esbuild-client-config.ts`에서 `postcssConfigPath` 검색 결과 없음 (No matches found). `client.worker.ts`에서도 2곳 모두 제거 확인.
6
+ - createScssPlugin에 로딩된 PostCSS 인스턴스가 전달됨: `esbuild-client-config.ts:118`에서 `postcssPlugins: loadedPostcssPlugins`로 `createScssPlugin`에 전달 확인.
@@ -2,25 +2,25 @@
2
2
 
3
3
  ## Feature 1.1a 검증 항목
4
4
 
5
- - [x] import 경로: `@angular/build/private`에서 `createCompilerPlugin`, `SourceFileCache`, `CompilerPluginOptions`, `BundleStylesheetOptions`를 정상 import — `private.d.ts` line 31-37에 모두 export 확인
6
- - [x] `createCompilerPlugin`의 2-param 시그니처(private export wrapper)와 일치하는 호출 — `createCompilerPlugin(pluginOptions, styleOptions)` 2개 인자로 호출 (private.d.ts의 wrapper 시그니처와 일치)
7
- - [x] `CompilerPluginOptions.sourcemap` 타입이 `boolean | 'external'` 범위 내 값 사용 — `isDev` (boolean)으로 전달, `true`/`false` 범위 내
8
- - [x] `BundleStylesheetOptions.sourcemap` 타입이 `boolean | 'external' | 'inline' | 'linked'` 범위 내 값 사용 — `isDev ? "linked" : false` 범위 내
9
- - [x] `sd-config.types.ts`의 `postCss.plugins` 타입이 Angular의 `PostcssConfiguration` 포맷과 일치 — `[string, (object | string)?][]` = Angular의 `[name: string, options?: object | string][]`
10
- - [x] `onEnd` 플러그인이 esbuild Plugin 규격(`name` + `setup`)을 준수 — `{ name: "sd-on-end", setup(build) { build.onEnd(...) } }` 규격 충족
11
- - [x] 패키지 루트 `index.ts`에서 신규 모듈 export 필요 여부 — 불필요. 기존 `esbuild-config.ts`도 내부 유틸로 export 안 함. `sd-config.types.ts`만 export 중
5
+ - import 경로: `@angular/build/private`에서 `createCompilerPlugin`, `SourceFileCache`, `CompilerPluginOptions`, `BundleStylesheetOptions`를 정상 import — `private.d.ts` line 31-37에 모두 export 확인
6
+ - `createCompilerPlugin`의 2-param 시그니처(private export wrapper)와 일치하는 호출 — `createCompilerPlugin(pluginOptions, styleOptions)` 2개 인자로 호출 (private.d.ts의 wrapper 시그니처와 일치)
7
+ - `CompilerPluginOptions.sourcemap` 타입이 `boolean | 'external'` 범위 내 값 사용 — `isDev` (boolean)으로 전달, `true`/`false` 범위 내
8
+ - `BundleStylesheetOptions.sourcemap` 타입이 `boolean | 'external' | 'inline' | 'linked'` 범위 내 값 사용 — `isDev ? "linked" : false` 범위 내
9
+ - `sd-config.types.ts`의 `postCss.plugins` 타입이 Angular의 `PostcssConfiguration` 포맷과 일치 — `[string, (object | string)?][]` = Angular의 `[name: string, options?: object | string][]`
10
+ - `onEnd` 플러그인이 esbuild Plugin 규격(`name` + `setup`)을 준수 — `{ name: "sd-on-end", setup(build) { build.onEnd(...) } }` 규격 충족
11
+ - 패키지 루트 `index.ts`에서 신규 모듈 export 필요 여부 — 불필요. 기존 `esbuild-config.ts`도 내부 유틸로 export 안 함. `sd-config.types.ts`만 export 중
12
12
 
13
13
  ## Feature 1.1b-2 검증 항목
14
14
 
15
- - [x] `browserslist-to-esbuild` import 정상 — `import browserslistToEsbuild from "browserslist-to-esbuild"` 추가. `vite-config.ts:5`와 동일한 패턴
16
- - [x] `browserslistToEsbuild` 반환값이 esbuild target 및 BundleStylesheetOptions.target에 동시 적용 — `esbuildTarget` 변수로 통합하여 두 곳에 사용 (line 51-56, 82, 122)
17
- - [x] 에셋 복사: `copyPublicFiles(pkgDir, false)` 시그니처가 build 모드 호출 가능 — `copy-public.ts:15` 시그니처 `(pkgDir: string, includeDev: boolean): Promise<void>` 확인. build 모드에서 `false` 전달 적합
18
- - [x] 에셋 감시: `watchPublicFiles(pkgDir, true)` 시그니처가 dev 모드 호출 가능 — `copy-public.ts:58` 시그니처 `(pkgDir: string, includeDev: boolean): Promise<FsWatcher | undefined>` 확인. dev 모드에서 `true` 전달 적합
19
- - [x] 에셋 복사 함수는 `createClientEsbuildContext` 외부 호출자 담당 (설계 결정 D4) — `createClientEsbuildContext` 내부에 `copyPublicFiles`/`watchPublicFiles` 호출 없음 확인. 실제 호출 통합은 Feature 3.1에서 수행
15
+ - `browserslist-to-esbuild` import 정상 — `import browserslistToEsbuild from "browserslist-to-esbuild"` 추가. `vite-config.ts:5`와 동일한 패턴
16
+ - `browserslistToEsbuild` 반환값이 esbuild target 및 BundleStylesheetOptions.target에 동시 적용 — `esbuildTarget` 변수로 통합하여 두 곳에 사용 (line 51-56, 82, 122)
17
+ - 에셋 복사: `copyPublicFiles(pkgDir, false)` 시그니처가 build 모드 호출 가능 — `copy-public.ts:15` 시그니처 `(pkgDir: string, includeDev: boolean): Promise<void>` 확인. build 모드에서 `false` 전달 적합
18
+ - 에셋 감시: `watchPublicFiles(pkgDir, true)` 시그니처가 dev 모드 호출 가능 — `copy-public.ts:58` 시그니처 `(pkgDir: string, includeDev: boolean): Promise<FsWatcher | undefined>` 확인. dev 모드에서 `true` 전달 적합
19
+ - 에셋 복사 함수는 `createClientEsbuildContext` 외부 호출자 담당 (설계 결정 D4) — `createClientEsbuildContext` 내부에 `copyPublicFiles`/`watchPublicFiles` 호출 없음 확인. 실제 호출 통합은 Feature 3.1에서 수행
20
20
 
21
21
  ## Feature 1.1b-1 검증 항목
22
22
 
23
- - [x] tsconfig 옵션이 CompilerPluginOptions와 esbuild context에 동일 기본값 사용 — 둘 다 `options.tsconfig ?? path.join(options.pkgDir, "tsconfig.json")`. CompilerPluginOptions(line 65)와 esbuild context(line 151)에서 동일 패턴
24
- - [x] esbuild tsconfig 옵션이 서버 빌드 패턴(D1)과 일치 — `esbuild-config.ts:94` `tsconfig: path.join(options.pkgDir, "tsconfig.json")`과 동일. 클라이언트는 추가로 `options.tsconfig` 커스텀 경로 지원 (기존 인터페이스에 이미 존재)
25
- - [x] scssPlugin loadPaths가 buildScssLoadPaths 패턴과 일치 — `ngtsc-build-core.ts:91-96`의 `[pkgDir/scss, cwd/node_modules]`와 `esbuild-client-config.ts:105-108`의 `[options.pkgDir/scss, options.cwd/node_modules]` 동일
26
- - [x] plugins 배열 순서가 구현계획과 일치 — `[angularPlugin, scssPlugin, ...customPlugins, ...onEndPlugin]` (line 153-169)
23
+ - tsconfig 옵션이 CompilerPluginOptions와 esbuild context에 동일 기본값 사용 — 둘 다 `options.tsconfig ?? path.join(options.pkgDir, "tsconfig.json")`. CompilerPluginOptions(line 65)와 esbuild context(line 151)에서 동일 패턴
24
+ - esbuild tsconfig 옵션이 서버 빌드 패턴(D1)과 일치 — `esbuild-config.ts:94` `tsconfig: path.join(options.pkgDir, "tsconfig.json")`과 동일. 클라이언트는 추가로 `options.tsconfig` 커스텀 경로 지원 (기존 인터페이스에 이미 존재)
25
+ - scssPlugin loadPaths가 buildScssLoadPaths 패턴과 일치 — `ngtsc-build-core.ts:91-96`의 `[pkgDir/scss, cwd/node_modules]`와 `esbuild-client-config.ts:105-108`의 `[options.pkgDir/scss, options.cwd/node_modules]` 동일
26
+ - plugins 배열 순서가 구현계획과 일치 — `[angularPlugin, scssPlugin, ...customPlugins, ...onEndPlugin]` (line 153-169)
@@ -2,9 +2,9 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] FileInfo 타입이 IndexHtmlGenerator의 FileInfo와 호환: IndexHtmlGeneratorProcessOptions.files는 `{file: string, name?: string, extension: string}` — 동일 구조 확인
6
- - [x] entrypoints 타입이 IndexHtmlGenerator의 Entrypoint와 호환: `[string, boolean][]` — `Entrypoint = [name: string, isModule: boolean]`과 동일
7
- - [x] SRI 옵션이 mode에 따라 정확히 설정: `sri: options.mode === "build"` — build일 때만 true
8
- - [x] cssBundle 연결 로직의 정확성: JS entry의 `output.cssBundle` 경로를 normalize하여 CSS output의 경로와 매칭. esbuild metafile 구조상 cssBundle은 output key와 동일 형식
9
- - [x] postTransform이 IndexHtmlGeneratorOptions에 올바르게 전달: `IndexHtmlTransform = (content: string) => Promise<string>` — GenerateIndexHtmlOptions.postTransform과 동일 타입
10
- - [x] Windows 경로 호환성: `replace(/\\/g, "/")` 로 모든 경로를 POSIX 형식으로 정규화
5
+ - FileInfo 타입이 IndexHtmlGenerator의 FileInfo와 호환: IndexHtmlGeneratorProcessOptions.files는 `{file: string, name?: string, extension: string}` — 동일 구조 확인
6
+ - entrypoints 타입이 IndexHtmlGenerator의 Entrypoint와 호환: `[string, boolean][]` — `Entrypoint = [name: string, isModule: boolean]`과 동일
7
+ - SRI 옵션이 mode에 따라 정확히 설정: `sri: options.mode === "build"` — build일 때만 true
8
+ - cssBundle 연결 로직의 정확성: JS entry의 `output.cssBundle` 경로를 normalize하여 CSS output의 경로와 매칭. esbuild metafile 구조상 cssBundle은 output key와 동일 형식
9
+ - postTransform이 IndexHtmlGeneratorOptions에 올바르게 전달: `IndexHtmlTransform = (content: string) => Promise<string>` — GenerateIndexHtmlOptions.postTransform과 동일 타입
10
+ - Windows 경로 호환성: `replace(/\\/g, "/")` 로 모든 경로를 POSIX 형식으로 정규화
@@ -2,8 +2,8 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] augmentAppWithServiceWorker 호출 인자가 정확한가: `esbuild-pwa.ts:108-113` — `(options.pkgDir, options.cwd, options.outdir, options.baseHref)` 순서로 호출 확인
6
- - [x] 기본 ngsw-config.json에 $schema, index, assetGroups(app, assets)가 포함되는가: `esbuild-pwa.ts:83-104` — `$schema`, `index: "/index.html"`, `assetGroups: [{name: "app"}, {name: "assets"}]` 확인
7
- - [x] 등록 스크립트에서 ngsw-worker.js를 등록하는가: `esbuild-pwa.ts:119` — `register("ngsw-worker.js")` 확인. `sw.js` 참조 없음
8
- - [x] SdPwaConfig.workbox 필드를 참조하지 않는가: grep 결과 "workbox" 0건 확인. D4 결정 준수
9
- - [x] generatePwaIcons 호출 결과를 dist/icons/로 복사하는 로직이 있는가: `esbuild-pwa.ts:51-58` — `srcIconsDir(public/icons/)` → `dstIconsDir(outdir/icons/)` copyFileSync 로직 확인
5
+ - augmentAppWithServiceWorker 호출 인자가 정확한가: `esbuild-pwa.ts:108-113` — `(options.pkgDir, options.cwd, options.outdir, options.baseHref)` 순서로 호출 확인
6
+ - 기본 ngsw-config.json에 $schema, index, assetGroups(app, assets)가 포함되는가: `esbuild-pwa.ts:83-104` — `$schema`, `index: "/index.html"`, `assetGroups: [{name: "app"}, {name: "assets"}]` 확인
7
+ - 등록 스크립트에서 ngsw-worker.js를 등록하는가: `esbuild-pwa.ts:119` — `register("ngsw-worker.js")` 확인. `sw.js` 참조 없음
8
+ - SdPwaConfig.workbox 필드를 참조하지 않는가: grep 결과 "workbox" 0건 확인. D4 결정 준수
9
+ - generatePwaIcons 호출 결과를 dist/icons/로 복사하는 로직이 있는가: `esbuild-pwa.ts:51-58` — `srcIconsDir(public/icons/)` → `dstIconsDir(outdir/icons/)` copyFileSync 로직 확인
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] createCompilerPlugin 컴포넌트 스타일과 비충돌: `createCompilerPlugin`은 `BundleStylesheetOptions`를 받아 컴포넌트 `styleUrls`를 TypeScript 변환 과정에서 내부 처리한다. 이들은 esbuild의 일반 `onLoad` 경로를 타지 않으므로, `sd-scss` 플러그인의 `onLoad({ filter: /\.scss$/ })` 콜백은 side-effect `import "./global.scss"` 같은 일반 import만 인터셉트한다. 충돌 없음 확인.
6
- - [x] onLoad filter 정확성: `/\.scss$/` 정규식이 `.scss` 파일만 매칭 — `.css`, `.scss.ts` 등은 매칭하지 않음. 단위 테스트(`esbuild-scss-plugin.spec.ts`)에서 검증 완료.
7
- - [x] sass 라인 번호 변환: sass `span.start.line`은 0-based, esbuild `location.line`은 1-based. `line + 1` 변환 적용 확인 (`esbuild-scss-plugin.ts:31`).
8
- - [x] fileURLToPath import 정상: `url` 모듈에서 import. `scss-compiler.ts`의 `pathToFileURL`과 동일 모듈.
5
+ - createCompilerPlugin 컴포넌트 스타일과 비충돌: `createCompilerPlugin`은 `BundleStylesheetOptions`를 받아 컴포넌트 `styleUrls`를 TypeScript 변환 과정에서 내부 처리한다. 이들은 esbuild의 일반 `onLoad` 경로를 타지 않으므로, `sd-scss` 플러그인의 `onLoad({ filter: /\.scss$/ })` 콜백은 side-effect `import "./global.scss"` 같은 일반 import만 인터셉트한다. 충돌 없음 확인.
6
+ - onLoad filter 정확성: `/\.scss$/` 정규식이 `.scss` 파일만 매칭 — `.css`, `.scss.ts` 등은 매칭하지 않음. 단위 테스트(`esbuild-scss-plugin.spec.ts`)에서 검증 완료.
7
+ - sass 라인 번호 변환: sass `span.start.line`은 0-based, esbuild `location.line`은 1-based. `line + 1` 변환 적용 확인 (`esbuild-scss-plugin.ts:31`).
8
+ - fileURLToPath import 정상: `url` 모듈에서 import. `scss-compiler.ts`의 `pathToFileURL`과 동일 모듈.
@@ -2,16 +2,16 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] ws 의존성이 sd-cli package.json dependencies에 추가되었는가: `"ws": "^8.20.0"` 확인 (package.json:51)
6
- - [x] @types/ws가 sd-cli package.json devDependencies에 추가되었는가: `"@types/ws": "^8.18.1"` 확인 (package.json:57)
7
- - [x] dev-http-server.ts의 onRequest 훅 타입 시그니처가 올바른가: `onRequest?: (req: http.IncomingMessage, res: http.ServerResponse) => boolean` — Node.js 표준 타입 사용, boolean 반환으로 처리 완료 여부 표시
8
- - [x] hmr-service.ts의 handleRequest가 angularComponentMiddleware와 동일한 encodeURIComponent 패턴을 사용하는가: `templateUpdates.get(encodeURIComponent(componentId))` (hmr-service.ts:65) — vite-angular-plugin.ts:553과 동일 패턴
9
- - [x] WebSocketServer가 httpServer의 upgrade 이벤트를 통해 연결되는가: `new WebSocketServer({ server: httpServer })` (hmr-service.ts:27) — ws 라이브러리가 httpServer의 upgrade 이벤트를 자동 처리
5
+ - ws 의존성이 sd-cli package.json dependencies에 추가되었는가: `"ws": "^8.20.0"` 확인 (package.json:51)
6
+ - @types/ws가 sd-cli package.json devDependencies에 추가되었는가: `"@types/ws": "^8.18.1"` 확인 (package.json:57)
7
+ - dev-http-server.ts의 onRequest 훅 타입 시그니처가 올바른가: `onRequest?: (req: http.IncomingMessage, res: http.ServerResponse) => boolean` — Node.js 표준 타입 사용, boolean 반환으로 처리 완료 여부 표시
8
+ - hmr-service.ts의 handleRequest가 angularComponentMiddleware와 동일한 encodeURIComponent 패턴을 사용하는가: `templateUpdates.get(encodeURIComponent(componentId))` (hmr-service.ts:65) — vite-angular-plugin.ts:553과 동일 패턴
9
+ - WebSocketServer가 httpServer의 upgrade 이벤트를 통해 연결되는가: `new WebSocketServer({ server: httpServer })` (hmr-service.ts:27) — ws 라이브러리가 httpServer의 upgrade 이벤트를 자동 처리
10
10
 
11
11
  ## Slice 2 검증 항목
12
12
 
13
- - [x] import.meta.hot 폴리필이 esbuild banner로 주입되는가: `esbuild-client-config.ts`에서 `templateUpdates != null && legacyModule !== true` 조건으로 banner 생성. `import.meta.hot.on()`, `import.meta.hot.off()`, `globalThis.__hmr_dispatch()` 제공.
14
- - [x] legacyModule일 때 폴리필이 주입되지 않는가: `options.legacyModule !== true` 조건으로 legacyModule에서 banner 미생성.
15
- - [x] ngHmrMode 가드가 있어 prod에서 실행되지 않는가: banner 코드가 `if(typeof ngHmrMode!=="undefined"&&ngHmrMode)` 가드로 래핑. prod에서 `ngHmrMode="false"`로 정의되므로 실행 안됨.
16
- - [x] sd-hmr-reset 플러그인이 onStart에서 templateUpdates.clear()를 호출하는가: `esbuild-client-config.ts`에 `sd-hmr-reset` 플러그인 추가. `build.onStart(() => { options.templateUpdates!.clear(); })` 확인.
17
- - [x] sd-hmr-reset이 angularPlugin보다 먼저 등록되는가: plugins 배열에서 `sd-hmr-reset`이 첫 번째 위치 (angularPlugin, scssPlugin보다 앞). createCompilerPlugin이 templateUpdates에 쓰기 전에 clear됨.
13
+ - import.meta.hot 폴리필이 esbuild banner로 주입되는가: `esbuild-client-config.ts`에서 `templateUpdates != null && legacyModule !== true` 조건으로 banner 생성. `import.meta.hot.on()`, `import.meta.hot.off()`, `globalThis.__hmr_dispatch()` 제공.
14
+ - legacyModule일 때 폴리필이 주입되지 않는가: `options.legacyModule !== true` 조건으로 legacyModule에서 banner 미생성.
15
+ - ngHmrMode 가드가 있어 prod에서 실행되지 않는가: banner 코드가 `if(typeof ngHmrMode!=="undefined"&&ngHmrMode)` 가드로 래핑. prod에서 `ngHmrMode="false"`로 정의되므로 실행 안됨.
16
+ - sd-hmr-reset 플러그인이 onStart에서 templateUpdates.clear()를 호출하는가: `esbuild-client-config.ts`에 `sd-hmr-reset` 플러그인 추가. `build.onStart(() => { options.templateUpdates!.clear(); })` 확인.
17
+ - sd-hmr-reset이 angularPlugin보다 먼저 등록되는가: plugins 배열에서 `sd-hmr-reset`이 첫 번째 위치 (angularPlugin, scssPlugin보다 앞). createCompilerPlugin이 templateUpdates에 쓰기 전에 clear됨.
@@ -2,9 +2,9 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] lint.worker.ts가 `../utils/lint-core`에서 import: `import { executeLint, type LintOptions, type LintResult } from "../utils/lint-core";` (line 2) 확인
6
- - [x] lint-utils.ts가 `./lint-core`에서 import: `import type { LintOptions, LintResult } from "./lint-core";` (line 2) 확인
7
- - [x] check.ts가 `../utils/lint-core`에서 import: `import { executeLint, type LintResult } from "../utils/lint-core";` (line 4) 확인
8
- - [x] commands/lint.ts�� `../commands/lint` import가 없음: `import { executeLint, type LintOptions } from "../utils/lint-core";` (line 1)만 존재
9
- - [x] lint-core.ts에 runLint가 없음: `executeLint`, `loadIgnorePatterns`, `LintOptions`, `LintResult`만 export
10
- - [x] commands/lint.ts에 runLint만 존재: 13줄의 thin wrapper
5
+ - lint.worker.ts가 `../utils/lint-core`에서 import: `import { executeLint, type LintOptions, type LintResult } from "../utils/lint-core";` (line 2) 확인
6
+ - lint-utils.ts가 `./lint-core`에서 import: `import type { LintOptions, LintResult } from "./lint-core";` (line 2) 확인
7
+ - check.ts가 `../utils/lint-core`에서 import: `import { executeLint, type LintResult } from "../utils/lint-core";` (line 4) 확인
8
+ - commands/lint.ts�� `../commands/lint` import가 없음: `import { executeLint, type LintOptions } from "../utils/lint-core";` (line 1)만 존재
9
+ - lint-core.ts에 runLint가 없음: `executeLint`, `loadIgnorePatterns`, `LintOptions`, `LintResult`만 export
10
+ - commands/lint.ts에 runLint만 존재: 13줄의 thin wrapper
@@ -2,14 +2,14 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] 파일 구조: `replace-deps-resolve.ts` 신규 생성, `replace-deps.ts` 기존 유지 확인
6
- - [x] 해석 함수 이동: `resolveReplaceDepEntries`, `parseWorkspaceGlobs`, `collectSearchRoots`, `resolveAllReplaceDepEntries`가 `replace-deps-resolve.ts`에 위치
7
- - [x] 타입 위치: `ReplaceDepEntry`가 `replace-deps-resolve.ts`에서 export, `replace-deps.ts`에서 `export type` re-export
8
- - [x] `WatchReplaceDepResult`가 `replace-deps.ts`에서 export
9
- - [x] `replace-deps.ts`에서 `resolveAllReplaceDepEntries`를 import하여 사용
10
- - [x] `commands/publish.ts` import 경로가 `../utils/replace-deps-resolve`로 변경
11
- - [x] `sd-cli.ts`, `BaseOrchestrator.ts`, `commands/replace-deps.ts`의 import 경로는 변경 없음 (실행 함수만 사용)
12
- - [x] `tests/utils/replace-deps.spec.ts` import 경로가 `../../src/deps/replace-deps-resolve`로 변경
13
- - [x] `tests/utils/replace-deps-watch.spec.ts`, `replace-deps-watch.acc.spec.ts`의 import 경로는 변경 없음
14
- - [x] `replace-deps.ts`에서 `glob` import가 제거됨 (해석 로직 전용)
15
- - [x] `replace-deps-resolve.ts`에서 `fsx`, `FsWatcher`, `exec` import가 없음 (실행 로직 전용)
5
+ - 파일 구조: `replace-deps-resolve.ts` 신규 생성, `replace-deps.ts` 기존 유지 확인
6
+ - 해석 함수 이동: `resolveReplaceDepEntries`, `parseWorkspaceGlobs`, `collectSearchRoots`, `resolveAllReplaceDepEntries`가 `replace-deps-resolve.ts`에 위치
7
+ - 타입 위치: `ReplaceDepEntry`가 `replace-deps-resolve.ts`에서 export, `replace-deps.ts`에서 `export type` re-export
8
+ - `WatchReplaceDepResult`가 `replace-deps.ts`에서 export
9
+ - `replace-deps.ts`에서 `resolveAllReplaceDepEntries`를 import하여 사용
10
+ - `commands/publish.ts` import 경로가 `../utils/replace-deps-resolve`로 변경
11
+ - `sd-cli.ts`, `BaseOrchestrator.ts`, `commands/replace-deps.ts`의 import 경로는 변경 없음 (실행 함수만 사용)
12
+ - `tests/utils/replace-deps.spec.ts` import 경로가 `../../src/deps/replace-deps-resolve`로 변경
13
+ - `tests/utils/replace-deps-watch.spec.ts`, `replace-deps-watch.acc.spec.ts`의 import 경로는 변경 없음
14
+ - `replace-deps.ts`에서 `glob` import가 제거됨 (해석 로직 전용)
15
+ - `replace-deps-resolve.ts`에서 `fsx`, `FsWatcher`, `exec` import가 없음 (실행 로직 전용)
@@ -2,8 +2,8 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] watchReplaceDeps 시그니처에 optional `options` 파라미터가 추가되었는가: `replace-deps.ts:321`에 `options?: { onChanged?: () => void }` 확인
6
- - [x] onChanged 콜백이 파일 복사 루프 완료 후(for 루프 바깥) 호출되는가: `replace-deps.ts:393`에서 for 루프(346-392) 완료 후 `options?.onChanged?.()` 호출 확인
7
- - [x] 기존 watchReplaceDeps 호출자가 새 시그니처와 호환되는가: `DevWatchOrchestrator.ts:121`에서 2개 인자로 호출 — 3번째 optional 파라미터 생략으로 호환
8
- - [x] esbuild onEnd 플러그인(esbuild-client-config.ts)이 빌드 결과를 외부로 전달하는 경로가 존재하는가: `esbuild-client-config.ts:215-218`에 `sd-on-end` 플러그인이 `options.onEnd(result)` 호출
9
- - [x] hmrService.onBuildEnd()가 metafile 기반으로 HMR 메시지를 디스패치하는 경로가 존재하는가: `hmr-service.ts:49-133`에 metafile 기반 변경 판별 → WS broadcast 로직 존재
5
+ - watchReplaceDeps 시그니처에 optional `options` 파라미터가 추가되었는가: `replace-deps.ts:321`에 `options?: { onChanged?: () => void }` 확인
6
+ - onChanged 콜백이 파일 복사 루프 완료 후(for 루프 바깥) 호출되는가: `replace-deps.ts:393`에서 for 루프(346-392) 완료 후 `options?.onChanged?.()` 호출 확인
7
+ - 기존 watchReplaceDeps 호출자가 새 시그니처와 호환되는가: `DevWatchOrchestrator.ts:121`에서 2개 인자로 호출 — 3번째 optional 파라미터 생략으로 호환
8
+ - esbuild onEnd 플러그인(esbuild-client-config.ts)이 빌드 결과를 외부로 전달하는 경로가 존재하는가: `esbuild-client-config.ts:215-218`에 `sd-on-end` 플러그인이 `options.onEnd(result)` 호출
9
+ - hmrService.onBuildEnd()가 metafile 기반으로 HMR 메시지를 디스패치하는 경로가 존재하는가: `hmr-service.ts:49-133`에 metafile 기반 변경 판별 → WS broadcast 로직 존재
@@ -2,13 +2,13 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] 4개 함수가 utils/server-production-files.ts에 export되어 있다: line 14, 27, 68, 87에 각각 export function 확인
6
- - [x] worker에서 4개 함수 정의가 제거되었다: worker에 함수 정의 없음, import와 호출만 존재
7
- - [x] worker에서 collectAllExternals, generateProductionFiles를 새 모듈에서 import한다: line 19 `import { collectAllExternals, generateProductionFiles } from "../utils/server-production-files"`
8
- - [x] collectAllExternals 시그니처: `(pkgDir: string, manualExternals?: string[]) => string[]` — line 14 확인
9
- - [x] parseLockfileVersions 시그니처: `(cwd: string) => Map<string, string>` — line 27 확인
10
- - [x] resolveLockedVersions 시그니처: `(cwd: string, pkgNames: string[]) => Record<string, string>` — line 68 확인
11
- - [x] generateProductionFiles 시그니처: `(info: ServerBuildInfo, externals: string[]) => void` — line 87 확인
12
- - [x] worker에 build, rebuildAll, startWatch, stopWatch, cleanup, createEsbuildWatchContext가 존재한다: line 116, 148, 259, 336, 359, 488 확인
13
- - [x] worker에서 cpx import가 제거되었다: grep 결과 매칭 없음
14
- - [x] worker에서 collectAllDependencyExternals import가 제거되었다: grep 결과 매칭 없음
5
+ - 4개 함수가 utils/server-production-files.ts에 export되어 있다: line 14, 27, 68, 87에 각각 export function 확인
6
+ - worker에서 4개 함수 정의가 제거되었다: worker에 함수 정의 없음, import와 호출만 존재
7
+ - worker에서 collectAllExternals, generateProductionFiles를 새 모듈에서 import한다: line 19 `import { collectAllExternals, generateProductionFiles } from "../utils/server-production-files"`
8
+ - collectAllExternals 시그니처: `(pkgDir: string, manualExternals?: string[]) => string[]` — line 14 확인
9
+ - parseLockfileVersions 시그니처: `(cwd: string) => Map<string, string>` — line 27 확인
10
+ - resolveLockedVersions 시그니처: `(cwd: string, pkgNames: string[]) => Record<string, string>` — line 68 확인
11
+ - generateProductionFiles 시그니처: `(info: ServerBuildInfo, externals: string[]) => void` — line 87 확인
12
+ - worker에 build, rebuildAll, startWatch, stopWatch, cleanup, createEsbuildWatchContext가 존재한다: line 116, 148, 259, 336, 359, 488 확인
13
+ - worker에서 cpx import가 제거되었다: grep 결과 매칭 없음
14
+ - worker에서 collectAllDependencyExternals import가 제거되었다: grep 결과 매칭 없음
@@ -2,6 +2,6 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] enableLint 옵션 제거: `CreateClientViteConfigOptions` 인터페이스에서 `enableLint` 필드가 완전히 제거됨. `vite-config.ts` 전체에서 `enableLint` 문자열 검색 결과 0건.
6
- - [x] replaceDepDistPaths 계산 제거: `vite-config.ts` 전체에서 `replaceDepDistPaths` 문자열 검색 결과 0건. 기존 line 98-114의 계산 로직(fs.realpathSync, pathx.posix 사용)이 완전히 제거됨. `fs`와 `pathx` import도 함께 제거됨.
7
- - [x] tsconfigPath, browserslist, postCssPlugins, legacyModule은 인터페이스 옵션이 아닌 함수 내부 로컬 변수로만 존재: 모두 `loadSdConfig()` 결과에서 추출하거나 `pkgDir`에서 derive됨.
5
+ - enableLint 옵션 제거: `CreateClientViteConfigOptions` 인터페이스에서 `enableLint` 필드가 완전히 제거됨. `vite-config.ts` 전체에서 `enableLint` 문자열 검색 결과 0건.
6
+ - replaceDepDistPaths 계산 제거: `vite-config.ts` 전체에서 `replaceDepDistPaths` 문자열 검색 결과 0건. 기존 line 98-114의 계산 로직(fs.realpathSync, pathx.posix 사용)이 완전히 제거됨. `fs`와 `pathx` import도 함께 제거됨.
7
+ - tsconfigPath, browserslist, postCssPlugins, legacyModule은 인터페이스 옵션이 아닌 함수 내부 로컬 변수로만 존재: 모두 `loadSdConfig()` 결과에서 추출하거나 `pkgDir`에서 derive됨.
@@ -2,9 +2,9 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] buildWatchPaths 호출 인자가 기존 코드와 동등: `srcGlobs: ["*.ts"]`, `replaceDeps: info.replaceDeps` — 기존 `pathx.posixResolve(info.pkgDir, "src", "**", "*.ts")` 패턴과 동일한 경로 생성 확인
6
- - [x] workspace deps 경로 생성이 동일: 기존 `workspaceDeps.map((d) => pathx.posixResolve(info.cwd, "packages", d, "src", "**", "*.ts"))` → buildWatchPaths 내부에서 동일하게 `pathx.posixResolve(cwd, "packages", d)` + `src/**/*.ts` 생성
7
- - [x] replaceDeps dist 경로가 cwd와 pkgDir 양쪽에서 생성됨: buildWatchPaths 내부에서 `pathx.posixResolve(cwd, "node_modules", ...pkg.split("/"), "dist", "**", "*.{js,mjs,cjs}")` 및 pkgDir 경로 동일하게 생성
8
- - [x] collectDeps import 제거됨: library-build.worker.ts에서 collectDeps가 더 이상 직접 import되지 않음 — buildWatchPaths가 내부에서 호출
9
- - [x] 변경 필터링 동작 동일: 기존 `hasFileAddOrRemove` 인라인 로직 + `lastSourceFilePaths` 교차가 `shouldSkipRebuild(changes.map(c => c.path), hasFileAddOrRemove(changes), lastSourceFilePaths, logger)`로 동일하게 대체됨
10
- - [x] 기존 테스트(library-build-worker.spec.ts) 16건 모두 통과 확인
5
+ - buildWatchPaths 호출 인자가 기존 코드와 동등: `srcGlobs: ["*.ts"]`, `replaceDeps: info.replaceDeps` — 기존 `pathx.posixResolve(info.pkgDir, "src", "**", "*.ts")` 패턴과 동일한 경로 생성 확인
6
+ - workspace deps 경로 생성이 동일: 기존 `workspaceDeps.map((d) => pathx.posixResolve(info.cwd, "packages", d, "src", "**", "*.ts"))` → buildWatchPaths 내부에서 동일하게 `pathx.posixResolve(cwd, "packages", d)` + `src/**/*.ts` 생성
7
+ - replaceDeps dist 경로가 cwd와 pkgDir 양쪽에서 생성됨: buildWatchPaths 내부에서 `pathx.posixResolve(cwd, "node_modules", ...pkg.split("/"), "dist", "**", "*.{js,mjs,cjs}")` 및 pkgDir 경로 동일하게 생성
8
+ - collectDeps import 제거됨: library-build.worker.ts에서 collectDeps가 더 이상 직접 import되지 않음 — buildWatchPaths가 내부에서 호출
9
+ - 변경 필터링 동작 동일: 기존 `hasFileAddOrRemove` 인라인 로직 + `lastSourceFilePaths` 교차가 `shouldSkipRebuild(changes.map(c => c.path), hasFileAddOrRemove(changes), lastSourceFilePaths, logger)`로 동일하게 대체됨
10
+ - 기존 테스트(library-build-worker.spec.ts) 16건 모두 통과 확인
@@ -2,11 +2,11 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] ngtsc-build watchPaths 동일성: `srcGlobs: ["*.{ts,scss,css}"]`, `extraDirs: [{ dir: "scss", globs: ["*.{scss,css}"] }]` — 기존 코드의 `src/**/*.{ts,scss,css}` + `scss/**/*.{scss,css}` + deps 동일 패턴과 매칭 확인
6
- - [x] ngtsc-build SCSS 역방향 탐색 유지: `hasFileAddOrRemove` → `hasFileAddOrRemoveFn`으로 변경 후에도 `modifiedFiles` 구성 로직(pipeline.findAffectedByScss)이 그대로 유지됨
7
- - [x] ngtsc-build `shouldSkipRebuild(modifiedFiles, addOrRemove, ...)`: SCSS 역방향 탐색 결과가 포함된 `modifiedFiles` Set을 Iterable로 전달하여 정확한 필터링 수행
8
- - [x] server-build watchPaths 동일성: `srcGlobs: ["*"]` — 기존 `src/**/*` 패턴과 동일
9
- - [x] server-build metafile 기반 필터링 유지: `hasFileAddOrRemoveFn(changes)` → `addOrRemove` 변수명으로 변경 외에 metafile 기반 로직(L444-470) 무변경
10
- - [x] server-build esbuild context 재생성 로직 유지: `if (addOrRemove)` 블록 내 context 재생성 로직이 기존과 동일
11
- - [x] collectDeps import 제거: ngtsc-build, server-build 모두에서 collectDeps 직접 import 제거됨 — buildWatchPaths가 내부에서 호출
12
- - [x] 기존 테스트 94건 모두 통과 확인
5
+ - ngtsc-build watchPaths 동일성: `srcGlobs: ["*.{ts,scss,css}"]`, `extraDirs: [{ dir: "scss", globs: ["*.{scss,css}"] }]` — 기존 코드의 `src/**/*.{ts,scss,css}` + `scss/**/*.{scss,css}` + deps 동일 패턴과 매칭 확인
6
+ - ngtsc-build SCSS 역방향 탐색 유지: `hasFileAddOrRemove` → `hasFileAddOrRemoveFn`으로 변경 후에도 `modifiedFiles` 구성 로직(pipeline.findAffectedByScss)이 그대로 유지됨
7
+ - ngtsc-build `shouldSkipRebuild(modifiedFiles, addOrRemove, ...)`: SCSS 역방향 탐색 결과가 포함된 `modifiedFiles` Set을 Iterable로 전달하여 정확한 필터링 수행
8
+ - server-build watchPaths 동일성: `srcGlobs: ["*"]` — 기존 `src/**/*` 패턴과 동일
9
+ - server-build metafile 기반 필터링 유지: `hasFileAddOrRemoveFn(changes)` → `addOrRemove` 변수명으로 변경 외에 metafile 기반 로직(L444-470) 무변경
10
+ - server-build esbuild context 재생성 로직 유지: `if (addOrRemove)` 블록 내 context 재생성 로직이 기존과 동일
11
+ - collectDeps import 제거: ngtsc-build, server-build 모두에서 collectDeps 직접 import 제거됨 — buildWatchPaths가 내부에서 호출
12
+ - 기존 테스트 94건 모두 통과 확인
@@ -2,6 +2,6 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] loadSdConfig import 제거: `client.worker.ts` — `import { loadSdConfig }` 라인이 제거됨. `sd-config` 모듈 import 없음
6
- - [x] resolvePackageInfo가 동기 함수: `client.worker.ts:73` — `function resolvePackageInfo(info: ClientBuildInfo): {` (async 제거, Promise 반환 없음)
7
- - [x] resolvePackageInfo가 info.browserSupport 사용: `client.worker.ts:83-86` — `info.browserSupport?.legacyModule`, `info.browserSupport?.browserslist`, `info.browserSupport?.postCss?.plugins`
5
+ - loadSdConfig import 제거: `client.worker.ts` — `import { loadSdConfig }` 라인이 제거됨. `sd-config` 모듈 import 없음
6
+ - resolvePackageInfo가 동기 함수: `client.worker.ts:73` — `function resolvePackageInfo(info: ClientBuildInfo): {` (async 제거, Promise 반환 없음)
7
+ - resolvePackageInfo가 info.browserSupport 사용: `client.worker.ts:83-86` — `info.browserSupport?.legacyModule`, `info.browserSupport?.browserslist`, `info.browserSupport?.postCss?.plugins`
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] resolvePackageInfo에서 tsconfigPath 반환 제거: 반환 타입이 `{ pkgName: string }`으로 변경됨. 함수 내부에서 `tsconfigPath` 변수 선언 및 계산이 제거됨. 모든 호출부(startWatch:199, startLegacyWatch:266, build:396)에서 `{ pkgName }`으로만 구조분해.
6
- - [x] startWatch에서 제거된 옵션 미전달: `createClientViteConfig` 호출에서 `tsconfigPath`, `browserslist`, `postCssPlugins`, `legacyModule`, `enableLint` 모두 제거됨.
7
- - [x] startLegacyWatch에서 제거된 옵션 미전달: 동일하게 5개 옵션 모두 제거됨.
8
- - [x] build에서 제거된 옵션 미전달: 동일하게 5개 옵션 모두 제거됨.
5
+ - resolvePackageInfo에서 tsconfigPath 반환 제거: 반환 타입이 `{ pkgName: string }`으로 변경됨. 함수 내부에서 `tsconfigPath` 변수 선언 및 계산이 제거됨. 모든 호출부(startWatch:199, startLegacyWatch:266, build:396)에서 `{ pkgName }`으로만 구조분해.
6
+ - startWatch에서 제거된 옵션 미전달: `createClientViteConfig` 호출에서 `tsconfigPath`, `browserslist`, `postCssPlugins`, `legacyModule`, `enableLint` 모두 제거됨.
7
+ - startLegacyWatch에서 제거된 옵션 미전달: 동일하게 5개 옵션 모두 제거됨.
8
+ - build에서 제거된 옵션 미전달: 동일하게 5개 옵션 모두 제거됨.
@@ -2,6 +2,6 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] client.worker.ts onEnd에서 초기 빌드 시 errors 필드가 포함되는지: `client.worker.ts:285-291` — `initialBuildResolve`에 `errors: result.errors.map((e) => e.text)` 포함 확인
6
- - [x] EsbuildClientEngine.startWatch에서 반환값의 success 확인 후 ResultCollector에 보고하는지: `EsbuildClientEngine.ts:129-138` — `!result.success` 조건으로 `resultCollector.add()` 호출 확인. logger.error는 Feature 1.2에서 제거됨 (중복 출력 방지)
7
- - [x] esbuild-client-config.ts에서 logLevel이 "silent"인지: `esbuild-client-config.ts:191` — `logLevel: "silent"` 확인. Feature 1.2에서 dev/build 모두 "silent"로 통일됨
5
+ - client.worker.ts onEnd에서 초기 빌드 시 errors 필드가 포함되는지: `client.worker.ts:285-291` — `initialBuildResolve`에 `errors: result.errors.map((e) => e.text)` 포함 확인
6
+ - EsbuildClientEngine.startWatch에서 반환값의 success 확인 후 ResultCollector에 보고하는지: `EsbuildClientEngine.ts:129-138` — `!result.success` 조건으로 `resultCollector.add()` 호출 확인. logger.error는 Feature 1.2에서 제거됨 (중복 출력 방지)
7
+ - esbuild-client-config.ts에서 logLevel이 "silent"인지: `esbuild-client-config.ts:191` — `logLevel: "silent"` 확인. Feature 1.2에서 dev/build 모두 "silent"로 통일됨
@@ -2,6 +2,6 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] client.worker.ts의 initialBuildResolve에 warnings 필드가 포함되는지: `client.worker.ts:305-315` — `initialBuildResolve`에 `warnings: result.warnings.length > 0 ? result.warnings.map(formatEsbuildMessage) : undefined` 포함 확인. 후속 빌드(line 295-298)와 동일 패턴
6
- - [x] warnings가 없을 때 undefined인지: `client.worker.ts:312-314` — `result.warnings.length > 0` 조건으로 빈 배열일 때 undefined 반환 확인
7
- - [x] ClientBuildResult 인터페이스에 warnings 필드가 있는지: `client.worker.ts:47` — `warnings?: string[]` 확인. 변경 불필요
5
+ - client.worker.ts의 initialBuildResolve에 warnings 필드가 포함되는지: `client.worker.ts:305-315` — `initialBuildResolve`에 `warnings: result.warnings.length > 0 ? result.warnings.map(formatEsbuildMessage) : undefined` 포함 확인. 후속 빌드(line 295-298)와 동일 패턴
6
+ - warnings가 없을 때 undefined인지: `client.worker.ts:312-314` — `result.warnings.length > 0` 조건으로 빈 배열일 때 undefined 반환 확인
7
+ - ClientBuildResult 인터페이스에 warnings 필드가 있는지: `client.worker.ts:47` — `warnings?: string[]` 확인. 변경 불필요
@@ -2,9 +2,9 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] createSourceFileCachePlugin이 IncrementalMtimeTracker를 사용하는지 확인: `client.worker.ts:198` — `const mtimeTracker = new IncrementalMtimeTracker();` 확인됨
6
- - [x] onStart에서 detectChanges 결과로 invalidate가 호출되는지 확인: `client.worker.ts:210-213` — `mtimeTracker.detectChanges(watchTargets)` 결과를 `sourceFileCache.invalidate(changedFiles)`에 전달. 기존 로직과 동작 동일
7
- - [x] onEnd에서 updateMtimes가 호출되는지 확인: `client.worker.ts:228` — `mtimeTracker.updateMtimes(watchTargets)` 호출 확인. `prevMtimes.clear()` + 전체 순회 제거됨
8
- - [x] esbuildResult == null 가드가 유지되는지 확인: onStart의 `if (esbuildResult != null)` (라인 202), onEnd의 `if (esbuildResult == null) return;` (라인 222) 모두 유지됨
9
- - [x] isInitialBuild 가드와 sender.send("buildStart")가 유지되는지 확인: `client.worker.ts:216-218` — `if (!isInitialBuild) { sender.send("buildStart", {}); }` 유지됨
10
- - [x] import 경로에 .js 확장자가 없는지 확인: `client.worker.ts:20` — `from "./incremental-mtime-tracker"` (확장자 없음)
5
+ - createSourceFileCachePlugin이 IncrementalMtimeTracker를 사용하는지 확인: `client.worker.ts:198` — `const mtimeTracker = new IncrementalMtimeTracker();` 확인됨
6
+ - onStart에서 detectChanges 결과로 invalidate가 호출되는지 확인: `client.worker.ts:210-213` — `mtimeTracker.detectChanges(watchTargets)` 결과를 `sourceFileCache.invalidate(changedFiles)`에 전달. 기존 로직과 동작 동일
7
+ - onEnd에서 updateMtimes가 호출되는지 확인: `client.worker.ts:228` — `mtimeTracker.updateMtimes(watchTargets)` 호출 확인. `prevMtimes.clear()` + 전체 순회 제거됨
8
+ - esbuildResult == null 가드가 유지되는지 확인: onStart의 `if (esbuildResult != null)` (라인 202), onEnd의 `if (esbuildResult == null) return;` (라인 222) 모두 유지됨
9
+ - isInitialBuild 가드와 sender.send("buildStart")가 유지되는지 확인: `client.worker.ts:216-218` — `if (!isInitialBuild) { sender.send("buildStart", {}); }` 유지됨
10
+ - import 경로에 .js 확장자가 없는지 확인: `client.worker.ts:20` — `from "./incremental-mtime-tracker"` (확장자 없음)
@@ -2,6 +2,6 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] onEnd 타입이 `void | Promise<void>`를 허용: `esbuild-client-config.ts:29` — `onEnd?: (result: esbuild.BuildResult) => void | Promise<void>;`
6
- - [x] sd-on-end 플러그인이 onEnd 반환값을 return: `esbuild-client-config.ts:220` — `return options.onEnd!(result);`
7
- - [x] client.worker.ts onEnd가 async 직접 전달 (fire-and-forget 제거): `client.worker.ts:240` — `onEnd: async (result: esbuild.BuildResult) => {` (이전의 `void (async () => { ... })()` 패턴 제거됨)
5
+ - onEnd 타입이 `void | Promise<void>`를 허용: `esbuild-client-config.ts:29` — `onEnd?: (result: esbuild.BuildResult) => void | Promise<void>;`
6
+ - sd-on-end 플러그인이 onEnd 반환값을 return: `esbuild-client-config.ts:220` — `return options.onEnd!(result);`
7
+ - client.worker.ts onEnd가 async 직접 전달 (fire-and-forget 제거): `client.worker.ts:240` — `onEnd: async (result: esbuild.BuildResult) => {` (이전의 `void (async () => { ... })()` 패턴 제거됨)
@@ -2,21 +2,21 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] createSourceFileCachePlugin이 모듈 스코프에 존재하고 esbuild.Plugin을 반환한다: lines 192-250, `function createSourceFileCachePlugin(): esbuild.Plugin` 반환 타입 명시, `name: "sd-build-start"` 유지
6
- - [x] createDevBuildEndHandler가 모듈 스코프에 존재하고 onEnd 콜백을 반환한다: lines 255-322, 반환 타입 `(result: esbuild.BuildResult) => Promise<void>`
7
- - [x] startWatch에서 추출 함수를 호출한다: line 385 `plugins: [createSourceFileCachePlugin()]`, line 386 `onEnd: createDevBuildEndHandler(basePath, actualPort, outdir, entryNames, info.pkgDir)`
8
- - [x] 파일 변경 감지 로직이 동일하다: createSourceFileCachePlugin onStart (lines 198-230) — watchFiles + typeScriptFileCache 순회, mtime 비교, invalidate 호출, buildStart 이벤트 전송 모두 원본과 동일
9
- - [x] mtime 기록 로직이 동일하다: createSourceFileCachePlugin onEnd (lines 232-247) — prevMtimes.clear() + mtime 기록 원본과 동일
10
- - [x] index.html 재생성 로직이 동일하다: createDevBuildEndHandler (lines 264-279) — lastMetafile 보관 + generateIndexHtml + writeFileSync 원본과 동일
11
- - [x] HMR 디스패치 로직이 동일하다: lines 281-284, `hmrService.onBuildEnd(result.metafile)` 조건부 호출 원본과 동일
12
- - [x] build 이벤트 전송 로직이 동일하다: lines 286-300, `sender.send("build", ...)` 조건부 호출 원본과 동일
13
- - [x] 초기 빌드 resolve 로직이 동일하다: lines 302-312, `isInitialBuild = false` + `initialBuildResolve?.()` 원본과 동일
14
- - [x] 에러 핸들링 로직이 동일하다: lines 313-320, catch 블록 원본과 동일
15
- - [x] 외부 인터페이스가 변경되지 않았다: export는 `export default sender`만 존재 (line 501), ClientBuildInfo/ClientBuildResult/ClientWorkerEvents 타입 변경 없음
16
- - [x] build 함수가 변경되지 않았다: lines 96-187, 원본과 동일
17
- - [x] stopWatch에 리셋 로직이 추가되었다: lines 472-475, `lastMetafile = undefined`, `isInitialBuild = true`, `initialBuildResolve = undefined`
18
- - [x] stopWatch 기존 정리 로직이 변경되지 않았다: lines 439-470, 5단계 정리(esbuild dispose, HMR 종료, HTTP 종료, public 감시 종료, index.html 감시 종료) 원본과 동일
19
- - [x] 모듈 스코프 변수가 올바르게 선언되었다: lines 67-69, 기존 변수(62-66) 바로 아래 배치
20
- - [x] startWatch가 ~110줄로 축소되었다: lines 327-434 = 107줄 (목표 ~110줄 달성)
21
- - [x] index.html watcher에서 lastMetafile 접근이 정상 동작한다: line 400, `if (lastMetafile == null) return;` — 모듈 스코프 변수로 접근
22
- - [x] 기존 테스트 6개 전부 통과: client-worker.spec.ts (3), client-worker.acc.spec.ts (3) — 회귀 없음
5
+ - createSourceFileCachePlugin이 모듈 스코프에 존재하고 esbuild.Plugin을 반환한다: lines 192-250, `function createSourceFileCachePlugin(): esbuild.Plugin` 반환 타입 명시, `name: "sd-build-start"` 유지
6
+ - createDevBuildEndHandler가 모듈 스코프에 존재하고 onEnd 콜백을 반환한다: lines 255-322, 반환 타입 `(result: esbuild.BuildResult) => Promise<void>`
7
+ - startWatch에서 추출 함수를 호출한다: line 385 `plugins: [createSourceFileCachePlugin()]`, line 386 `onEnd: createDevBuildEndHandler(basePath, actualPort, outdir, entryNames, info.pkgDir)`
8
+ - 파일 변경 감지 로직이 동일하다: createSourceFileCachePlugin onStart (lines 198-230) — watchFiles + typeScriptFileCache 순회, mtime 비교, invalidate 호출, buildStart 이벤트 전송 모두 원본과 동일
9
+ - mtime 기록 로직이 동일하다: createSourceFileCachePlugin onEnd (lines 232-247) — prevMtimes.clear() + mtime 기록 원본과 동일
10
+ - index.html 재생성 로직이 동일하다: createDevBuildEndHandler (lines 264-279) — lastMetafile 보관 + generateIndexHtml + writeFileSync 원본과 동일
11
+ - HMR 디스패치 로직이 동일하다: lines 281-284, `hmrService.onBuildEnd(result.metafile)` 조건부 호출 원본과 동일
12
+ - build 이벤트 전송 로직이 동일하다: lines 286-300, `sender.send("build", ...)` 조건부 호출 원본과 동일
13
+ - 초기 빌드 resolve 로직이 동일하다: lines 302-312, `isInitialBuild = false` + `initialBuildResolve?.()` 원본과 동일
14
+ - 에러 핸들링 로직이 동일하다: lines 313-320, catch 블록 원본과 동일
15
+ - 외부 인터페이스가 변경되지 않았다: export는 `export default sender`만 존재 (line 501), ClientBuildInfo/ClientBuildResult/ClientWorkerEvents 타입 변경 없음
16
+ - build 함수가 변경되지 않았다: lines 96-187, 원본과 동일
17
+ - stopWatch에 리셋 로직이 추가되었다: lines 472-475, `lastMetafile = undefined`, `isInitialBuild = true`, `initialBuildResolve = undefined`
18
+ - stopWatch 기존 정리 로직이 변경되지 않았다: lines 439-470, 5단계 정리(esbuild dispose, HMR 종료, HTTP 종료, public 감시 종료, index.html 감시 종료) 원본과 동일
19
+ - 모듈 스코프 변수가 올바르게 선언되었다: lines 67-69, 기존 변수(62-66) 바로 아래 배치
20
+ - startWatch가 ~110줄로 축소되었다: lines 327-434 = 107줄 (목표 ~110줄 달성)
21
+ - index.html watcher에서 lastMetafile 접근이 정상 동작한다: line 400, `if (lastMetafile == null) return;` — 모듈 스코프 변수로 접근
22
+ - 기존 테스트 6개 전부 통과: client-worker.spec.ts (3), client-worker.acc.spec.ts (3) — 회귀 없음
@@ -2,11 +2,11 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] onStart에서 `typeScriptFileCache.keys()`가 watchTargets에 포함: `client.worker.ts:266` — `...typeScriptFileCache.keys()`가 `watchTargets` 배열에 spread되어 포함됨
6
- - [x] onStart에서 `loadResultCache.watchFiles`도 여전히 watchTargets에 포함: `client.worker.ts:265` — `...loadResultCache.watchFiles`가 첫 번째로 spread됨 (기존 JS 동작 보존)
7
- - [x] onStart에서 watchTargets의 각 파일에 대해 mtime 비교 수행: `client.worker.ts:268-279` — `for (const file of watchTargets)` 루프에서 `fs.statSync(file).mtimeMs`와 `prevMtimes.get(file)` 비교
8
- - [x] 초기 빌드 직후 prevMtimes가 비어있으면 mtime 비교 스킵: `client.worker.ts:271-273` — `prev != null` 조건에 의해 `prevMtimes`에 없는 파일은 `changedFiles`에 추가되지 않음
9
- - [x] onEnd에서 `typeScriptFileCache.keys()`가 prevMtimes 기록 대상에 포함: `client.worker.ts:297` — `...esbuildResult.sourceFileCache.typeScriptFileCache.keys()`가 watchTargets에 spread됨
10
- - [x] onEnd에서 `loadResultCache.watchFiles`도 여전히 prevMtimes 기록 대상에 포함: `client.worker.ts:296` — `...esbuildResult.sourceFileCache.loadResultCache.watchFiles`가 첫 번째로 spread됨
11
- - [x] `typeScriptFileCache`가 `sourceFileCache`에서 destructuring으로 접근: `client.worker.ts:260` — `const { loadResultCache, typeScriptFileCache } = esbuildResult.sourceFileCache;` SourceFileCache의 public 속성 (`source-file-cache.js:52`)
12
- - [x] 삭제된 TS 파일에 대한 catch 처리: `client.worker.ts:275-279` — `catch` 블록에서 `prevMtimes.has(file)`인 경우 `changedFiles`에 추가 (기존 로직 동일)
5
+ - onStart에서 `typeScriptFileCache.keys()`가 watchTargets에 포함: `client.worker.ts:266` — `...typeScriptFileCache.keys()`가 `watchTargets` 배열에 spread되어 포함됨
6
+ - onStart에서 `loadResultCache.watchFiles`도 여전히 watchTargets에 포함: `client.worker.ts:265` — `...loadResultCache.watchFiles`가 첫 번째로 spread됨 (기존 JS 동작 보존)
7
+ - onStart에서 watchTargets의 각 파일에 대해 mtime 비교 수행: `client.worker.ts:268-279` — `for (const file of watchTargets)` 루프에서 `fs.statSync(file).mtimeMs`와 `prevMtimes.get(file)` 비교
8
+ - 초기 빌드 직후 prevMtimes가 비어있으면 mtime 비교 스킵: `client.worker.ts:271-273` — `prev != null` 조건에 의해 `prevMtimes`에 없는 파일은 `changedFiles`에 추가되지 않음
9
+ - onEnd에서 `typeScriptFileCache.keys()`가 prevMtimes 기록 대상에 포함: `client.worker.ts:297` — `...esbuildResult.sourceFileCache.typeScriptFileCache.keys()`가 watchTargets에 spread됨
10
+ - onEnd에서 `loadResultCache.watchFiles`도 여전히 prevMtimes 기록 대상에 포함: `client.worker.ts:296` — `...esbuildResult.sourceFileCache.loadResultCache.watchFiles`가 첫 번째로 spread됨
11
+ - `typeScriptFileCache`가 `sourceFileCache`에서 destructuring으로 접근: `client.worker.ts:260` — `const { loadResultCache, typeScriptFileCache } = esbuildResult.sourceFileCache;` SourceFileCache의 public 속성 (`source-file-cache.js:52`)
12
+ - 삭제된 TS 파일에 대한 catch 처리: `client.worker.ts:275-279` — `catch` 블록에서 `prevMtimes.has(file)`인 경우 `changedFiles`에 추가 (기존 로직 동일)
@@ -1,6 +1,6 @@
1
1
  # 포트 파일 기록/삭제 — LLM 검증
2
2
 
3
3
  ## 검증 항목
4
- - [x] client.worker에서 dev 모드 serverReady 후 writeDevPort 호출: `client.worker.ts:250-253` — serverReady(248) 직후 `fs.writeFileSync(path.join(distDir, ".dev-port"), String(actualPort))` 확인
5
- - [x] client.worker에서 legacy 모드 serverReady 후 writeDevPort 호출: `client.worker.ts:331-332` — serverReady(329) 직후 `fs.writeFileSync(path.join(info.pkgDir, "dist", ".dev-port"), String(serverPort))` 확인
6
- - [x] ViteEngine.stop()에서 deleteDevPort 호출: `ViteEngine.ts:202-204` — `fs.unlinkSync(portFile)` with try-catch 확인
4
+ - client.worker에서 dev 모드 serverReady 후 writeDevPort 호출: `client.worker.ts:250-253` — serverReady(248) 직후 `fs.writeFileSync(path.join(distDir, ".dev-port"), String(actualPort))` 확인
5
+ - client.worker에서 legacy 모드 serverReady 후 writeDevPort 호출: `client.worker.ts:331-332` — serverReady(329) 직후 `fs.writeFileSync(path.join(info.pkgDir, "dist", ".dev-port"), String(serverPort))` 확인
6
+ - ViteEngine.stop()에서 deleteDevPort 호출: `ViteEngine.ts:202-204` — `fs.unlinkSync(portFile)` with try-catch 확인
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] onChange에서 addOrRemove === true일 때 parseTsconfig + getPackageSourceFiles + pipeline.updateRootNames 호출: `ngtsc-build.worker.ts:299-306` — `if (addOrRemove)` 블록 내에서 `parseTsconfig(watchInfo!.pkgDir)` → `getPackageSourceFiles()` 또는 `getPackageFiles()` → `pipeline.updateRootNames(newSourceFiles)` 호출 체인이 정확히 구현됨
6
- - [x] includeTests 분기가 초기 설정(line 233-235)과 동일 패턴: 초기 설정 `watchInfo.output.includeTests === true ? getPackageFiles(...) : getPackageSourceFiles(...)` (line 233-235)와 onChange 내 분기 `watchInfo!.output.includeTests === true ? getPackageFiles(...) : getPackageSourceFiles(...)` (line 302-304)가 동일한 패턴을 사용
7
- - [x] addOrRemove === false일 때 rootNames 미갱신: `if (addOrRemove)` 블록(line 300-306) 내부에서만 rootNames 재스캔이 수행되므로, addOrRemove가 false일 때는 `pipeline.updateRootNames()`가 호출되지 않음. `shouldSkipRebuild`(line 293)에서 `hasAddOrRemove`가 false이고 변경 파일이 lastSourceFilePaths에 있으면 정상적으로 `pipeline.update(modifiedFiles)`만 실행됨
8
- - [x] rootNames 재스캔이 shouldSkipRebuild 이후 + pipeline.update() 이전에 위치: line 293에서 shouldSkipRebuild 체크 → line 299에서 rootNames 재스캔 → line 310에서 pipeline.update(). 올바른 순서
5
+ - onChange에서 addOrRemove === true일 때 parseTsconfig + getPackageSourceFiles + pipeline.updateRootNames 호출: `ngtsc-build.worker.ts:299-306` — `if (addOrRemove)` 블록 내에서 `parseTsconfig(watchInfo!.pkgDir)` → `getPackageSourceFiles()` 또는 `getPackageFiles()` → `pipeline.updateRootNames(newSourceFiles)` 호출 체인이 정확히 구현됨
6
+ - includeTests 분기가 초기 설정(line 233-235)과 동일 패턴: 초기 설정 `watchInfo.output.includeTests === true ? getPackageFiles(...) : getPackageSourceFiles(...)` (line 233-235)와 onChange 내 분기 `watchInfo!.output.includeTests === true ? getPackageFiles(...) : getPackageSourceFiles(...)` (line 302-304)가 동일한 패턴을 사용
7
+ - addOrRemove === false일 때 rootNames 미갱신: `if (addOrRemove)` 블록(line 300-306) 내부에서만 rootNames 재스캔이 수행되므로, addOrRemove가 false일 때는 `pipeline.updateRootNames()`가 호출되지 않음. `shouldSkipRebuild`(line 293)에서 `hasAddOrRemove`가 false이고 변경 파일이 lastSourceFilePaths에 있으면 정상적으로 `pipeline.update(modifiedFiles)`만 실행됨
8
+ - rootNames 재스캔이 shouldSkipRebuild 이후 + pipeline.update() 이전에 위치: line 293에서 shouldSkipRebuild 체크 → line 299에서 rootNames 재스캔 → line 310에서 pipeline.update(). 올바른 순서
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] try-finally 패턴 적용: `server-build.worker.ts:434-442` — oldContext 캡처 후 try 블록에서 새 context 생성, finally에서 oldContext.dispose() 호출
6
- - [x] 성공 시 dispose: try 블록에서 새 context 생성 성공 → finally에서 oldContext.dispose() 실행
7
- - [x] 실패 시 dispose: createEsbuildWatchContext() 예외 시 → finally에서 oldContext.dispose() 실행 보장
8
- - [x] null 안전: `if (oldContext != null)` 가드로 oldContext가 없는 경우(output.js=false 등) 안전
5
+ - try-finally 패턴 적용: `server-build.worker.ts:434-442` — oldContext 캡처 후 try 블록에서 새 context 생성, finally에서 oldContext.dispose() 호출
6
+ - 성공 시 dispose: try 블록에서 새 context 생성 성공 → finally에서 oldContext.dispose() 실행
7
+ - 실패 시 dispose: createEsbuildWatchContext() 예외 시 → finally에서 oldContext.dispose() 실행 보장
8
+ - null 안전: `if (oldContext != null)` 가드로 oldContext가 없는 경우(output.js=false 등) 안전
@@ -2,8 +2,8 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] 프로덕션 빌드에 Worker 플러그인 포함: `server-build.worker.ts:169`에서 `plugins: [createWorkerBundlePlugin(), tscPlugin.plugin]`로 설정됨. Worker 플러그인이 tsc 플러그인보다 앞에 위치.
6
- - [x] Watch/dev 빌드에 Worker 플러그인 포함: `server-esbuild-context.ts:66-69`에서 `workerPlugin` 변수로 생성 후 tsc 유무에 따라 `[workerPlugin, tscPlugin.plugin]` 또는 `[workerPlugin]`으로 설정됨.
7
- - [x] Worker 패턴 없는 서버 코드 투명 통과: `esbuild-worker-plugin.ts:83-85`에서 `content.includes("Worker")`가 false면 즉시 `undefined` 반환. `esbuild-worker-plugin.ts:197`의 onLoad에서 `result == null`이면 `undefined` 반환하여 다음 핸들러에 위임.
8
- - [x] 기존 tsc 플러그인/external 처리 미변경: `createServerEsbuildOptions` 함수 미수정. tsc 플러그인 생성 로직 미변경. external 처리 미변경.
9
- - [x] import 경로에 `.js` 확장자 미사용: 두 파일 모두 `from "../esbuild/esbuild-worker-plugin"` (확장자 없음)
5
+ - 프로덕션 빌드에 Worker 플러그인 포함: `server-build.worker.ts:169`에서 `plugins: [createWorkerBundlePlugin(), tscPlugin.plugin]`로 설정됨. Worker 플러그인이 tsc 플러그인보다 앞에 위치.
6
+ - Watch/dev 빌드에 Worker 플러그인 포함: `server-esbuild-context.ts:66-69`에서 `workerPlugin` 변수로 생성 후 tsc 유무에 따라 `[workerPlugin, tscPlugin.plugin]` 또는 `[workerPlugin]`으로 설정됨.
7
+ - Worker 패턴 없는 서버 코드 투명 통과: `esbuild-worker-plugin.ts:83-85`에서 `content.includes("Worker")`가 false면 즉시 `undefined` 반환. `esbuild-worker-plugin.ts:197`의 onLoad에서 `result == null`이면 `undefined` 반환하여 다음 핸들러에 위임.
8
+ - 기존 tsc 플러그인/external 처리 미변경: `createServerEsbuildOptions` 함수 미수정. tsc 플러그인 생성 로직 미변경. external 처리 미변경.
9
+ - import 경로에 `.js` 확장자 미사용: 두 파일 모두 `from "../esbuild/esbuild-worker-plugin"` (확장자 없음)
@@ -2,13 +2,13 @@
2
2
 
3
3
  ## 검증 항목
4
4
 
5
- - [x] rebuildAll()이 startWatch() 내부 클로저로 정의: `server-build.worker.ts:272` — startWatch (`:259`) 내부에 `async function rebuildAll()` 정의 확인
6
- - [x] lastBuilderProgram이 startWatch 로컬 변수: `server-build.worker.ts:264` — `let lastBuilderProgram` startWatch 함수 스코프 내 정의 확인
7
- - [x] watchLintRunner가 startWatch 로컬 변수: `server-build.worker.ts:265` — `let watchLintRunner` startWatch 함수 스코프 내 정의 확인
8
- - [x] watchInfo 모듈 스코프 변수 제거: 모듈 스코프에 `watchInfo` 선언 없음 확인, startWatch의 `info` 파라미터를 직접 사용
9
- - [x] cleanup()에서 lastBuilderProgram 참조 제거: `server-build.worker.ts:108-123` — cleanup 함수에 lastBuilderProgram 참조 없음 확인
10
- - [x] startWatch에서 createContext에 tsc 옵션 전달: `server-build.worker.ts:348-359` — `tsc: { cwd, output: { dts }, env, includeTests }` 옵션 포함 확인
11
- - [x] build() js=true에서 createTscPlugin 로컬 생성: `server-build.worker.ts:153-159` — build 함수 내 `const tscPlugin = createTscPlugin({...})` 확인
12
- - [x] build() js=false에서 runTscPackageBuild 직접 호출: `server-build.worker.ts:192-199` — `runTscPackageBuild({...})` 직접 호출 확인
13
- - [x] 외부 인터페이스(ServerBuildInfo/WatchInfo/Result/WorkerEvents) 변경 없음: 타입 정의 `:33-96` 변경 없음 확인
14
- - [x] runTscPackageBuild import 유지: `server-build.worker.ts:19` — import 존재 확인 (js=false fallback용)
5
+ - rebuildAll()이 startWatch() 내부 클로저로 정의: `server-build.worker.ts:272` — startWatch (`:259`) 내부에 `async function rebuildAll()` 정의 확인
6
+ - lastBuilderProgram이 startWatch 로컬 변수: `server-build.worker.ts:264` — `let lastBuilderProgram` startWatch 함수 스코프 내 정의 확인
7
+ - watchLintRunner가 startWatch 로컬 변수: `server-build.worker.ts:265` — `let watchLintRunner` startWatch 함수 스코프 내 정의 확인
8
+ - watchInfo 모듈 스코프 변수 제거: 모듈 스코프에 `watchInfo` 선언 없음 확인, startWatch의 `info` 파라미터를 직접 사용
9
+ - cleanup()에서 lastBuilderProgram 참조 제거: `server-build.worker.ts:108-123` — cleanup 함수에 lastBuilderProgram 참조 없음 확인
10
+ - startWatch에서 createContext에 tsc 옵션 전달: `server-build.worker.ts:348-359` — `tsc: { cwd, output: { dts }, env, includeTests }` 옵션 포함 확인
11
+ - build() js=true에서 createTscPlugin 로컬 생성: `server-build.worker.ts:153-159` — build 함수 내 `const tscPlugin = createTscPlugin({...})` 확인
12
+ - build() js=false에서 runTscPackageBuild 직접 호출: `server-build.worker.ts:192-199` — `runTscPackageBuild({...})` 직접 호출 확인
13
+ - 외부 인터페이스(ServerBuildInfo/WatchInfo/Result/WorkerEvents) 변경 없음: 타입 정의 `:33-96` 변경 없음 확인
14
+ - runTscPackageBuild import 유지: `server-build.worker.ts:19` — import 존재 확인 (js=false fallback용)