@simplysm/sd-cli 14.0.7 → 14.0.9
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/dist/angular/client-transform-stylesheet.d.ts.map +1 -1
- package/dist/angular/client-transform-stylesheet.js.map +1 -1
- package/dist/angular/vite-angular-plugin.d.ts.map +1 -1
- package/dist/angular/vite-angular-plugin.js +15 -8
- package/dist/angular/vite-angular-plugin.js.map +1 -1
- package/dist/angular/vite-postcss-inline-plugin.d.ts.map +1 -1
- package/dist/angular/vite-postcss-inline-plugin.js.map +1 -1
- package/dist/capacitor/capacitor.d.ts +1 -1
- package/dist/capacitor/capacitor.d.ts.map +1 -1
- package/dist/capacitor/capacitor.js +43 -44
- package/dist/capacitor/capacitor.js.map +1 -1
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +2 -2
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/lint.d.ts.map +1 -1
- package/dist/commands/lint.js.map +1 -1
- package/dist/commands/publish.d.ts.map +1 -1
- package/dist/commands/publish.js +12 -13
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/replace-deps.d.ts.map +1 -1
- package/dist/commands/replace-deps.js.map +1 -1
- package/dist/commands/typecheck.d.ts.map +1 -1
- package/dist/commands/typecheck.js +12 -12
- package/dist/commands/typecheck.js.map +1 -1
- package/dist/commands/watch.d.ts.map +1 -1
- package/dist/commands/watch.js.map +1 -1
- package/dist/electron/electron.d.ts.map +1 -1
- package/dist/electron/electron.js +42 -37
- package/dist/electron/electron.js.map +1 -1
- package/dist/engines/BaseEngine.d.ts +1 -5
- package/dist/engines/BaseEngine.d.ts.map +1 -1
- package/dist/engines/BaseEngine.js +7 -16
- package/dist/engines/BaseEngine.js.map +1 -1
- package/dist/engines/NgtscEngine.d.ts.map +1 -1
- package/dist/engines/NgtscEngine.js +10 -11
- package/dist/engines/NgtscEngine.js.map +1 -1
- package/dist/engines/ServerEsbuildEngine.d.ts.map +1 -1
- package/dist/engines/ServerEsbuildEngine.js +10 -11
- package/dist/engines/ServerEsbuildEngine.js.map +1 -1
- package/dist/engines/TscEngine.d.ts.map +1 -1
- package/dist/engines/TscEngine.js +10 -11
- package/dist/engines/TscEngine.js.map +1 -1
- package/dist/engines/ViteEngine.d.ts.map +1 -1
- package/dist/engines/ViteEngine.js +3 -13
- package/dist/engines/ViteEngine.js.map +1 -1
- package/dist/engines/index.d.ts.map +1 -1
- package/dist/engines/index.js.map +1 -1
- package/dist/engines/types.d.ts +3 -6
- package/dist/engines/types.d.ts.map +1 -1
- package/dist/engines/types.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/infra/ResultCollector.d.ts +1 -1
- package/dist/infra/ResultCollector.d.ts.map +1 -1
- package/dist/infra/ResultCollector.js.map +1 -1
- package/dist/infra/SignalHandler.d.ts.map +1 -1
- package/dist/infra/SignalHandler.js.map +1 -1
- package/dist/infra/WorkerManager.d.ts.map +1 -1
- package/dist/infra/WorkerManager.js.map +1 -1
- package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/BuildOrchestrator.js +30 -61
- package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
- package/dist/orchestrators/DevWatchOrchestrator.d.ts +2 -0
- package/dist/orchestrators/DevWatchOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/DevWatchOrchestrator.js +40 -44
- package/dist/orchestrators/DevWatchOrchestrator.js.map +1 -1
- package/dist/sd-cli-entry.d.ts.map +1 -1
- package/dist/sd-cli-entry.js +2 -13
- package/dist/sd-cli-entry.js.map +1 -1
- package/dist/sd-cli.d.ts.map +1 -1
- package/dist/sd-cli.js +5 -5
- package/dist/sd-cli.js.map +1 -1
- package/dist/sd-config.types.d.ts.map +1 -1
- package/dist/sd-config.types.js.map +1 -1
- package/dist/utils/SdCliReporter.d.ts +18 -0
- package/dist/utils/SdCliReporter.d.ts.map +1 -0
- package/dist/utils/SdCliReporter.js +144 -0
- package/dist/utils/SdCliReporter.js.map +1 -0
- package/dist/utils/angular-build.d.ts.map +1 -1
- package/dist/utils/angular-build.js.map +1 -1
- package/dist/utils/angular-compiler.d.ts.map +1 -1
- package/dist/utils/angular-compiler.js +11 -4
- package/dist/utils/angular-compiler.js.map +1 -1
- package/dist/utils/build-env.d.ts.map +1 -1
- package/dist/utils/build-env.js +2 -1
- package/dist/utils/build-env.js.map +1 -1
- package/dist/utils/concurrency.d.ts.map +1 -1
- package/dist/utils/concurrency.js.map +1 -1
- package/dist/utils/copy-public.d.ts.map +1 -1
- package/dist/utils/copy-public.js +21 -21
- package/dist/utils/copy-public.js.map +1 -1
- package/dist/utils/copy-src.d.ts.map +1 -1
- package/dist/utils/copy-src.js +12 -12
- package/dist/utils/copy-src.js.map +1 -1
- package/dist/utils/diagnostic-utils.d.ts.map +1 -1
- package/dist/utils/diagnostic-utils.js +3 -2
- package/dist/utils/diagnostic-utils.js.map +1 -1
- package/dist/utils/engine-stop.d.ts.map +1 -1
- package/dist/utils/engine-stop.js.map +1 -1
- package/dist/utils/esbuild-config.d.ts.map +1 -1
- package/dist/utils/esbuild-config.js +2 -0
- package/dist/utils/esbuild-config.js.map +1 -1
- package/dist/utils/generate-pwa-icons.d.ts.map +1 -1
- package/dist/utils/generate-pwa-icons.js.map +1 -1
- package/dist/utils/hmr-candidates.d.ts.map +1 -1
- package/dist/utils/hmr-candidates.js.map +1 -1
- package/dist/utils/lint-utils.d.ts.map +1 -1
- package/dist/utils/lint-utils.js.map +1 -1
- package/dist/utils/lint-with-program.d.ts.map +1 -1
- package/dist/utils/lint-with-program.js +7 -3
- package/dist/utils/lint-with-program.js.map +1 -1
- package/dist/utils/ngtsc-build-core.d.ts +2 -10
- package/dist/utils/ngtsc-build-core.d.ts.map +1 -1
- package/dist/utils/ngtsc-build-core.js +16 -15
- package/dist/utils/ngtsc-build-core.js.map +1 -1
- package/dist/utils/orchestrator-utils.d.ts.map +1 -1
- package/dist/utils/orchestrator-utils.js.map +1 -1
- package/dist/utils/output-path-rewriter.d.ts.map +1 -1
- package/dist/utils/output-path-rewriter.js +7 -7
- package/dist/utils/output-path-rewriter.js.map +1 -1
- package/dist/utils/output-utils.d.ts.map +1 -1
- package/dist/utils/output-utils.js +1 -1
- package/dist/utils/output-utils.js.map +1 -1
- package/dist/utils/package-utils.d.ts +4 -0
- package/dist/utils/package-utils.d.ts.map +1 -1
- package/dist/utils/package-utils.js +34 -13
- package/dist/utils/package-utils.js.map +1 -1
- package/dist/utils/rebuild-manager.d.ts +1 -1
- package/dist/utils/rebuild-manager.d.ts.map +1 -1
- package/dist/utils/rebuild-manager.js +3 -1
- package/dist/utils/rebuild-manager.js.map +1 -1
- package/dist/utils/replace-deps.d.ts.map +1 -1
- package/dist/utils/replace-deps.js +10 -10
- package/dist/utils/replace-deps.js.map +1 -1
- package/dist/utils/scss-compiler.d.ts.map +1 -1
- package/dist/utils/scss-compiler.js.map +1 -1
- package/dist/utils/sd-config.d.ts.map +1 -1
- package/dist/utils/sd-config.js +2 -3
- package/dist/utils/sd-config.js.map +1 -1
- package/dist/utils/tsc-build.d.ts +3 -1
- package/dist/utils/tsc-build.d.ts.map +1 -1
- package/dist/utils/tsc-build.js +7 -4
- package/dist/utils/tsc-build.js.map +1 -1
- package/dist/utils/tsconfig.d.ts.map +1 -1
- package/dist/utils/tsconfig.js.map +1 -1
- package/dist/utils/typecheck-non-package.d.ts.map +1 -1
- package/dist/utils/typecheck-non-package.js +10 -5
- package/dist/utils/typecheck-non-package.js.map +1 -1
- package/dist/utils/typecheck-serialization.d.ts.map +1 -1
- package/dist/utils/typecheck-serialization.js.map +1 -1
- package/dist/utils/vite-config.d.ts.map +1 -1
- package/dist/utils/vite-config.js +2 -1
- 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.map +1 -1
- package/dist/utils/worker-events.d.ts +1 -1
- package/dist/utils/worker-events.d.ts.map +1 -1
- package/dist/utils/worker-events.js +1 -0
- package/dist/utils/worker-events.js.map +1 -1
- package/dist/utils/worker-utils.d.ts +1 -1
- package/dist/utils/worker-utils.d.ts.map +1 -1
- package/dist/utils/worker-utils.js +3 -1
- package/dist/utils/worker-utils.js.map +1 -1
- package/dist/vitest-plugin.d.ts.map +1 -1
- package/dist/vitest-plugin.js +2 -0
- package/dist/vitest-plugin.js.map +1 -1
- package/dist/workers/client.worker.d.ts.map +1 -1
- package/dist/workers/client.worker.js +4 -0
- package/dist/workers/client.worker.js.map +1 -1
- package/dist/workers/library-build.worker.d.ts +2 -10
- package/dist/workers/library-build.worker.d.ts.map +1 -1
- package/dist/workers/library-build.worker.js +38 -14
- package/dist/workers/library-build.worker.js.map +1 -1
- package/dist/workers/lint.worker.d.ts.map +1 -1
- package/dist/workers/lint.worker.js.map +1 -1
- package/dist/workers/ngtsc-build.worker.d.ts.map +1 -1
- package/dist/workers/ngtsc-build.worker.js +40 -14
- package/dist/workers/ngtsc-build.worker.js.map +1 -1
- package/dist/workers/server-build.worker.d.ts +2 -10
- package/dist/workers/server-build.worker.d.ts.map +1 -1
- package/dist/workers/server-build.worker.js +30 -22
- package/dist/workers/server-build.worker.js.map +1 -1
- package/dist/workers/server-runtime.worker.d.ts.map +1 -1
- package/dist/workers/server-runtime.worker.js.map +1 -1
- package/package.json +4 -5
- package/src/angular/vite-angular-plugin.ts +18 -9
- package/src/capacitor/capacitor.ts +43 -44
- package/src/commands/check.ts +2 -2
- package/src/commands/publish.ts +12 -13
- package/src/commands/typecheck.ts +12 -12
- package/src/electron/electron.ts +44 -38
- package/src/engines/BaseEngine.ts +8 -19
- package/src/engines/NgtscEngine.ts +11 -11
- package/src/engines/ServerEsbuildEngine.ts +11 -11
- package/src/engines/TscEngine.ts +11 -11
- package/src/engines/ViteEngine.ts +3 -14
- package/src/engines/types.ts +3 -6
- package/src/infra/ResultCollector.ts +1 -1
- package/src/orchestrators/BuildOrchestrator.ts +31 -62
- package/src/orchestrators/DevWatchOrchestrator.ts +41 -44
- package/src/sd-cli-entry.ts +2 -12
- package/src/sd-cli.ts +8 -5
- package/src/utils/SdCliReporter.ts +177 -0
- package/src/utils/angular-compiler.ts +11 -4
- package/src/utils/build-env.ts +2 -1
- package/src/utils/copy-public.ts +21 -21
- package/src/utils/copy-src.ts +12 -12
- package/src/utils/diagnostic-utils.ts +3 -2
- package/src/utils/esbuild-config.ts +2 -0
- package/src/utils/lint-with-program.ts +7 -3
- package/src/utils/ngtsc-build-core.ts +18 -18
- package/src/utils/output-path-rewriter.ts +7 -7
- package/src/utils/output-utils.ts +1 -1
- package/src/utils/package-utils.ts +37 -13
- package/src/utils/rebuild-manager.ts +4 -2
- package/src/utils/replace-deps.ts +10 -10
- package/src/utils/sd-config.ts +2 -3
- package/src/utils/tsc-build.ts +9 -4
- package/src/utils/typecheck-non-package.ts +10 -5
- package/src/utils/vite-config.ts +2 -1
- package/src/utils/worker-events.ts +2 -1
- package/src/utils/worker-utils.ts +3 -1
- package/src/vitest-plugin.ts +5 -0
- package/src/workers/client.worker.ts +4 -0
- package/src/workers/library-build.worker.ts +48 -18
- package/src/workers/ngtsc-build.worker.ts +48 -13
- package/src/workers/server-build.worker.ts +32 -26
- package/tests/angular/vite-angular-plugin-hmr-fallback.spec.ts +11 -7
- package/tests/angular/vite-angular-plugin-lint.spec.ts +6 -1
- package/tests/capacitor/capacitor-build.spec.ts +14 -7
- package/tests/capacitor/capacitor-icon.spec.ts +14 -7
- package/tests/capacitor/capacitor-init.spec.ts +13 -6
- package/tests/capacitor/capacitor-run.spec.ts +18 -11
- package/tests/capacitor/capacitor-workspace.spec.ts +13 -6
- package/tests/commands/check.spec.ts +5 -2
- package/tests/commands/publish.spec.ts +4 -4
- package/tests/commands/typecheck.spec.ts +20 -31
- package/tests/electron/electron.spec.ts +32 -23
- package/tests/engines/base-engine.spec.ts +15 -21
- package/tests/engines/engine-lint-integration.spec.ts +5 -10
- package/tests/engines/ngtsc-engine.spec.ts +27 -41
- package/tests/engines/server-esbuild-engine.spec.ts +18 -29
- package/tests/engines/tsc-engine.spec.ts +14 -23
- package/tests/engines/vite-engine.spec.ts +10 -15
- package/tests/infra/result-collector.spec.ts +2 -2
- package/tests/orchestrators/build-orchestrator.spec.ts +19 -29
- package/tests/orchestrators/dev-watch-orchestrator.spec.ts +110 -95
- package/tests/utils/copy-src.spec.ts +25 -19
- package/tests/utils/diagnostic-utils.spec.ts +72 -0
- package/tests/utils/ngtsc-build-core-angular-compiler.spec.ts +2 -3
- package/tests/utils/output-path-rewriter.spec.ts +7 -6
- package/tests/utils/output-utils.spec.ts +5 -5
- package/tests/utils/rebuild-manager.spec.ts +1 -1
- package/tests/utils/sd-config.spec.ts +4 -0
- package/tests/utils/tsc-build.spec.ts +23 -5
- package/tests/workers/library-build-worker.spec.ts +113 -20
- package/tests/workers/ngtsc-build-lint.spec.ts +3 -6
- package/tests/workers/ngtsc-build-worker.spec.ts +11 -13
- package/tests/workers/server-build-lint.spec.ts +4 -1
- package/tests/workers/server-build-worker.spec.ts +25 -25
- package/tests/angular/migration-cleanup.spec.ts +0 -59
|
@@ -2,6 +2,7 @@ import path from "path";
|
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import { consola } from "consola";
|
|
4
4
|
import { SdError } from "@simplysm/core-common";
|
|
5
|
+
import { pathx } from "@simplysm/core-node";
|
|
5
6
|
import type {
|
|
6
7
|
BuildTarget,
|
|
7
8
|
SdBuildPackageConfig,
|
|
@@ -36,8 +37,8 @@ export function iteratePackages(
|
|
|
36
37
|
*/
|
|
37
38
|
export function findPackageRoot(startDir: string): string {
|
|
38
39
|
let dir = startDir;
|
|
39
|
-
while (!fs.existsSync(path.join(dir, "package.json"))) {
|
|
40
|
-
const parent = path.dirname(dir);
|
|
40
|
+
while (!fs.existsSync(pathx.posix(path.join(dir, "package.json")))) {
|
|
41
|
+
const parent = pathx.posix(path.dirname(dir));
|
|
41
42
|
if (parent === dir) throw new Error("package.json not found");
|
|
42
43
|
dir = parent;
|
|
43
44
|
}
|
|
@@ -49,13 +50,14 @@ export function findPackageRoot(startDir: string): string {
|
|
|
49
50
|
* Returns a map of directory name → relative path (e.g., "orm" → "tests/orm").
|
|
50
51
|
*/
|
|
51
52
|
export function discoverWorkspacePackages(cwd: string): Map<string, string> {
|
|
53
|
+
logger.debug("워크스페이스 패키지 탐색 시작");
|
|
52
54
|
const map = new Map<string, string>();
|
|
53
55
|
for (const dir of ["packages", "tests"]) {
|
|
54
|
-
const baseDir = path.join(cwd, dir);
|
|
56
|
+
const baseDir = pathx.posix(path.join(cwd, dir));
|
|
55
57
|
if (!fs.existsSync(baseDir)) continue;
|
|
56
58
|
for (const entry of fs.readdirSync(baseDir, { withFileTypes: true })) {
|
|
57
59
|
if (!entry.isDirectory()) continue;
|
|
58
|
-
if (!fs.existsSync(path.join(baseDir, entry.name, "package.json"))) continue;
|
|
60
|
+
if (!fs.existsSync(pathx.posix(path.join(baseDir, entry.name, "package.json")))) continue;
|
|
59
61
|
if (map.has(entry.name)) {
|
|
60
62
|
throw new SdError(
|
|
61
63
|
`Duplicate workspace package name: ${entry.name} (${map.get(entry.name)} and ${dir}/${entry.name})`,
|
|
@@ -64,6 +66,7 @@ export function discoverWorkspacePackages(cwd: string): Map<string, string> {
|
|
|
64
66
|
map.set(entry.name, `${dir}/${entry.name}`);
|
|
65
67
|
}
|
|
66
68
|
}
|
|
69
|
+
logger.debug(`워크스페이스 패키지 탐색 완료 (${map.size}개)`);
|
|
67
70
|
return map;
|
|
68
71
|
}
|
|
69
72
|
|
|
@@ -73,10 +76,24 @@ export function discoverWorkspacePackages(cwd: string): Map<string, string> {
|
|
|
73
76
|
* Also builds a pathMap (name → relative path) for all packages.
|
|
74
77
|
* Throws SdError if a tests package name collides with an sd.config.ts package name.
|
|
75
78
|
*/
|
|
79
|
+
/**
|
|
80
|
+
* Build pathMap from sd.config.ts packages only (without tests packages).
|
|
81
|
+
*/
|
|
82
|
+
export function buildPathMapFromConfig(
|
|
83
|
+
configPackages: Record<string, SdPackageConfig | undefined>,
|
|
84
|
+
): Map<string, string> {
|
|
85
|
+
const pathMap = new Map<string, string>();
|
|
86
|
+
for (const name of Object.keys(configPackages)) {
|
|
87
|
+
pathMap.set(name, `packages/${name}`);
|
|
88
|
+
}
|
|
89
|
+
return pathMap;
|
|
90
|
+
}
|
|
91
|
+
|
|
76
92
|
export function mergeTestsPackagesIntoConfig(
|
|
77
93
|
configPackages: Record<string, SdPackageConfig | undefined>,
|
|
78
94
|
workspacePackages: Map<string, string>,
|
|
79
95
|
): { merged: Record<string, SdPackageConfig | undefined>; pathMap: Map<string, string> } {
|
|
96
|
+
logger.debug("tests 패키지 병합 시작");
|
|
80
97
|
const pathMap = new Map<string, string>();
|
|
81
98
|
const merged: Record<string, SdPackageConfig | undefined> = { ...configPackages };
|
|
82
99
|
|
|
@@ -99,6 +116,7 @@ export function mergeTestsPackagesIntoConfig(
|
|
|
99
116
|
pathMap.set(name, relPath);
|
|
100
117
|
}
|
|
101
118
|
|
|
119
|
+
logger.debug(`tests 패키지 병합 완료 (총 ${Object.keys(merged).length}개)`);
|
|
102
120
|
return { merged, pathMap };
|
|
103
121
|
}
|
|
104
122
|
|
|
@@ -114,7 +132,7 @@ export function collectDeps(
|
|
|
114
132
|
): DepsResult {
|
|
115
133
|
const startTime = performance.now();
|
|
116
134
|
logger.debug("의존성 수집 시작");
|
|
117
|
-
const rootPkgJsonPath = path.join(cwd, "package.json");
|
|
135
|
+
const rootPkgJsonPath = pathx.posix(path.join(cwd, "package.json"));
|
|
118
136
|
const rootPkgJson = JSON.parse(fs.readFileSync(rootPkgJsonPath, "utf-8")) as { name: string };
|
|
119
137
|
const scopeMatch = rootPkgJson.name.match(/^(@[^/]+)\//);
|
|
120
138
|
const workspaceScope = scopeMatch != null ? scopeMatch[1] : undefined;
|
|
@@ -132,7 +150,7 @@ export function collectDeps(
|
|
|
132
150
|
const visited = new Set<string>();
|
|
133
151
|
|
|
134
152
|
function traverse(dir: string): void {
|
|
135
|
-
const pkgJsonPath = path.join(dir, "package.json");
|
|
153
|
+
const pkgJsonPath = pathx.posix(path.join(dir, "package.json"));
|
|
136
154
|
if (!fs.existsSync(pkgJsonPath)) return;
|
|
137
155
|
|
|
138
156
|
const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8")) as {
|
|
@@ -147,8 +165,8 @@ export function collectDeps(
|
|
|
147
165
|
// Check for workspace package
|
|
148
166
|
if (workspaceScope != null && dep.startsWith(workspaceScope + "/")) {
|
|
149
167
|
const dirName = dep.slice(workspaceScope.length + 1);
|
|
150
|
-
const depDir = path.join(cwd, "packages", dirName);
|
|
151
|
-
if (fs.existsSync(path.join(depDir, "package.json"))) {
|
|
168
|
+
const depDir = pathx.posix(path.join(cwd, "packages", dirName));
|
|
169
|
+
if (fs.existsSync(pathx.posix(path.join(depDir, "package.json")))) {
|
|
152
170
|
workspaceDeps.push(dirName);
|
|
153
171
|
traverse(depDir);
|
|
154
172
|
continue;
|
|
@@ -159,8 +177,8 @@ export function collectDeps(
|
|
|
159
177
|
const matched = replaceDepsPatterns.find((p) => p.regex.test(dep));
|
|
160
178
|
if (matched != null) {
|
|
161
179
|
replaceDeps.push(dep);
|
|
162
|
-
const depNodeModulesDir = path.join(cwd, "node_modules", ...dep.split("/"));
|
|
163
|
-
if (fs.existsSync(path.join(depNodeModulesDir, "package.json"))) {
|
|
180
|
+
const depNodeModulesDir = pathx.posix(path.join(cwd, "node_modules", ...dep.split("/")));
|
|
181
|
+
if (fs.existsSync(pathx.posix(path.join(depNodeModulesDir, "package.json")))) {
|
|
164
182
|
traverse(depNodeModulesDir);
|
|
165
183
|
}
|
|
166
184
|
continue;
|
|
@@ -180,7 +198,7 @@ export function collectDeps(
|
|
|
180
198
|
* in dependencies or peerDependencies.
|
|
181
199
|
*/
|
|
182
200
|
export function hasAngularCoreDependency(pkgDir: string): boolean {
|
|
183
|
-
const pkgJsonPath = path.join(pkgDir, "package.json");
|
|
201
|
+
const pkgJsonPath = pathx.posix(path.join(pkgDir, "package.json"));
|
|
184
202
|
if (!fs.existsSync(pkgJsonPath)) return false;
|
|
185
203
|
try {
|
|
186
204
|
const content = fs.readFileSync(pkgJsonPath, "utf-8");
|
|
@@ -226,6 +244,7 @@ export function filterPackagesByTargets(
|
|
|
226
244
|
packages: Record<string, SdPackageConfig | undefined>,
|
|
227
245
|
targets: string[],
|
|
228
246
|
): Record<string, SdPackageConfig> {
|
|
247
|
+
logger.debug(`패키지 필터링 시작 (targets: ${targets.length > 0 ? targets.join(", ") : "전체"})`);
|
|
229
248
|
const result: Record<string, SdPackageConfig> = {};
|
|
230
249
|
|
|
231
250
|
for (const [name, config] of Object.entries(packages)) {
|
|
@@ -246,6 +265,7 @@ export function filterPackagesByTargets(
|
|
|
246
265
|
}
|
|
247
266
|
}
|
|
248
267
|
|
|
268
|
+
logger.debug(`패키지 필터링 완료 (${Object.keys(result).length}개)`);
|
|
249
269
|
return result;
|
|
250
270
|
}
|
|
251
271
|
|
|
@@ -268,12 +288,13 @@ export function classifyWatchPackages(
|
|
|
268
288
|
cwd: string,
|
|
269
289
|
pathMap: Map<string, string>,
|
|
270
290
|
): WatchClassifiedPackages {
|
|
291
|
+
logger.debug("watch 패키지 분류 시작");
|
|
271
292
|
const libraryPackages: WatchClassifiedPackages["libraryPackages"] = [];
|
|
272
293
|
const watchHookPackages: WatchClassifiedPackages["watchHookPackages"] = [];
|
|
273
294
|
|
|
274
295
|
for (const { name, config } of iteratePackages(allPackages, [])) {
|
|
275
296
|
const relPath = pathMap.get(name) ?? `packages/${name}`;
|
|
276
|
-
const pkgDir = path.join(cwd, relPath);
|
|
297
|
+
const pkgDir = pathx.posix(path.join(cwd, relPath));
|
|
277
298
|
if (isLibraryTarget(config.target)) {
|
|
278
299
|
const buildConfig = config as SdBuildPackageConfig;
|
|
279
300
|
libraryPackages.push({ name, dir: pkgDir, config: buildConfig });
|
|
@@ -289,6 +310,7 @@ export function classifyWatchPackages(
|
|
|
289
310
|
}
|
|
290
311
|
}
|
|
291
312
|
|
|
313
|
+
logger.debug(`watch 패키지 분류 완료 (library: ${libraryPackages.length}, watchHook: ${watchHookPackages.length})`);
|
|
292
314
|
return { libraryPackages, watchHookPackages };
|
|
293
315
|
}
|
|
294
316
|
|
|
@@ -307,6 +329,7 @@ export function classifyDevPackages(
|
|
|
307
329
|
cwd: string,
|
|
308
330
|
pathMap: Map<string, string>,
|
|
309
331
|
): DevClassifiedPackages {
|
|
332
|
+
logger.debug("dev 패키지 분류 시작");
|
|
310
333
|
const serverPackages: DevClassifiedPackages["serverPackages"] = [];
|
|
311
334
|
const clientPackages: DevClassifiedPackages["clientPackages"] = [];
|
|
312
335
|
const serverClientsMap = new Map<string, string[]>();
|
|
@@ -324,7 +347,7 @@ export function classifyDevPackages(
|
|
|
324
347
|
// Second pass: classify all packages
|
|
325
348
|
for (const { name, config } of entries) {
|
|
326
349
|
const relPath = pathMap.get(name) ?? `packages/${name}`;
|
|
327
|
-
const pkgDir = path.join(cwd, relPath);
|
|
350
|
+
const pkgDir = pathx.posix(path.join(cwd, relPath));
|
|
328
351
|
if (config.target === "server") {
|
|
329
352
|
serverPackages.push({
|
|
330
353
|
name,
|
|
@@ -355,6 +378,7 @@ export function classifyDevPackages(
|
|
|
355
378
|
// Library and scripts packages are excluded from dev mode
|
|
356
379
|
}
|
|
357
380
|
|
|
381
|
+
logger.debug(`dev 패키지 분류 완료 (server: ${serverPackages.length}, client: ${clientPackages.length})`);
|
|
358
382
|
return { serverPackages, clientPackages, serverClientsMap };
|
|
359
383
|
}
|
|
360
384
|
|
|
@@ -2,7 +2,7 @@ import { EventEmitter } from "node:events";
|
|
|
2
2
|
import { consola } from "consola";
|
|
3
3
|
|
|
4
4
|
interface RebuildManagerEvents {
|
|
5
|
-
batchComplete: [];
|
|
5
|
+
batchComplete: [completedKeys: string[]];
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export class RebuildManager extends EventEmitter<RebuildManagerEvents> {
|
|
@@ -19,6 +19,7 @@ export class RebuildManager extends EventEmitter<RebuildManagerEvents> {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
registerBuild(key: string, title: string): () => void {
|
|
22
|
+
this._logger.debug(`빌드 등록: ${key} (${title})`);
|
|
22
23
|
let resolver!: () => void;
|
|
23
24
|
const promise = new Promise<void>((resolve) => {
|
|
24
25
|
resolver = resolve;
|
|
@@ -35,6 +36,7 @@ export class RebuildManager extends EventEmitter<RebuildManagerEvents> {
|
|
|
35
36
|
|
|
36
37
|
private async _runBatch(): Promise<void> {
|
|
37
38
|
if (this._isRunning || this._pendingBuilds.size === 0) {
|
|
39
|
+
this._logger.debug(`배치 건너뜀 (running: ${String(this._isRunning)}, pending: ${this._pendingBuilds.size})`);
|
|
38
40
|
return;
|
|
39
41
|
}
|
|
40
42
|
|
|
@@ -60,7 +62,7 @@ export class RebuildManager extends EventEmitter<RebuildManagerEvents> {
|
|
|
60
62
|
|
|
61
63
|
this._logger.success(`리빌드 실행 완료 (${titles})`);
|
|
62
64
|
|
|
63
|
-
this.emit("batchComplete");
|
|
65
|
+
this.emit("batchComplete", Array.from(batchBuilds.keys()));
|
|
64
66
|
|
|
65
67
|
this._isRunning = false;
|
|
66
68
|
|
|
@@ -133,7 +133,7 @@ export interface WatchReplaceDepResult {
|
|
|
133
133
|
async function collectSearchRoots(projectRoot: string): Promise<string[]> {
|
|
134
134
|
const searchRoots = [projectRoot];
|
|
135
135
|
|
|
136
|
-
const workspaceYamlPath = path.join(projectRoot, "pnpm-workspace.yaml");
|
|
136
|
+
const workspaceYamlPath = pathx.posix(path.join(projectRoot, "pnpm-workspace.yaml"));
|
|
137
137
|
try {
|
|
138
138
|
const yamlContent = await fs.promises.readFile(workspaceYamlPath, "utf-8");
|
|
139
139
|
const workspaceGlobs = parseWorkspaceGlobs(yamlContent);
|
|
@@ -171,7 +171,7 @@ async function resolveAllReplaceDepEntries(
|
|
|
171
171
|
const searchRoots = await collectSearchRoots(projectRoot);
|
|
172
172
|
|
|
173
173
|
for (const searchRoot of searchRoots) {
|
|
174
|
-
const nodeModulesDir = path.join(searchRoot, "node_modules");
|
|
174
|
+
const nodeModulesDir = pathx.posix(path.join(searchRoot, "node_modules"));
|
|
175
175
|
|
|
176
176
|
try {
|
|
177
177
|
await fs.promises.access(nodeModulesDir);
|
|
@@ -192,8 +192,8 @@ async function resolveAllReplaceDepEntries(
|
|
|
192
192
|
const matchedEntries = resolveReplaceDepEntries(replaceDeps, targetNames);
|
|
193
193
|
|
|
194
194
|
for (const { targetName, sourcePath } of matchedEntries) {
|
|
195
|
-
const targetPath = path.join(nodeModulesDir, targetName);
|
|
196
|
-
const resolvedSourcePath =
|
|
195
|
+
const targetPath = pathx.posix(path.join(nodeModulesDir, targetName));
|
|
196
|
+
const resolvedSourcePath = pathx.posixResolve(projectRoot, sourcePath);
|
|
197
197
|
|
|
198
198
|
// Verify source path exists
|
|
199
199
|
try {
|
|
@@ -208,7 +208,7 @@ async function resolveAllReplaceDepEntries(
|
|
|
208
208
|
try {
|
|
209
209
|
const stat = await fs.promises.lstat(targetPath);
|
|
210
210
|
if (stat.isSymbolicLink()) {
|
|
211
|
-
actualTargetPath = await fs.promises.realpath(targetPath);
|
|
211
|
+
actualTargetPath = pathx.posix(await fs.promises.realpath(targetPath));
|
|
212
212
|
}
|
|
213
213
|
} catch {
|
|
214
214
|
// If targetPath doesn't exist, use as-is
|
|
@@ -263,7 +263,7 @@ export async function setupReplaceDeps(
|
|
|
263
263
|
|
|
264
264
|
// Run postinstall scripts from replaced packages
|
|
265
265
|
for (const { targetName, resolvedSourcePath, actualTargetPath } of entries) {
|
|
266
|
-
const sourcePkgJsonPath = path.join(resolvedSourcePath, "package.json");
|
|
266
|
+
const sourcePkgJsonPath = pathx.posix(path.join(resolvedSourcePath, "package.json"));
|
|
267
267
|
try {
|
|
268
268
|
const pkgJson = JSON.parse(await fs.promises.readFile(sourcePkgJsonPath, "utf-8"));
|
|
269
269
|
const postinstall = pkgJson.scripts?.postinstall as string | undefined;
|
|
@@ -312,7 +312,7 @@ export async function watchReplaceDeps(
|
|
|
312
312
|
watchedSources.add(entry.resolvedSourcePath);
|
|
313
313
|
|
|
314
314
|
const excludedPaths = [...EXCLUDED_NAMES].map((name) =>
|
|
315
|
-
path.join(entry.resolvedSourcePath, name),
|
|
315
|
+
pathx.posix(path.join(entry.resolvedSourcePath, name)),
|
|
316
316
|
);
|
|
317
317
|
|
|
318
318
|
const watcher = await FsWatcher.watch([entry.resolvedSourcePath], { followSymlinks: false });
|
|
@@ -331,8 +331,8 @@ export async function watchReplaceDeps(
|
|
|
331
331
|
if (e.resolvedSourcePath !== entry.resolvedSourcePath) continue;
|
|
332
332
|
|
|
333
333
|
// Calculate relative path from source
|
|
334
|
-
const relativePath = path.relative(e.resolvedSourcePath, changedPath);
|
|
335
|
-
const destPath = path.join(e.actualTargetPath, relativePath);
|
|
334
|
+
const relativePath = pathx.posix(path.relative(e.resolvedSourcePath, changedPath));
|
|
335
|
+
const destPath = pathx.posix(path.join(e.actualTargetPath, relativePath));
|
|
336
336
|
|
|
337
337
|
try {
|
|
338
338
|
// Check if source exists
|
|
@@ -350,7 +350,7 @@ export async function watchReplaceDeps(
|
|
|
350
350
|
if (stat.isDirectory()) {
|
|
351
351
|
await fsx.mkdir(destPath);
|
|
352
352
|
} else {
|
|
353
|
-
await fsx.mkdir(path.dirname(destPath));
|
|
353
|
+
await fsx.mkdir(pathx.posix(path.dirname(destPath)));
|
|
354
354
|
await fsx.copy(changedPath, destPath, replaceDepsCopyFilter);
|
|
355
355
|
}
|
|
356
356
|
} else {
|
package/src/utils/sd-config.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import path from "path";
|
|
2
1
|
import { createJiti } from "jiti";
|
|
3
2
|
import { SdError } from "@simplysm/core-common";
|
|
4
|
-
import { fsx } from "@simplysm/core-node";
|
|
3
|
+
import { fsx, pathx } from "@simplysm/core-node";
|
|
5
4
|
import { consola } from "consola";
|
|
6
5
|
import type { SdConfig, SdConfigParams } from "../sd-config.types";
|
|
7
6
|
|
|
@@ -13,7 +12,7 @@ const logger = consola.withTag("sd:cli:sd-config");
|
|
|
13
12
|
* @throws if sd.config.ts is missing or format is incorrect
|
|
14
13
|
*/
|
|
15
14
|
export async function loadSdConfig(params: SdConfigParams): Promise<SdConfig> {
|
|
16
|
-
const sdConfigPath =
|
|
15
|
+
const sdConfigPath = pathx.posixResolve(params.cwd, "sd.config.ts");
|
|
17
16
|
logger.debug(`sd.config.ts 로드 중: ${sdConfigPath}`);
|
|
18
17
|
|
|
19
18
|
if (!(await fsx.exists(sdConfigPath))) {
|
package/src/utils/tsc-build.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { err as errNs } from "@simplysm/core-common";
|
|
|
4
4
|
import { consola } from "consola";
|
|
5
5
|
|
|
6
6
|
const logger = consola.withTag("sd:cli:tsc-build");
|
|
7
|
+
import { pathx } from "@simplysm/core-node";
|
|
7
8
|
import {
|
|
8
9
|
parseTsconfig,
|
|
9
10
|
getPackageSourceFiles,
|
|
@@ -27,6 +28,8 @@ export interface TscPackageBuildOptions {
|
|
|
27
28
|
parsedConfig?: ts.ParsedCommandLine;
|
|
28
29
|
/** Typecheck environment. When set, adjusts compilerOptions via getCompilerOptionsForEnv(). */
|
|
29
30
|
env?: TypecheckEnv;
|
|
31
|
+
/** Include tests/ files in typecheck-only mode. Defaults to false. */
|
|
32
|
+
includeTests?: boolean;
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
/**
|
|
@@ -49,7 +52,7 @@ export interface TscPackageBuildResult {
|
|
|
49
52
|
* Run TypeScript incremental build for a package.
|
|
50
53
|
*
|
|
51
54
|
* - output.js || output.dts: emit mode (src files only, generates output files)
|
|
52
|
-
* - neither: typecheck only (src + test files
|
|
55
|
+
* - neither: typecheck only (src files only by default, src + test files when includeTests=true)
|
|
53
56
|
*
|
|
54
57
|
* Uses tsBuildInfoFile for incremental compilation across runs.
|
|
55
58
|
*/
|
|
@@ -68,7 +71,7 @@ export function runTscPackageBuild(options: TscPackageBuildOptions): TscPackageB
|
|
|
68
71
|
|
|
69
72
|
let rootFiles: string[];
|
|
70
73
|
|
|
71
|
-
if (needsEmit) {
|
|
74
|
+
if (needsEmit || !options.includeTests) {
|
|
72
75
|
rootFiles = getPackageSourceFiles(pkgDir, parsedConfig);
|
|
73
76
|
} else {
|
|
74
77
|
rootFiles = getPackageFiles(pkgDir, parsedConfig);
|
|
@@ -79,7 +82,9 @@ export function runTscPackageBuild(options: TscPackageBuildOptions): TscPackageB
|
|
|
79
82
|
const tsBuildInfoFile = path.join(
|
|
80
83
|
pkgDir,
|
|
81
84
|
".cache",
|
|
82
|
-
needsEmit
|
|
85
|
+
needsEmit
|
|
86
|
+
? `build${output.dts ? "" : "-no-dts"}${envSuffix}.tsbuildinfo`
|
|
87
|
+
: `typecheck${envSuffix}.tsbuildinfo`,
|
|
83
88
|
);
|
|
84
89
|
|
|
85
90
|
const compilerOptions: ts.CompilerOptions = {
|
|
@@ -148,7 +153,7 @@ export function runTscPackageBuild(options: TscPackageBuildOptions): TscPackageB
|
|
|
148
153
|
const result = builderProgram.getSemanticDiagnosticsOfNextAffectedFile();
|
|
149
154
|
if (result == null) break;
|
|
150
155
|
if ("fileName" in result.affected) {
|
|
151
|
-
affectedFiles?.add(result.affected.fileName
|
|
156
|
+
affectedFiles?.add(pathx.posix(result.affected.fileName));
|
|
152
157
|
} else {
|
|
153
158
|
// ts.Program returned — global change, treat as full rebuild
|
|
154
159
|
affectedFiles = undefined;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
import ts from "typescript";
|
|
3
3
|
import { consola } from "consola";
|
|
4
|
+
import { pathx } from "@simplysm/core-node";
|
|
4
5
|
import { parseTsconfig } from "./tsconfig";
|
|
5
6
|
import { serializeDiagnostic, type SerializedDiagnostic } from "./typecheck-serialization";
|
|
6
7
|
|
|
@@ -28,15 +29,15 @@ export function typecheckNonPackageFiles(cwd: string): NonPackageTypecheckResult
|
|
|
28
29
|
const packagesDir = path.join(cwd, "packages");
|
|
29
30
|
|
|
30
31
|
const isNonPackageFile = (fileName: string): boolean => {
|
|
31
|
-
const normalized =
|
|
32
|
-
const normalizedPkgDir =
|
|
32
|
+
const normalized = pathx.posixResolve(fileName);
|
|
33
|
+
const normalizedPkgDir = pathx.posixResolve(packagesDir);
|
|
33
34
|
|
|
34
35
|
// Files outside packages/ directory
|
|
35
|
-
if (!normalized.startsWith(normalizedPkgDir +
|
|
36
|
+
if (!normalized.startsWith(normalizedPkgDir + "/")) return true;
|
|
36
37
|
|
|
37
38
|
// Files directly in package root (e.g., packages/{pkg}/file.ts — depth 2)
|
|
38
|
-
const relative = path.relative(normalizedPkgDir, normalized);
|
|
39
|
-
return relative.split(
|
|
39
|
+
const relative = pathx.posix(path.relative(normalizedPkgDir, normalized));
|
|
40
|
+
return relative.split("/").length === 2;
|
|
40
41
|
};
|
|
41
42
|
|
|
42
43
|
const rootFiles = parsedConfig.fileNames.filter(isNonPackageFile);
|
|
@@ -54,14 +55,18 @@ export function typecheckNonPackageFiles(cwd: string): NonPackageTypecheckResult
|
|
|
54
55
|
declarationMap: false,
|
|
55
56
|
};
|
|
56
57
|
|
|
58
|
+
logger.debug("incremental 프로그램 생성 시작");
|
|
57
59
|
const host = ts.createIncrementalCompilerHost(options);
|
|
58
60
|
const program = ts.createIncrementalProgram({
|
|
59
61
|
rootNames: rootFiles,
|
|
60
62
|
options,
|
|
61
63
|
host,
|
|
62
64
|
});
|
|
65
|
+
logger.debug("incremental 프로그램 생성 완료");
|
|
63
66
|
|
|
67
|
+
logger.debug("emit 시작");
|
|
64
68
|
program.emit();
|
|
69
|
+
logger.debug("emit 완료");
|
|
65
70
|
|
|
66
71
|
const allDiagnostics = [
|
|
67
72
|
...program.getConfigFileParsingDiagnostics(),
|
package/src/utils/vite-config.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { InlineConfig, PluginOption } from "vite";
|
|
2
2
|
import path from "path";
|
|
3
|
+
import { pathx } from "@simplysm/core-node";
|
|
3
4
|
import tsconfigPaths from "vite-tsconfig-paths";
|
|
4
5
|
import browserslistToEsbuild from "browserslist-to-esbuild";
|
|
5
6
|
import { sdAngularPlugin } from "../angular/vite-angular-plugin.js";
|
|
@@ -227,7 +228,7 @@ export async function createClientViteConfig(
|
|
|
227
228
|
if (!code.includes("import.meta")) return;
|
|
228
229
|
|
|
229
230
|
// id(파일 경로)를 Vite 서빙 URL로 변환
|
|
230
|
-
const relative = path.relative(pkgDir, id)
|
|
231
|
+
const relative = pathx.posix(path.relative(pkgDir, id));
|
|
231
232
|
const moduleUrl = id.startsWith("/") || id.startsWith("\0")
|
|
232
233
|
? id // 가상 모듈(/@vite/client 등)은 그대로 사용
|
|
233
234
|
: base + relative;
|
|
@@ -51,7 +51,7 @@ export interface BaseWorkerInfo<TEvents extends Record<string, unknown> = Record
|
|
|
51
51
|
export interface WorkerEventHandlerOptions {
|
|
52
52
|
resultKey: string;
|
|
53
53
|
listrTitle: string;
|
|
54
|
-
resultType: "build"
|
|
54
|
+
resultType: "build";
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
/**
|
|
@@ -77,6 +77,7 @@ export function registerWorkerEventHandlers(
|
|
|
77
77
|
results: Map<string, BuildResult>,
|
|
78
78
|
rebuildManager: RebuildManager,
|
|
79
79
|
): (result: BuildResult) => void {
|
|
80
|
+
workerEventsLogger.debug(`[${workerInfo.name}] 이벤트 핸들러 등록 (${opts.resultType})`);
|
|
80
81
|
const completeTask = (result: BuildResult): void => {
|
|
81
82
|
results.set(opts.resultKey, result);
|
|
82
83
|
workerInfo.buildResolver?.();
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import consola, { type ConsolaInstance, LogLevels } from "consola";
|
|
2
|
+
import { SdCliReporter } from "./SdCliReporter";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
|
-
* Apply debug log level in worker threads
|
|
5
|
+
* Apply sd-cli reporter and debug log level in worker threads
|
|
5
6
|
*
|
|
6
7
|
* Checks the SD_DEBUG environment variable (set by --debug flag in main process)
|
|
7
8
|
* and applies debug log level to consola in the current worker thread.
|
|
8
9
|
* Must be called at worker module top level.
|
|
9
10
|
*/
|
|
10
11
|
export function applyDebugLevel(): void {
|
|
12
|
+
consola.options.reporters = [new SdCliReporter()];
|
|
11
13
|
if (process.env["SD_DEBUG"] === "true") {
|
|
12
14
|
consola.level = LogLevels.debug;
|
|
13
15
|
}
|
package/src/vitest-plugin.ts
CHANGED
|
@@ -31,8 +31,13 @@ export function angularVitestPlugin(options: AngularVitestPluginOptions): Plugin
|
|
|
31
31
|
(f) => f.includes("/src/") || f.includes(".fixture."),
|
|
32
32
|
);
|
|
33
33
|
|
|
34
|
+
const angularCompilerOptions = configFile.config?.angularCompilerOptions as
|
|
35
|
+
| Record<string, unknown>
|
|
36
|
+
| undefined;
|
|
37
|
+
|
|
34
38
|
const compilerOptions: ts.CompilerOptions = {
|
|
35
39
|
...parsedConfig.options,
|
|
40
|
+
...(angularCompilerOptions as ts.CompilerOptions | undefined),
|
|
36
41
|
noEmit: false,
|
|
37
42
|
declaration: false,
|
|
38
43
|
declarationMap: false,
|
|
@@ -104,8 +104,10 @@ async function startWatch(info: ClientBuildInfo): Promise<ClientBuildResult> {
|
|
|
104
104
|
pwa: info.pwa,
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
+
logger.debug(`[${info.name}] Vite server 생성 시작`);
|
|
107
108
|
viteServer = await createServer(viteConfig);
|
|
108
109
|
await viteServer.listen();
|
|
110
|
+
logger.debug(`[${info.name}] Vite server listen 완료`);
|
|
109
111
|
|
|
110
112
|
// 실제 포트 감지
|
|
111
113
|
const address = viteServer.httpServer?.address();
|
|
@@ -139,11 +141,13 @@ async function startWatch(info: ClientBuildInfo): Promise<ClientBuildResult> {
|
|
|
139
141
|
* dev server 중지. Vite server를 정리한다.
|
|
140
142
|
*/
|
|
141
143
|
async function stopWatch(): Promise<void> {
|
|
144
|
+
logger.debug("Vite server 정리 시작");
|
|
142
145
|
const serverToClose = viteServer;
|
|
143
146
|
viteServer = undefined;
|
|
144
147
|
if (serverToClose != null) {
|
|
145
148
|
await serverToClose.close();
|
|
146
149
|
}
|
|
150
|
+
logger.debug("Vite server 정리 완료");
|
|
147
151
|
}
|
|
148
152
|
|
|
149
153
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { createWorker, FsWatcher } from "@simplysm/core-node";
|
|
1
|
+
import type ts from "typescript";
|
|
2
|
+
import { createWorker, FsWatcher, pathx } from "@simplysm/core-node";
|
|
3
3
|
import { err as errNs } from "@simplysm/core-common";
|
|
4
4
|
import { consola } from "consola";
|
|
5
5
|
import type { SdBuildPackageConfig } from "../sd-config.types";
|
|
@@ -26,14 +26,12 @@ export interface LibraryBuildInfo {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
export interface LibraryBuildResult {
|
|
29
|
-
|
|
30
|
-
dts: { success: boolean; errors?: string[]; diagnostics: SerializedDiagnostic[] };
|
|
29
|
+
build: { success: boolean; errors?: string[]; warnings?: string[]; diagnostics: SerializedDiagnostic[] };
|
|
31
30
|
lint?: LintWithProgramResult;
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
export interface CombinedBuildEvent {
|
|
35
|
-
|
|
36
|
-
dts: { success: boolean; errors?: string[] };
|
|
34
|
+
build: { success: boolean; errors?: string[]; warnings?: string[] };
|
|
37
35
|
lint?: LintWithProgramResult;
|
|
38
36
|
}
|
|
39
37
|
|
|
@@ -54,6 +52,7 @@ let fsWatcher: FsWatcher | undefined;
|
|
|
54
52
|
async function cleanup(): Promise<void> {
|
|
55
53
|
const watcherToClose = fsWatcher;
|
|
56
54
|
fsWatcher = undefined;
|
|
55
|
+
lastSourceFilePaths = undefined;
|
|
57
56
|
await watcherToClose?.close();
|
|
58
57
|
}
|
|
59
58
|
|
|
@@ -70,28 +69,27 @@ async function build(info: LibraryBuildInfo): Promise<LibraryBuildResult> {
|
|
|
70
69
|
cwd: info.cwd,
|
|
71
70
|
output: info.output,
|
|
72
71
|
env: info.output.env,
|
|
72
|
+
includeTests: info.output.includeTests,
|
|
73
73
|
});
|
|
74
74
|
logger.debug(`[${info.name}] library worker build 완료 (success: ${tscResult.success})`);
|
|
75
75
|
|
|
76
76
|
// Run lint if enabled and program is available
|
|
77
77
|
let lint: LintWithProgramResult | undefined;
|
|
78
78
|
if (info.output.lint === true && tscResult.program != null) {
|
|
79
|
+
logger.debug(`[${info.name}] lint 시작`);
|
|
79
80
|
const lintRunner = new LintWithProgramRunner({
|
|
80
81
|
cwd: info.cwd,
|
|
81
82
|
pkgName: info.name,
|
|
82
83
|
});
|
|
83
84
|
lint = await lintRunner.lint({ program: tscResult.program });
|
|
85
|
+
logger.debug(`[${info.name}] lint 완료`);
|
|
84
86
|
}
|
|
85
87
|
|
|
86
88
|
return {
|
|
87
|
-
|
|
89
|
+
build: {
|
|
88
90
|
success: tscResult.success,
|
|
89
91
|
errors: tscResult.errors,
|
|
90
92
|
warnings: undefined,
|
|
91
|
-
},
|
|
92
|
-
dts: {
|
|
93
|
-
success: tscResult.success,
|
|
94
|
-
errors: tscResult.errors,
|
|
95
93
|
diagnostics: tscResult.diagnostics,
|
|
96
94
|
},
|
|
97
95
|
lint,
|
|
@@ -107,20 +105,36 @@ const guardStartWatch = createOnceGuard("startWatch");
|
|
|
107
105
|
// Mutable state for watch mode
|
|
108
106
|
let watchInfo: LibraryBuildInfo | undefined;
|
|
109
107
|
let watchLintRunner: LintWithProgramRunner | undefined;
|
|
108
|
+
let lastSourceFilePaths: Set<string> | undefined;
|
|
109
|
+
|
|
110
|
+
function extractSourceFilePaths(program: ts.Program | undefined): Set<string> | undefined {
|
|
111
|
+
if (program == null) return undefined;
|
|
112
|
+
const paths = new Set<string>();
|
|
113
|
+
for (const sf of program.getSourceFiles()) {
|
|
114
|
+
paths.add(pathx.posix(sf.fileName));
|
|
115
|
+
}
|
|
116
|
+
return paths;
|
|
117
|
+
}
|
|
110
118
|
|
|
111
119
|
async function rebuildAll(): Promise<CombinedBuildEvent> {
|
|
112
120
|
const info = watchInfo!;
|
|
121
|
+
logger.debug(`[${info.name}] rebuildAll 시작`);
|
|
113
122
|
|
|
114
123
|
const tscResult = runTscPackageBuild({
|
|
115
124
|
pkgDir: info.pkgDir,
|
|
116
125
|
cwd: info.cwd,
|
|
117
126
|
output: info.output,
|
|
118
127
|
env: info.output.env,
|
|
128
|
+
includeTests: info.output.includeTests,
|
|
119
129
|
});
|
|
120
130
|
|
|
131
|
+
// Update source file paths for dependency filtering
|
|
132
|
+
lastSourceFilePaths = extractSourceFilePaths(tscResult.program) ?? lastSourceFilePaths;
|
|
133
|
+
|
|
121
134
|
// Run lint if enabled and program is available
|
|
122
135
|
let lint: LintWithProgramResult | undefined;
|
|
123
136
|
if (info.output.lint === true && tscResult.program != null) {
|
|
137
|
+
logger.debug(`[${info.name}] lint 시작`);
|
|
124
138
|
if (watchLintRunner == null) {
|
|
125
139
|
watchLintRunner = new LintWithProgramRunner({
|
|
126
140
|
cwd: info.cwd,
|
|
@@ -131,11 +145,12 @@ async function rebuildAll(): Promise<CombinedBuildEvent> {
|
|
|
131
145
|
program: tscResult.program,
|
|
132
146
|
affectedFiles: tscResult.affectedFiles,
|
|
133
147
|
});
|
|
148
|
+
logger.debug(`[${info.name}] lint 완료`);
|
|
134
149
|
}
|
|
135
150
|
|
|
151
|
+
logger.debug(`[${info.name}] rebuildAll 완료`);
|
|
136
152
|
return {
|
|
137
|
-
|
|
138
|
-
dts: { success: tscResult.success, errors: tscResult.errors },
|
|
153
|
+
build: { success: tscResult.success, errors: tscResult.errors },
|
|
139
154
|
lint,
|
|
140
155
|
};
|
|
141
156
|
}
|
|
@@ -153,18 +168,33 @@ async function startWatch(info: LibraryBuildInfo): Promise<void> {
|
|
|
153
168
|
const { workspaceDeps, replaceDeps } = collectDeps(info.pkgDir, info.cwd, info.replaceDeps);
|
|
154
169
|
|
|
155
170
|
// Start FsWatcher — own src/ + workspace deps' src/ + replaceDeps dist/
|
|
171
|
+
logger.debug(`[${info.name}] FsWatcher 시작`);
|
|
156
172
|
const watchPaths = [
|
|
157
|
-
|
|
158
|
-
...workspaceDeps.map((d) =>
|
|
173
|
+
pathx.posixResolve(info.pkgDir, "src", "**", "*.ts"),
|
|
174
|
+
...workspaceDeps.map((d) => pathx.posixResolve(info.cwd, "packages", d, "src", "**", "*.ts")),
|
|
159
175
|
...replaceDeps.flatMap((pkg) => [
|
|
160
|
-
|
|
161
|
-
|
|
176
|
+
pathx.posixResolve(info.cwd, "node_modules", ...pkg.split("/"), "dist", "**", "*.{js,mjs,cjs}"),
|
|
177
|
+
pathx.posixResolve(info.pkgDir, "node_modules", ...pkg.split("/"), "dist", "**", "*.{js,mjs,cjs}"),
|
|
162
178
|
]),
|
|
163
179
|
];
|
|
164
180
|
fsWatcher = await FsWatcher.watch(watchPaths);
|
|
165
181
|
|
|
166
|
-
fsWatcher.onChange({ delay: 300 }, async () => {
|
|
182
|
+
fsWatcher.onChange({ delay: 300 }, async (changes) => {
|
|
167
183
|
try {
|
|
184
|
+
const hasFileAddOrRemove = changes.some(
|
|
185
|
+
(c) => c.event === "add" || c.event === "unlink",
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
if (!hasFileAddOrRemove && lastSourceFilePaths != null) {
|
|
189
|
+
const hasRelevantChange = changes.some((c) =>
|
|
190
|
+
lastSourceFilePaths!.has(c.path),
|
|
191
|
+
);
|
|
192
|
+
if (!hasRelevantChange) {
|
|
193
|
+
logger.debug("변경된 파일이 빌드에 포함되지 않아 리빌드 건너뜀");
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
168
198
|
sender.send("buildStart", {});
|
|
169
199
|
const result = await rebuildAll();
|
|
170
200
|
sender.send("build", result);
|