@simplysm/sd-cli 14.0.10 → 14.0.12
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.
- package/README.md +58 -253
- package/dist/angular/client-transform-stylesheet.js +1 -1
- package/dist/angular/client-transform-stylesheet.js.map +1 -1
- package/dist/angular/vite-angular-plugin.d.ts +1 -1
- package/dist/angular/vite-angular-plugin.d.ts.map +1 -1
- package/dist/angular/vite-angular-plugin.js +60 -34
- package/dist/angular/vite-angular-plugin.js.map +1 -1
- package/dist/angular/vite-postcss-inline-plugin.d.ts +1 -1
- package/dist/angular/vite-postcss-inline-plugin.js +1 -1
- package/dist/capacitor/capacitor.d.ts +14 -2
- package/dist/capacitor/capacitor.d.ts.map +1 -1
- package/dist/capacitor/capacitor.js +131 -17
- package/dist/capacitor/capacitor.js.map +1 -1
- package/dist/commands/build.d.ts +3 -10
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +3 -10
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/check.js +3 -3
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/dev.d.ts +3 -9
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +3 -9
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/device.d.ts +13 -0
- package/dist/commands/device.d.ts.map +1 -0
- package/dist/commands/device.js +53 -0
- package/dist/commands/device.js.map +1 -0
- package/dist/commands/publish.d.ts +1 -1
- package/dist/commands/publish.d.ts.map +1 -1
- package/dist/commands/publish.js +18 -26
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/replace-deps.d.ts +3 -3
- package/dist/commands/replace-deps.d.ts.map +1 -1
- package/dist/commands/replace-deps.js +1 -1
- package/dist/commands/typecheck.d.ts +4 -3
- package/dist/commands/typecheck.d.ts.map +1 -1
- package/dist/commands/typecheck.js +5 -11
- package/dist/commands/typecheck.js.map +1 -1
- package/dist/commands/watch.d.ts +9 -9
- package/dist/commands/watch.js +9 -9
- package/dist/electron/electron.d.ts.map +1 -1
- package/dist/electron/electron.js +42 -3
- package/dist/electron/electron.js.map +1 -1
- package/dist/engines/BaseEngine.d.ts +1 -1
- package/dist/engines/BaseEngine.d.ts.map +1 -1
- package/dist/engines/BaseEngine.js +3 -1
- package/dist/engines/BaseEngine.js.map +1 -1
- package/dist/engines/NgtscEngine.d.ts +7 -7
- package/dist/engines/NgtscEngine.d.ts.map +1 -1
- package/dist/engines/NgtscEngine.js +3 -3
- package/dist/engines/ServerEsbuildEngine.d.ts +7 -7
- package/dist/engines/ServerEsbuildEngine.d.ts.map +1 -1
- package/dist/engines/ServerEsbuildEngine.js +3 -3
- package/dist/engines/TscEngine.d.ts +7 -7
- package/dist/engines/TscEngine.d.ts.map +1 -1
- package/dist/engines/TscEngine.js +3 -3
- package/dist/engines/ViteEngine.d.ts +1 -1
- package/dist/engines/ViteEngine.d.ts.map +1 -1
- package/dist/engines/ViteEngine.js +7 -12
- package/dist/engines/ViteEngine.js.map +1 -1
- package/dist/engines/index.d.ts +5 -5
- package/dist/engines/index.js +5 -5
- package/dist/engines/types.d.ts +20 -20
- package/dist/engines/types.d.ts.map +1 -1
- package/dist/infra/ResultCollector.d.ts +9 -9
- package/dist/infra/ResultCollector.js +8 -8
- package/dist/infra/SignalHandler.d.ts +7 -7
- package/dist/infra/SignalHandler.js +7 -7
- package/dist/infra/WorkerManager.d.ts +14 -14
- package/dist/infra/WorkerManager.js +14 -14
- package/dist/orchestrators/BuildOrchestrator.d.ts +25 -25
- package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/BuildOrchestrator.js +29 -29
- package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
- package/dist/orchestrators/DevWatchOrchestrator.d.ts +7 -7
- package/dist/orchestrators/DevWatchOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/DevWatchOrchestrator.js +35 -57
- package/dist/orchestrators/DevWatchOrchestrator.js.map +1 -1
- package/dist/sd-cli-entry.d.ts +2 -2
- package/dist/sd-cli-entry.d.ts.map +1 -1
- package/dist/sd-cli-entry.js +45 -9
- package/dist/sd-cli-entry.js.map +1 -1
- package/dist/sd-cli.d.ts +3 -3
- package/dist/sd-cli.js +16 -16
- package/dist/sd-cli.js.map +1 -1
- package/dist/sd-config.types.d.ts +105 -105
- package/dist/sd-config.types.d.ts.map +1 -1
- package/dist/utils/angular-compiler.js +5 -5
- package/dist/utils/angular-compiler.js.map +1 -1
- package/dist/utils/build-env.d.ts +1 -1
- package/dist/utils/build-env.js +1 -1
- package/dist/utils/concurrency.d.ts +7 -7
- package/dist/utils/concurrency.js +7 -7
- package/dist/utils/copy-public.d.ts +9 -9
- package/dist/utils/copy-public.js +17 -17
- package/dist/utils/copy-public.js.map +1 -1
- package/dist/utils/copy-src.d.ts +9 -9
- package/dist/utils/copy-src.js +11 -11
- package/dist/utils/copy-src.js.map +1 -1
- package/dist/utils/engine-stop.d.ts +8 -9
- package/dist/utils/engine-stop.d.ts.map +1 -1
- package/dist/utils/engine-stop.js +9 -10
- package/dist/utils/engine-stop.js.map +1 -1
- package/dist/utils/esbuild-config.d.ts +23 -23
- package/dist/utils/esbuild-config.d.ts.map +1 -1
- package/dist/utils/esbuild-config.js +25 -25
- package/dist/utils/esbuild-config.js.map +1 -1
- package/dist/utils/lint-with-program.d.ts +15 -15
- package/dist/utils/lint-with-program.d.ts.map +1 -1
- package/dist/utils/lint-with-program.js +29 -29
- package/dist/utils/lint-with-program.js.map +1 -1
- package/dist/utils/ngtsc-build-core.d.ts +8 -8
- package/dist/utils/ngtsc-build-core.d.ts.map +1 -1
- package/dist/utils/ngtsc-build-core.js +14 -14
- package/dist/utils/ngtsc-build-core.js.map +1 -1
- package/dist/utils/output-path-rewriter.d.ts +14 -14
- package/dist/utils/output-path-rewriter.js +18 -18
- package/dist/utils/output-path-rewriter.js.map +1 -1
- package/dist/utils/output-utils.d.ts +6 -6
- package/dist/utils/output-utils.js +11 -11
- package/dist/utils/output-utils.js.map +1 -1
- package/dist/utils/package-utils.d.ts +21 -21
- package/dist/utils/package-utils.d.ts.map +1 -1
- package/dist/utils/package-utils.js +56 -45
- package/dist/utils/package-utils.js.map +1 -1
- package/dist/utils/replace-deps.d.ts +25 -25
- package/dist/utils/replace-deps.d.ts.map +1 -1
- package/dist/utils/replace-deps.js +84 -65
- package/dist/utils/replace-deps.js.map +1 -1
- package/dist/utils/sd-config.d.ts +3 -3
- package/dist/utils/sd-config.js +3 -3
- package/dist/utils/tsc-build.d.ts +13 -13
- package/dist/utils/tsc-build.d.ts.map +1 -1
- package/dist/utils/tsc-build.js +9 -9
- package/dist/utils/tsc-build.js.map +1 -1
- package/dist/utils/tsconfig.d.ts +11 -9
- package/dist/utils/tsconfig.d.ts.map +1 -1
- package/dist/utils/tsconfig.js +11 -9
- package/dist/utils/tsconfig.js.map +1 -1
- package/dist/utils/typecheck-non-package.d.ts +5 -6
- package/dist/utils/typecheck-non-package.d.ts.map +1 -1
- package/dist/utils/typecheck-non-package.js +7 -8
- package/dist/utils/typecheck-non-package.js.map +1 -1
- package/dist/utils/typecheck-serialization.d.ts +8 -8
- package/dist/utils/typecheck-serialization.d.ts.map +1 -1
- package/dist/utils/typecheck-serialization.js +12 -16
- package/dist/utils/typecheck-serialization.js.map +1 -1
- package/dist/utils/vite-config.d.ts +8 -5
- package/dist/utils/vite-config.d.ts.map +1 -1
- package/dist/utils/vite-config.js +36 -29
- package/dist/utils/vite-config.js.map +1 -1
- package/dist/utils/vite-scope-watch-plugin.d.ts.map +1 -1
- package/dist/utils/vite-scope-watch-plugin.js +1 -1
- package/dist/utils/vite-scope-watch-plugin.js.map +1 -1
- package/dist/utils/worker-events.d.ts +12 -12
- package/dist/utils/worker-events.d.ts.map +1 -1
- package/dist/utils/worker-events.js +10 -10
- package/dist/utils/worker-events.js.map +1 -1
- package/dist/utils/worker-utils.d.ts +12 -13
- package/dist/utils/worker-utils.d.ts.map +1 -1
- package/dist/utils/worker-utils.js +12 -13
- package/dist/utils/worker-utils.js.map +1 -1
- package/dist/vitest-plugin.d.ts.map +1 -1
- package/dist/vitest-plugin.js +5 -7
- package/dist/vitest-plugin.js.map +1 -1
- package/dist/workers/client.worker.d.ts +4 -2
- package/dist/workers/client.worker.d.ts.map +1 -1
- package/dist/workers/client.worker.js +209 -1
- package/dist/workers/client.worker.js.map +1 -1
- package/dist/workers/library-build.worker.d.ts +1 -1
- package/dist/workers/library-build.worker.d.ts.map +1 -1
- package/dist/workers/library-build.worker.js +7 -7
- package/dist/workers/library-build.worker.js.map +1 -1
- package/dist/workers/lint.worker.d.ts +2 -2
- package/dist/workers/lint.worker.js +2 -2
- package/dist/workers/ngtsc-build.worker.js +30 -30
- package/dist/workers/ngtsc-build.worker.js.map +1 -1
- package/dist/workers/server-build.worker.d.ts +17 -17
- package/dist/workers/server-build.worker.d.ts.map +1 -1
- package/dist/workers/server-build.worker.js +46 -46
- package/dist/workers/server-build.worker.js.map +1 -1
- package/dist/workers/server-runtime.worker.d.ts +7 -7
- package/dist/workers/server-runtime.worker.d.ts.map +1 -1
- package/dist/workers/server-runtime.worker.js +17 -17
- package/dist/workers/server-runtime.worker.js.map +1 -1
- package/docs/config.md +340 -0
- package/docs/publish-configuration-types.md +87 -0
- package/docs/pwa-configuration-types.md +55 -0
- package/docs/vitest-plugin.md +47 -0
- package/package.json +9 -7
- package/src/angular/client-transform-stylesheet.ts +1 -1
- package/src/angular/vite-angular-plugin.ts +70 -37
- package/src/angular/vite-postcss-inline-plugin.ts +1 -1
- package/src/capacitor/capacitor.ts +159 -23
- package/src/commands/build.ts +3 -10
- package/src/commands/check.ts +3 -3
- package/src/commands/dev.ts +3 -9
- package/src/commands/device.ts +65 -0
- package/src/commands/publish.ts +30 -26
- package/src/commands/replace-deps.ts +3 -3
- package/src/commands/typecheck.ts +7 -13
- package/src/commands/watch.ts +9 -9
- package/src/electron/electron.ts +49 -4
- package/src/engines/BaseEngine.ts +4 -1
- package/src/engines/NgtscEngine.ts +7 -7
- package/src/engines/ServerEsbuildEngine.ts +7 -7
- package/src/engines/TscEngine.ts +7 -7
- package/src/engines/ViteEngine.ts +8 -13
- package/src/engines/index.ts +5 -5
- package/src/engines/types.ts +20 -20
- package/src/infra/ResultCollector.ts +9 -9
- package/src/infra/SignalHandler.ts +7 -7
- package/src/infra/WorkerManager.ts +14 -14
- package/src/orchestrators/BuildOrchestrator.ts +37 -37
- package/src/orchestrators/DevWatchOrchestrator.ts +37 -61
- package/src/sd-cli-entry.ts +51 -9
- package/src/sd-cli.ts +16 -16
- package/src/sd-config.types.ts +107 -107
- package/src/utils/angular-compiler.ts +5 -5
- package/src/utils/build-env.ts +1 -1
- package/src/utils/concurrency.ts +7 -7
- package/src/utils/copy-public.ts +17 -17
- package/src/utils/copy-src.ts +11 -11
- package/src/utils/engine-stop.ts +9 -10
- package/src/utils/esbuild-config.ts +29 -29
- package/src/utils/lint-with-program.ts +34 -34
- package/src/utils/ngtsc-build-core.ts +17 -17
- package/src/utils/output-path-rewriter.ts +18 -18
- package/src/utils/output-utils.ts +11 -11
- package/src/utils/package-utils.ts +57 -45
- package/src/utils/replace-deps.ts +92 -67
- package/src/utils/sd-config.ts +3 -3
- package/src/utils/tsc-build.ts +18 -18
- package/src/utils/tsconfig.ts +11 -9
- package/src/utils/typecheck-non-package.ts +7 -8
- package/src/utils/typecheck-serialization.ts +13 -15
- package/src/utils/vite-config.ts +45 -35
- package/src/utils/vite-scope-watch-plugin.ts +6 -1
- package/src/utils/worker-events.ts +16 -16
- package/src/utils/worker-utils.ts +12 -13
- package/src/vitest-plugin.ts +5 -8
- package/src/workers/client.worker.ts +236 -2
- package/src/workers/library-build.worker.ts +8 -8
- package/src/workers/lint.worker.ts +2 -2
- package/src/workers/ngtsc-build.worker.ts +31 -31
- package/src/workers/server-build.worker.ts +60 -60
- package/src/workers/server-runtime.worker.ts +22 -22
- package/tests/angular/vite-angular-plugin-hmr-fallback.spec.ts +1 -0
- package/tests/angular/vite-angular-plugin-hmr.spec.ts +78 -0
- package/tests/angular/vite-angular-plugin.spec.ts +67 -0
- package/tests/capacitor/capacitor-build.spec.ts +6 -4
- package/tests/capacitor/capacitor-icon.spec.ts +7 -5
- package/tests/capacitor/capacitor-init.spec.ts +120 -10
- package/tests/capacitor/capacitor-run.spec.ts +14 -17
- package/tests/capacitor/capacitor-workspace.spec.ts +5 -3
- package/tests/commands/check.spec.ts +2 -2
- package/tests/commands/device.spec.ts +147 -0
- package/tests/commands/publish.spec.ts +2 -2
- package/tests/commands/typecheck.spec.ts +8 -0
- package/tests/electron/electron.spec.ts +12 -10
- package/tests/engines/base-engine.spec.ts +37 -0
- package/tests/engines/vite-engine.spec.ts +115 -3
- package/tests/orchestrators/dev-watch-orchestrator.spec.ts +21 -93
- package/tests/utils/vite-config.spec.ts +144 -90
- package/tests/workers/client-worker.spec.ts +690 -0
- package/tests/workers/server-build-worker.spec.ts +3 -3
|
@@ -7,12 +7,12 @@ import { exec } from "child_process";
|
|
|
7
7
|
import { promisify } from "util";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* replaceDeps 설정의 glob 패턴을 대상 패키지 목록과 매칭하여
|
|
11
|
+
* { targetName, sourcePath } 쌍을 반환한다.
|
|
12
12
|
*
|
|
13
|
-
* @param replaceDeps -
|
|
14
|
-
* @param targetNames -
|
|
15
|
-
* @returns
|
|
13
|
+
* @param replaceDeps - sd.config.ts의 replaceDeps 설정 (키: glob 패턴, 값: 소스 경로)
|
|
14
|
+
* @param targetNames - node_modules에서 찾은 패키지명 목록 (예: ["@simplysm/solid", ...])
|
|
15
|
+
* @returns 매칭된 { targetName, sourcePath } 배열
|
|
16
16
|
*/
|
|
17
17
|
export function resolveReplaceDepEntries(
|
|
18
18
|
replaceDeps: Record<string, string>,
|
|
@@ -21,7 +21,7 @@ export function resolveReplaceDepEntries(
|
|
|
21
21
|
const results: Array<{ targetName: string; sourcePath: string }> = [];
|
|
22
22
|
|
|
23
23
|
for (const [pattern, sourceTemplate] of Object.entries(replaceDeps)) {
|
|
24
|
-
//
|
|
24
|
+
// glob 패턴을 정규식으로 변환: * → (.*), . → \., / → [\\/]
|
|
25
25
|
const regexpText = pattern.replace(/[\\/.+*]/g, (ch) => {
|
|
26
26
|
if (ch === "*") return "(.*)";
|
|
27
27
|
if (ch === ".") return "\\.";
|
|
@@ -36,7 +36,7 @@ export function resolveReplaceDepEntries(
|
|
|
36
36
|
const match = regex.exec(targetName);
|
|
37
37
|
if (match == null) continue;
|
|
38
38
|
|
|
39
|
-
//
|
|
39
|
+
// 캡처 그룹이 있으면 소스 경로의 *를 캡처된 값으로 치환
|
|
40
40
|
const sourcePath = hasWildcard ? sourceTemplate.replace(/\*/g, match[1]) : sourceTemplate;
|
|
41
41
|
|
|
42
42
|
results.push({ targetName, sourcePath });
|
|
@@ -47,11 +47,11 @@ export function resolveReplaceDepEntries(
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
50
|
+
* pnpm-workspace.yaml 내용을 파싱하여 워크스페이스 패키지 glob 배열을 반환한다.
|
|
51
|
+
* 별도 YAML 라이브러리 없이 간단한 줄 파싱으로 처리한다.
|
|
52
52
|
*
|
|
53
|
-
* @param content -
|
|
54
|
-
* @returns
|
|
53
|
+
* @param content - pnpm-workspace.yaml 파일 내용
|
|
54
|
+
* @returns glob 패턴 배열 (예: ["packages/*", "tools/*"])
|
|
55
55
|
*/
|
|
56
56
|
export function parseWorkspaceGlobs(content: string): string[] {
|
|
57
57
|
const lines = content.split("\n");
|
|
@@ -66,7 +66,7 @@ export function parseWorkspaceGlobs(content: string): string[] {
|
|
|
66
66
|
continue;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
//
|
|
69
|
+
// packages 섹션의 목록 항목
|
|
70
70
|
if (inPackages && trimmed.startsWith("- ")) {
|
|
71
71
|
const value = trimmed
|
|
72
72
|
.slice(2)
|
|
@@ -76,7 +76,7 @@ export function parseWorkspaceGlobs(content: string): string[] {
|
|
|
76
76
|
continue;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
//
|
|
79
|
+
// 다른 섹션이 시작되면 종료
|
|
80
80
|
if (inPackages && trimmed !== "" && !trimmed.startsWith("#")) {
|
|
81
81
|
break;
|
|
82
82
|
}
|
|
@@ -86,16 +86,16 @@ export function parseWorkspaceGlobs(content: string): string[] {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
/**
|
|
89
|
-
*
|
|
89
|
+
* 복사 시 제외할 이름 목록
|
|
90
90
|
*/
|
|
91
91
|
const EXCLUDED_NAMES = new Set(["node_modules", "package.json", ".cache", "tests"]);
|
|
92
92
|
|
|
93
93
|
/**
|
|
94
|
-
*
|
|
95
|
-
*
|
|
94
|
+
* replaceDeps 복사용 필터 함수
|
|
95
|
+
* node_modules, package.json, .cache, tests를 제외한다.
|
|
96
96
|
*
|
|
97
|
-
* @param itemPath -
|
|
98
|
-
* @returns
|
|
97
|
+
* @param itemPath - 복사할 항목의 절대 경로
|
|
98
|
+
* @returns 복사 대상이면 true, 제외 대상이면 false
|
|
99
99
|
*/
|
|
100
100
|
function replaceDepsCopyFilter(itemPath: string): boolean {
|
|
101
101
|
const basename = path.basename(itemPath);
|
|
@@ -103,7 +103,7 @@ function replaceDepsCopyFilter(itemPath: string): boolean {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
/**
|
|
106
|
-
* replaceDeps
|
|
106
|
+
* replaceDeps 복사/교체 항목
|
|
107
107
|
*/
|
|
108
108
|
export interface ReplaceDepEntry {
|
|
109
109
|
targetName: string;
|
|
@@ -114,7 +114,7 @@ export interface ReplaceDepEntry {
|
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
/**
|
|
117
|
-
*
|
|
117
|
+
* watchReplaceDeps의 반환 타입
|
|
118
118
|
*/
|
|
119
119
|
export interface WatchReplaceDepResult {
|
|
120
120
|
entries: ReplaceDepEntry[];
|
|
@@ -122,13 +122,13 @@ export interface WatchReplaceDepResult {
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
/**
|
|
125
|
-
*
|
|
125
|
+
* 프로젝트 루트 및 워크스페이스 패키지 경로를 수집한다.
|
|
126
126
|
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
127
|
+
* pnpm-workspace.yaml을 파싱하여 워크스페이스 패키지의 절대 경로를 수집한다.
|
|
128
|
+
* 파일이 없거나 파싱 실패 시 루트 경로만 반환한다.
|
|
129
129
|
*
|
|
130
|
-
* @param projectRoot -
|
|
131
|
-
* @returns [
|
|
130
|
+
* @param projectRoot - 프로젝트 루트 경로
|
|
131
|
+
* @returns [루트, ...워크스페이스 패키지 경로] 배열
|
|
132
132
|
*/
|
|
133
133
|
async function collectSearchRoots(projectRoot: string): Promise<string[]> {
|
|
134
134
|
const searchRoots = [projectRoot];
|
|
@@ -143,23 +143,23 @@ async function collectSearchRoots(projectRoot: string): Promise<string[]> {
|
|
|
143
143
|
searchRoots.push(...dirs);
|
|
144
144
|
}
|
|
145
145
|
} catch {
|
|
146
|
-
//
|
|
146
|
+
// pnpm-workspace.yaml이 존재하지 않으면 루트만 처리
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
return searchRoots;
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
/**
|
|
153
|
-
*
|
|
153
|
+
* replaceDeps 설정에서 모든 교체 대상 항목을 해결한다.
|
|
154
154
|
*
|
|
155
|
-
* 1.
|
|
156
|
-
* 2.
|
|
157
|
-
* 3.
|
|
155
|
+
* 1. pnpm-workspace.yaml 파싱 → 워크스페이스 패키지 경로
|
|
156
|
+
* 2. [루트, ...워크스페이스 패키지] node_modules에서 매칭 패키지 탐색
|
|
157
|
+
* 3. 패턴 매칭 + 소스 경로 존재 확인 + symlink 해결
|
|
158
158
|
*
|
|
159
|
-
* @param projectRoot -
|
|
160
|
-
* @param replaceDeps -
|
|
161
|
-
* @param logger - consola
|
|
162
|
-
* @returns
|
|
159
|
+
* @param projectRoot - 프로젝트 루트 경로
|
|
160
|
+
* @param replaceDeps - sd.config.ts의 replaceDeps 설정
|
|
161
|
+
* @param logger - consola 로거
|
|
162
|
+
* @returns 해결된 교체 대상 항목 배열
|
|
163
163
|
*/
|
|
164
164
|
async function resolveAllReplaceDepEntries(
|
|
165
165
|
projectRoot: string,
|
|
@@ -167,35 +167,47 @@ async function resolveAllReplaceDepEntries(
|
|
|
167
167
|
logger: ReturnType<typeof consola.withTag>,
|
|
168
168
|
): Promise<ReplaceDepEntry[]> {
|
|
169
169
|
const entries: ReplaceDepEntry[] = [];
|
|
170
|
+
const searchedDirs = new Set<string>();
|
|
170
171
|
|
|
172
|
+
// 초기 탐색 대상: 프로젝트 루트 + workspace 패키지들의 node_modules
|
|
171
173
|
const searchRoots = await collectSearchRoots(projectRoot);
|
|
174
|
+
const pendingDirs: string[] = searchRoots.map((root) =>
|
|
175
|
+
pathx.posix(path.join(root, "node_modules")),
|
|
176
|
+
);
|
|
172
177
|
|
|
173
|
-
|
|
174
|
-
|
|
178
|
+
// 교체된 패키지의 node_modules도 재귀적으로 탐색 (간접 의존성 교체)
|
|
179
|
+
while (pendingDirs.length > 0) {
|
|
180
|
+
const nodeModulesDir = pendingDirs.pop()!;
|
|
181
|
+
|
|
182
|
+
if (searchedDirs.has(nodeModulesDir)) continue;
|
|
183
|
+
searchedDirs.add(nodeModulesDir);
|
|
175
184
|
|
|
176
185
|
try {
|
|
177
186
|
await fs.promises.access(nodeModulesDir);
|
|
178
187
|
} catch {
|
|
179
|
-
|
|
188
|
+
logger.debug(`[replace-deps] 접근 불가: ${nodeModulesDir}`);
|
|
189
|
+
continue;
|
|
180
190
|
}
|
|
181
191
|
|
|
182
|
-
//
|
|
192
|
+
// replaceDeps의 각 glob 패턴으로 node_modules 디렉토리 탐색
|
|
183
193
|
const targetNames: string[] = [];
|
|
184
194
|
for (const pattern of Object.keys(replaceDeps)) {
|
|
185
195
|
const matches = await glob(pattern, { cwd: nodeModulesDir });
|
|
186
196
|
targetNames.push(...matches);
|
|
187
197
|
}
|
|
188
198
|
|
|
199
|
+
logger.debug(`[replace-deps] 탐색: ${nodeModulesDir} → ${targetNames.length}개 매칭 (${targetNames.join(", ")})`);
|
|
200
|
+
|
|
189
201
|
if (targetNames.length === 0) continue;
|
|
190
202
|
|
|
191
|
-
//
|
|
203
|
+
// 패턴 매칭 및 경로 해결
|
|
192
204
|
const matchedEntries = resolveReplaceDepEntries(replaceDeps, targetNames);
|
|
193
205
|
|
|
194
206
|
for (const { targetName, sourcePath } of matchedEntries) {
|
|
195
207
|
const targetPath = pathx.posix(path.join(nodeModulesDir, targetName));
|
|
196
208
|
const resolvedSourcePath = pathx.posixResolve(projectRoot, sourcePath);
|
|
197
209
|
|
|
198
|
-
//
|
|
210
|
+
// 소스 경로 존재 확인
|
|
199
211
|
try {
|
|
200
212
|
await fs.promises.access(resolvedSourcePath);
|
|
201
213
|
} catch {
|
|
@@ -203,7 +215,7 @@ async function resolveAllReplaceDepEntries(
|
|
|
203
215
|
continue;
|
|
204
216
|
}
|
|
205
217
|
|
|
206
|
-
//
|
|
218
|
+
// targetPath가 symlink이면 실제 .pnpm 저장소 경로로 해결
|
|
207
219
|
let actualTargetPath = targetPath;
|
|
208
220
|
try {
|
|
209
221
|
const stat = await fs.promises.lstat(targetPath);
|
|
@@ -211,9 +223,12 @@ async function resolveAllReplaceDepEntries(
|
|
|
211
223
|
actualTargetPath = pathx.posix(await fs.promises.realpath(targetPath));
|
|
212
224
|
}
|
|
213
225
|
} catch {
|
|
214
|
-
//
|
|
226
|
+
// targetPath가 존재하지 않으면 그대로 사용
|
|
215
227
|
}
|
|
216
228
|
|
|
229
|
+
// 동일 actualTargetPath가 이미 등록된 경우 건너뜀 (pnpm 중복 방지)
|
|
230
|
+
if (entries.some((e) => e.actualTargetPath === actualTargetPath)) continue;
|
|
231
|
+
|
|
217
232
|
entries.push({
|
|
218
233
|
targetName,
|
|
219
234
|
sourcePath,
|
|
@@ -221,6 +236,13 @@ async function resolveAllReplaceDepEntries(
|
|
|
221
236
|
resolvedSourcePath,
|
|
222
237
|
actualTargetPath,
|
|
223
238
|
});
|
|
239
|
+
|
|
240
|
+
// 교체된 패키지의 node_modules를 탐색 대기열에 추가
|
|
241
|
+
const depth = targetName.split(/[/\\]/).length;
|
|
242
|
+
const entryNodeModulesDir = pathx.posix(
|
|
243
|
+
path.resolve(actualTargetPath, ...Array(depth).fill("..")),
|
|
244
|
+
);
|
|
245
|
+
pendingDirs.push(entryNodeModulesDir);
|
|
224
246
|
}
|
|
225
247
|
}
|
|
226
248
|
|
|
@@ -228,14 +250,14 @@ async function resolveAllReplaceDepEntries(
|
|
|
228
250
|
}
|
|
229
251
|
|
|
230
252
|
/**
|
|
231
|
-
*
|
|
253
|
+
* replaceDeps 설정에 따라 node_modules의 패키지를 소스 디렉토리로 교체한다.
|
|
232
254
|
*
|
|
233
|
-
* 1.
|
|
234
|
-
* 2.
|
|
235
|
-
* 3.
|
|
255
|
+
* 1. pnpm-workspace.yaml 파싱 → 워크스페이스 패키지 경로
|
|
256
|
+
* 2. [루트, ...워크스페이스 패키지] node_modules에서 매칭 패키지 탐색
|
|
257
|
+
* 3. 기존 symlink/디렉토리 제거 → 소스 경로 복사 (node_modules, package.json, .cache, tests 제외)
|
|
236
258
|
*
|
|
237
|
-
* @param projectRoot -
|
|
238
|
-
* @param replaceDeps -
|
|
259
|
+
* @param projectRoot - 프로젝트 루트 경로
|
|
260
|
+
* @param replaceDeps - sd.config.ts의 replaceDeps 설정
|
|
239
261
|
*/
|
|
240
262
|
export async function setupReplaceDeps(
|
|
241
263
|
projectRoot: string,
|
|
@@ -250,7 +272,7 @@ export async function setupReplaceDeps(
|
|
|
250
272
|
|
|
251
273
|
for (const { targetName, resolvedSourcePath, actualTargetPath } of entries) {
|
|
252
274
|
try {
|
|
253
|
-
//
|
|
275
|
+
// 소스 파일을 actualTargetPath에 덮어쓰기 복사 (기존 디렉토리 유지, symlink 보존)
|
|
254
276
|
await fsx.copy(resolvedSourcePath, actualTargetPath, replaceDepsCopyFilter);
|
|
255
277
|
|
|
256
278
|
setupCount += 1;
|
|
@@ -261,7 +283,7 @@ export async function setupReplaceDeps(
|
|
|
261
283
|
|
|
262
284
|
logger.success(`replace-deps 설정 완료 (${setupCount}개 의존성 교체)`);
|
|
263
285
|
|
|
264
|
-
//
|
|
286
|
+
// 교체된 패키지의 postinstall 스크립트 실행
|
|
265
287
|
for (const { targetName, resolvedSourcePath, actualTargetPath } of entries) {
|
|
266
288
|
const sourcePkgJsonPath = pathx.posix(path.join(resolvedSourcePath, "package.json"));
|
|
267
289
|
try {
|
|
@@ -282,16 +304,16 @@ export async function setupReplaceDeps(
|
|
|
282
304
|
}
|
|
283
305
|
|
|
284
306
|
/**
|
|
285
|
-
*
|
|
307
|
+
* replaceDeps 설정에 따라 소스 디렉토리를 감시하고 변경사항을 대상 경로에 복사한다.
|
|
286
308
|
*
|
|
287
|
-
* 1.
|
|
288
|
-
* 2.
|
|
289
|
-
* 3.
|
|
290
|
-
* 4.
|
|
309
|
+
* 1. pnpm-workspace.yaml 파싱 → 워크스페이스 패키지 경로
|
|
310
|
+
* 2. [루트, ...워크스페이스 패키지] node_modules에서 매칭 패키지 탐색
|
|
311
|
+
* 3. FsWatcher로 소스 디렉토리 감시 (300ms 딜레이)
|
|
312
|
+
* 4. 변경사항을 대상 경로에 복사 (node_modules, package.json, .cache, tests 제외)
|
|
291
313
|
*
|
|
292
|
-
* @param projectRoot -
|
|
293
|
-
* @param replaceDeps -
|
|
294
|
-
* @returns entries
|
|
314
|
+
* @param projectRoot - 프로젝트 루트 경로
|
|
315
|
+
* @param replaceDeps - sd.config.ts의 replaceDeps 설정
|
|
316
|
+
* @returns entries 및 dispose 함수
|
|
295
317
|
*/
|
|
296
318
|
export async function watchReplaceDeps(
|
|
297
319
|
projectRoot: string,
|
|
@@ -301,7 +323,7 @@ export async function watchReplaceDeps(
|
|
|
301
323
|
|
|
302
324
|
const entries = await resolveAllReplaceDepEntries(projectRoot, replaceDeps, logger);
|
|
303
325
|
|
|
304
|
-
//
|
|
326
|
+
// 소스 디렉토리 감시자 설정
|
|
305
327
|
const watchers: FsWatcher[] = [];
|
|
306
328
|
const watchedSources = new Set<string>();
|
|
307
329
|
|
|
@@ -315,10 +337,13 @@ export async function watchReplaceDeps(
|
|
|
315
337
|
pathx.posix(path.join(entry.resolvedSourcePath, name)),
|
|
316
338
|
);
|
|
317
339
|
|
|
318
|
-
const watcher = await FsWatcher.watch([entry.resolvedSourcePath], {
|
|
340
|
+
const watcher = await FsWatcher.watch([entry.resolvedSourcePath], {
|
|
341
|
+
followSymlinks: false,
|
|
342
|
+
ignored: [...EXCLUDED_NAMES].map((name) => `**/${name}`),
|
|
343
|
+
});
|
|
319
344
|
watcher.onChange({ delay: 300 }, async (changeInfos) => {
|
|
320
345
|
for (const { path: changedPath } of changeInfos) {
|
|
321
|
-
//
|
|
346
|
+
// 제외 항목 필터: basename 매칭 또는 제외 디렉토리 내 경로
|
|
322
347
|
if (
|
|
323
348
|
EXCLUDED_NAMES.has(path.basename(changedPath)) ||
|
|
324
349
|
excludedPaths.some((ep) => pathx.isChildPath(changedPath, ep))
|
|
@@ -326,26 +351,26 @@ export async function watchReplaceDeps(
|
|
|
326
351
|
continue;
|
|
327
352
|
}
|
|
328
353
|
|
|
329
|
-
//
|
|
354
|
+
// 이 소스 경로를 사용하는 모든 항목에 대해 복사
|
|
330
355
|
for (const e of entries) {
|
|
331
356
|
if (e.resolvedSourcePath !== entry.resolvedSourcePath) continue;
|
|
332
357
|
|
|
333
|
-
//
|
|
358
|
+
// 소스로부터의 상대 경로 계산
|
|
334
359
|
const relativePath = pathx.posix(path.relative(e.resolvedSourcePath, changedPath));
|
|
335
360
|
const destPath = pathx.posix(path.join(e.actualTargetPath, relativePath));
|
|
336
361
|
|
|
337
362
|
try {
|
|
338
|
-
//
|
|
363
|
+
// 소스 존재 여부 확인
|
|
339
364
|
let sourceExists = false;
|
|
340
365
|
try {
|
|
341
366
|
await fs.promises.access(changedPath);
|
|
342
367
|
sourceExists = true;
|
|
343
368
|
} catch {
|
|
344
|
-
//
|
|
369
|
+
// 소스가 삭제됨
|
|
345
370
|
}
|
|
346
371
|
|
|
347
372
|
if (sourceExists) {
|
|
348
|
-
//
|
|
373
|
+
// 소스가 디렉토리인지 파일인지 확인
|
|
349
374
|
const stat = await fs.promises.stat(changedPath);
|
|
350
375
|
if (stat.isDirectory()) {
|
|
351
376
|
await fsx.mkdir(destPath);
|
|
@@ -354,7 +379,7 @@ export async function watchReplaceDeps(
|
|
|
354
379
|
await fsx.copy(changedPath, destPath, replaceDepsCopyFilter);
|
|
355
380
|
}
|
|
356
381
|
} else {
|
|
357
|
-
//
|
|
382
|
+
// 소스가 삭제됨 → 대상도 삭제
|
|
358
383
|
await fsx.rm(destPath);
|
|
359
384
|
}
|
|
360
385
|
} catch (err) {
|
package/src/utils/sd-config.ts
CHANGED
|
@@ -7,9 +7,9 @@ import type { SdConfig, SdConfigParams } from "../sd-config.types";
|
|
|
7
7
|
const logger = consola.withTag("sd:cli:sd-config");
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
* @returns SdConfig
|
|
12
|
-
* @throws
|
|
10
|
+
* sd.config.ts를 로드한다.
|
|
11
|
+
* @returns SdConfig 객체
|
|
12
|
+
* @throws sd.config.ts가 없거나 형식이 잘못된 경우
|
|
13
13
|
*/
|
|
14
14
|
export async function loadSdConfig(params: SdConfigParams): Promise<SdConfig> {
|
|
15
15
|
const sdConfigPath = pathx.posixResolve(params.cwd, "sd.config.ts");
|
package/src/utils/tsc-build.ts
CHANGED
|
@@ -17,23 +17,23 @@ import { createOutputPathRewriter, addJsExtensionToImports } from "./output-path
|
|
|
17
17
|
import { isWorkspaceDiagnostic, formatDiagnosticError } from "./diagnostic-utils";
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
20
|
+
* 패키지 모드 tsc 빌드 옵션
|
|
21
21
|
*/
|
|
22
22
|
export interface TscPackageBuildOptions {
|
|
23
23
|
pkgDir: string;
|
|
24
24
|
cwd: string;
|
|
25
|
-
/**
|
|
25
|
+
/** 출력 제어 플래그: emit할 파일 종류 */
|
|
26
26
|
output: { js: boolean; dts: boolean };
|
|
27
|
-
/**
|
|
27
|
+
/** 미리 파싱된 tsconfig. 제공 시 parseTsconfig() 호출을 스킵한다. */
|
|
28
28
|
parsedConfig?: ts.ParsedCommandLine;
|
|
29
|
-
/**
|
|
29
|
+
/** 타입체크 환경. 설정 시 getCompilerOptionsForEnv()로 compilerOptions를 조정한다. */
|
|
30
30
|
env?: TypecheckEnv;
|
|
31
|
-
/**
|
|
31
|
+
/** 타입체크 전용 모드에서 tests/ 파일 포함 여부. 기본값 false. */
|
|
32
32
|
includeTests?: boolean;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
36
|
+
* 패키지 모드 tsc 빌드 결과
|
|
37
37
|
*/
|
|
38
38
|
export interface TscPackageBuildResult {
|
|
39
39
|
success: boolean;
|
|
@@ -41,20 +41,20 @@ export interface TscPackageBuildResult {
|
|
|
41
41
|
diagnostics: SerializedDiagnostic[];
|
|
42
42
|
errorCount: number;
|
|
43
43
|
warningCount: number;
|
|
44
|
-
/**
|
|
44
|
+
/** lint-with-program 통합을 위해 노출된 ts.Program */
|
|
45
45
|
program?: ts.Program;
|
|
46
|
-
/**
|
|
47
|
-
*
|
|
46
|
+
/** 이 빌드에서 영향받은 파일 (정규화된 순방향 슬래시 경로).
|
|
47
|
+
* watch 모드에서 증분 lint에 사용한다. */
|
|
48
48
|
affectedFiles?: ReadonlySet<string>;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
|
-
*
|
|
52
|
+
* 패키지에 대해 TypeScript 증분 빌드를 실행한다.
|
|
53
53
|
*
|
|
54
|
-
* - output.js || output.dts: emit
|
|
55
|
-
* -
|
|
54
|
+
* - output.js || output.dts: emit 모드 (src 파일만, 출력 파일 생성)
|
|
55
|
+
* - 둘 다 아님: 타입체크만 (기본 src 파일만, includeTests=true이면 src + test 파일)
|
|
56
56
|
*
|
|
57
|
-
*
|
|
57
|
+
* 실행 간 증분 컴파일을 위해 tsBuildInfoFile을 사용한다.
|
|
58
58
|
*/
|
|
59
59
|
export function runTscPackageBuild(options: TscPackageBuildOptions): TscPackageBuildResult {
|
|
60
60
|
try {
|
|
@@ -144,9 +144,9 @@ export function runTscPackageBuild(options: TscPackageBuildOptions): TscPackageB
|
|
|
144
144
|
host,
|
|
145
145
|
);
|
|
146
146
|
|
|
147
|
-
//
|
|
148
|
-
// getSemanticDiagnosticsOfNextAffectedFile
|
|
149
|
-
// affected
|
|
147
|
+
// builder program의 증분 분석을 통해 affected 파일을 추적한다.
|
|
148
|
+
// getSemanticDiagnosticsOfNextAffectedFile은 마지막 빌드 이후 변경된 파일을 순회한다.
|
|
149
|
+
// affected는 ts.SourceFile 또는 ts.Program(전역 스코프 변경 시)일 수 있다.
|
|
150
150
|
let affectedFiles: Set<string> | undefined = new Set<string>();
|
|
151
151
|
|
|
152
152
|
while (true) {
|
|
@@ -155,7 +155,7 @@ export function runTscPackageBuild(options: TscPackageBuildOptions): TscPackageB
|
|
|
155
155
|
if ("fileName" in result.affected) {
|
|
156
156
|
affectedFiles?.add(pathx.posix(result.affected.fileName));
|
|
157
157
|
} else {
|
|
158
|
-
// ts.Program
|
|
158
|
+
// ts.Program 반환 — 전역 변경, 전체 재빌드로 처리
|
|
159
159
|
affectedFiles = undefined;
|
|
160
160
|
}
|
|
161
161
|
}
|
|
@@ -173,7 +173,7 @@ export function runTscPackageBuild(options: TscPackageBuildOptions): TscPackageB
|
|
|
173
173
|
...emitResult.diagnostics,
|
|
174
174
|
];
|
|
175
175
|
|
|
176
|
-
//
|
|
176
|
+
// 워크스페이스 범위: node_modules 제외, 모든 워크스페이스 진단 유지
|
|
177
177
|
const filteredDiagnostics = allDiagnostics.filter(
|
|
178
178
|
(d) => isWorkspaceDiagnostic(d, options.cwd),
|
|
179
179
|
);
|
package/src/utils/tsconfig.ts
CHANGED
|
@@ -13,7 +13,7 @@ export type TypecheckEnv = "node" | "browser";
|
|
|
13
13
|
const DOM_LIB_PATTERNS = ["dom", "webworker"] as const;
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
16
|
+
* package.json devDependencies에서 @types/* 패키지명을 추출한다.
|
|
17
17
|
*/
|
|
18
18
|
export function getTypesFromPackageJson(packageDir: string): string[] {
|
|
19
19
|
const packageJsonPath = path.join(packageDir, "package.json");
|
|
@@ -33,10 +33,10 @@ export function getTypesFromPackageJson(packageDir: string): string[] {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
|
-
*
|
|
36
|
+
* 지정된 타입체크 환경에 맞게 compilerOptions를 조정한다.
|
|
37
37
|
*
|
|
38
|
-
* - node
|
|
39
|
-
* - browser
|
|
38
|
+
* - node 환경: 브라우저 관련 lib(dom, webworker 패턴)을 제거한다. types는 변경 없음.
|
|
39
|
+
* - browser 환경: lib은 변경 없음. types를 devDeps에서 "node"를 제외하고 명시적으로 설정한다.
|
|
40
40
|
*/
|
|
41
41
|
export function getCompilerOptionsForEnv(
|
|
42
42
|
baseOptions: ts.CompilerOptions,
|
|
@@ -64,8 +64,10 @@ export function getCompilerOptionsForEnv(
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
67
|
+
* 패키지 target을 타입체크 환경으로 매핑한다.
|
|
68
|
+
* - server → ["node"], client → ["browser"]
|
|
69
|
+
* - node → ["node"], browser → ["browser"]
|
|
70
|
+
* - neutral/undefined → 이중 타입체크 (["node", "browser"]).
|
|
69
71
|
*/
|
|
70
72
|
export function toTypecheckEnvs(target: string | undefined): TypecheckEnv[] {
|
|
71
73
|
if (target === "node" || target === "server") return ["node"];
|
|
@@ -76,7 +78,7 @@ export function toTypecheckEnvs(target: string | undefined): TypecheckEnv[] {
|
|
|
76
78
|
//#endregion
|
|
77
79
|
|
|
78
80
|
/**
|
|
79
|
-
*
|
|
81
|
+
* 지정된 디렉토리에서 tsconfig.json을 파싱한다.
|
|
80
82
|
*/
|
|
81
83
|
export function parseTsconfig(dir: string): ts.ParsedCommandLine {
|
|
82
84
|
const tsconfigPath = path.join(dir, "tsconfig.json");
|
|
@@ -98,7 +100,7 @@ export function parseTsconfig(dir: string): ts.ParsedCommandLine {
|
|
|
98
100
|
}
|
|
99
101
|
|
|
100
102
|
/**
|
|
101
|
-
*
|
|
103
|
+
* 패키지에서 소스 파일(src/ 하위)을 파싱된 tsconfig 기준으로 필터링하여 반환한다.
|
|
102
104
|
*/
|
|
103
105
|
export function getPackageSourceFiles(
|
|
104
106
|
pkgDir: string,
|
|
@@ -111,7 +113,7 @@ export function getPackageSourceFiles(
|
|
|
111
113
|
}
|
|
112
114
|
|
|
113
115
|
/**
|
|
114
|
-
*
|
|
116
|
+
* 패키지의 모든 파일(src + tests)을 파싱된 tsconfig 기준으로 필터링하여 반환한다.
|
|
115
117
|
*/
|
|
116
118
|
export function getPackageFiles(
|
|
117
119
|
pkgDir: string,
|
|
@@ -15,13 +15,12 @@ export interface NonPackageTypecheckResult {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
19
|
-
* Extracted from dts.worker.ts non-package mode.
|
|
18
|
+
* 비패키지 파일(루트 레벨 설정 + 패키지 루트 설정)을 타입체크한다.
|
|
20
19
|
*
|
|
21
|
-
*
|
|
22
|
-
* -
|
|
23
|
-
* -
|
|
24
|
-
*
|
|
20
|
+
* 비패키지 파일 범위:
|
|
21
|
+
* - 루트 레벨 파일 (vitest.config.ts 등) — packages/ 외부
|
|
22
|
+
* - 패키지 루트 설정 파일 (packages/{pkg}/vitest.config.ts) — packages/ 하위 깊이 2
|
|
23
|
+
* 패키지 소스 파일(packages/{pkg}/src/...)은 제외한다.
|
|
25
24
|
*/
|
|
26
25
|
export function typecheckNonPackageFiles(cwd: string): NonPackageTypecheckResult {
|
|
27
26
|
logger.debug("비패키지 파일 타입체크 시작");
|
|
@@ -32,10 +31,10 @@ export function typecheckNonPackageFiles(cwd: string): NonPackageTypecheckResult
|
|
|
32
31
|
const normalized = pathx.posixResolve(fileName);
|
|
33
32
|
const normalizedPkgDir = pathx.posixResolve(packagesDir);
|
|
34
33
|
|
|
35
|
-
//
|
|
34
|
+
// packages/ 디렉토리 외부 파일
|
|
36
35
|
if (!normalized.startsWith(normalizedPkgDir + "/")) return true;
|
|
37
36
|
|
|
38
|
-
//
|
|
37
|
+
// 패키지 루트에 직접 위치한 파일 (예: packages/{pkg}/file.ts — 깊이 2)
|
|
39
38
|
const relative = pathx.posix(path.relative(normalizedPkgDir, normalized));
|
|
40
39
|
return relative.split("/").length === 2;
|
|
41
40
|
};
|
|
@@ -2,7 +2,7 @@ import ts from "typescript";
|
|
|
2
2
|
import { fsx } from "@simplysm/core-node";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Worker로 전달할 수 있는 직렬화된 Diagnostic
|
|
6
6
|
*/
|
|
7
7
|
export interface SerializedDiagnostic {
|
|
8
8
|
category: number;
|
|
@@ -16,11 +16,11 @@ export interface SerializedDiagnostic {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
20
|
-
* (
|
|
19
|
+
* Diagnostic을 직렬화 가능한 형태로 변환한다.
|
|
20
|
+
* (Worker 스레드 간 structured clone 통신을 위해 순환 참조/함수를 제거)
|
|
21
21
|
*/
|
|
22
22
|
export function serializeDiagnostic(diagnostic: ts.Diagnostic): SerializedDiagnostic {
|
|
23
|
-
//
|
|
23
|
+
// DiagnosticMessageChain인 경우 모든 컨텍스트 정보를 보존하기 위해 전체 체인을 평탄화
|
|
24
24
|
const messageText = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
|
|
25
25
|
|
|
26
26
|
return {
|
|
@@ -38,22 +38,20 @@ export function serializeDiagnostic(diagnostic: ts.Diagnostic): SerializedDiagno
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
|
-
*
|
|
41
|
+
* 파일명에서 TypeScript ScriptKind를 결정한다.
|
|
42
42
|
*/
|
|
43
43
|
function getScriptKind(fileName: string): ts.ScriptKind {
|
|
44
|
-
if (fileName.endsWith(".tsx")) return ts.ScriptKind.TSX;
|
|
45
|
-
if (fileName.endsWith(".jsx")) return ts.ScriptKind.JSX;
|
|
46
44
|
if (fileName.endsWith(".js") || fileName.endsWith(".mjs") || fileName.endsWith(".cjs"))
|
|
47
45
|
return ts.ScriptKind.JS;
|
|
48
46
|
return ts.ScriptKind.TS;
|
|
49
47
|
}
|
|
50
48
|
|
|
51
49
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* @param serialized -
|
|
55
|
-
* @param fileCache -
|
|
56
|
-
* @returns
|
|
50
|
+
* SerializedDiagnostic을 ts.Diagnostic으로 복원한다.
|
|
51
|
+
* formatDiagnosticsWithColorAndContext에서 소스 코드 컨텍스트가 표시되도록 실제 파일 내용을 읽는다.
|
|
52
|
+
* @param serialized - 직렬화된 진단 정보
|
|
53
|
+
* @param fileCache - 파일 내용 캐시 (같은 파일의 중복 읽기 방지)
|
|
54
|
+
* @returns 복원된 ts.Diagnostic 객체
|
|
57
55
|
*/
|
|
58
56
|
export function deserializeDiagnostic(
|
|
59
57
|
serialized: SerializedDiagnostic,
|
|
@@ -63,9 +61,9 @@ export function deserializeDiagnostic(
|
|
|
63
61
|
if (serialized.file != null) {
|
|
64
62
|
const fileName = serialized.file.fileName;
|
|
65
63
|
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
// (
|
|
64
|
+
// 캐시된 파일 내용 가져오기 (없으면 읽어서 캐시)
|
|
65
|
+
// 파일이 삭제되었거나 접근 불가능하면 빈 내용으로 처리
|
|
66
|
+
// (소스 코드 컨텍스트는 표시되지 않지만 진단 메시지는 정상 표시됨)
|
|
69
67
|
if (!fileCache.has(fileName)) {
|
|
70
68
|
fileCache.set(fileName, fsx.existsSync(fileName) ? fsx.readSync(fileName) : "");
|
|
71
69
|
}
|