@simplysm/sd-cli 14.0.16 → 14.0.18
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 +2 -1
- package/dist/angular/client-transform-stylesheet.d.ts +2 -0
- package/dist/angular/client-transform-stylesheet.d.ts.map +1 -1
- package/dist/angular/client-transform-stylesheet.js +88 -2
- package/dist/angular/client-transform-stylesheet.js.map +1 -1
- package/dist/angular/vite-angular-plugin.d.ts +7 -0
- package/dist/angular/vite-angular-plugin.d.ts.map +1 -1
- package/dist/angular/vite-angular-plugin.js +78 -16
- package/dist/angular/vite-angular-plugin.js.map +1 -1
- package/dist/capacitor/capacitor.d.ts.map +1 -1
- package/dist/capacitor/capacitor.js +9 -13
- package/dist/capacitor/capacitor.js.map +1 -1
- package/dist/commands/check.d.ts.map +1 -1
- package/dist/commands/check.js +8 -9
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/device.d.ts.map +1 -1
- package/dist/commands/device.js +33 -1
- package/dist/commands/device.js.map +1 -1
- package/dist/commands/lint.d.ts +0 -1
- package/dist/commands/lint.d.ts.map +1 -1
- package/dist/commands/lint.js +2 -3
- package/dist/commands/lint.js.map +1 -1
- package/dist/commands/publish.js +2 -2
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/typecheck.d.ts.map +1 -1
- package/dist/commands/typecheck.js +0 -1
- package/dist/commands/typecheck.js.map +1 -1
- package/dist/electron/electron.d.ts +3 -2
- package/dist/electron/electron.d.ts.map +1 -1
- package/dist/electron/electron.js +54 -31
- package/dist/electron/electron.js.map +1 -1
- package/dist/engines/BaseEngine.js +1 -1
- package/dist/engines/BaseEngine.js.map +1 -1
- package/dist/engines/NgtscEngine.d.ts.map +1 -1
- package/dist/engines/NgtscEngine.js +0 -1
- package/dist/engines/NgtscEngine.js.map +1 -1
- package/dist/engines/ServerEsbuildEngine.d.ts.map +1 -1
- package/dist/engines/ServerEsbuildEngine.js +0 -1
- package/dist/engines/ServerEsbuildEngine.js.map +1 -1
- package/dist/engines/TscEngine.d.ts.map +1 -1
- package/dist/engines/TscEngine.js +0 -1
- package/dist/engines/TscEngine.js.map +1 -1
- package/dist/engines/ViteEngine.d.ts.map +1 -1
- package/dist/engines/ViteEngine.js +8 -1
- package/dist/engines/ViteEngine.js.map +1 -1
- package/dist/engines/index.d.ts +0 -10
- package/dist/engines/index.d.ts.map +1 -1
- package/dist/engines/index.js +0 -5
- package/dist/engines/index.js.map +1 -1
- package/dist/engines/types.d.ts +0 -1
- package/dist/engines/types.d.ts.map +1 -1
- package/dist/infra/SignalHandler.d.ts +1 -6
- package/dist/infra/SignalHandler.d.ts.map +1 -1
- package/dist/infra/SignalHandler.js +4 -13
- package/dist/infra/SignalHandler.js.map +1 -1
- package/dist/orchestrators/BuildOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/BuildOrchestrator.js +7 -12
- package/dist/orchestrators/BuildOrchestrator.js.map +1 -1
- package/dist/orchestrators/DevWatchOrchestrator.d.ts.map +1 -1
- package/dist/orchestrators/DevWatchOrchestrator.js +17 -10
- package/dist/orchestrators/DevWatchOrchestrator.js.map +1 -1
- package/dist/sd-cli-entry.d.ts +0 -1
- package/dist/sd-cli-entry.d.ts.map +1 -1
- package/dist/sd-cli-entry.js +7 -8
- package/dist/sd-cli-entry.js.map +1 -1
- package/dist/sd-config.types.d.ts +11 -1
- package/dist/sd-config.types.d.ts.map +1 -1
- package/dist/utils/angular-compiler.d.ts.map +1 -1
- package/dist/utils/angular-compiler.js +20 -13
- package/dist/utils/angular-compiler.js.map +1 -1
- package/dist/utils/esbuild-config.d.ts +1 -1
- package/dist/utils/esbuild-config.d.ts.map +1 -1
- package/dist/utils/esbuild-config.js +1 -4
- package/dist/utils/esbuild-config.js.map +1 -1
- package/dist/utils/ngtsc-build-core.d.ts.map +1 -1
- package/dist/utils/ngtsc-build-core.js +3 -0
- package/dist/utils/ngtsc-build-core.js.map +1 -1
- package/dist/utils/tsc-build.d.ts +5 -0
- package/dist/utils/tsc-build.d.ts.map +1 -1
- package/dist/utils/tsc-build.js +2 -1
- package/dist/utils/tsc-build.js.map +1 -1
- package/dist/utils/vite-config.d.ts +1 -1
- package/dist/utils/vite-config.d.ts.map +1 -1
- package/dist/utils/vite-config.js +22 -53
- package/dist/utils/vite-config.js.map +1 -1
- package/dist/utils/vite-pwa-plugin.d.ts +9 -0
- package/dist/utils/vite-pwa-plugin.d.ts.map +1 -0
- package/dist/utils/vite-pwa-plugin.js +139 -0
- package/dist/utils/vite-pwa-plugin.js.map +1 -0
- package/dist/utils/worker-utils.d.ts +2 -5
- package/dist/utils/worker-utils.d.ts.map +1 -1
- package/dist/utils/worker-utils.js +5 -11
- package/dist/utils/worker-utils.js.map +1 -1
- package/dist/workers/client.worker.d.ts.map +1 -1
- package/dist/workers/client.worker.js +9 -3
- package/dist/workers/client.worker.js.map +1 -1
- package/dist/workers/library-build.worker.d.ts.map +1 -1
- package/dist/workers/library-build.worker.js +6 -2
- package/dist/workers/library-build.worker.js.map +1 -1
- package/dist/workers/ngtsc-build.worker.js +2 -2
- package/dist/workers/ngtsc-build.worker.js.map +1 -1
- package/dist/workers/server-build.worker.d.ts.map +1 -1
- package/dist/workers/server-build.worker.js +6 -2
- package/dist/workers/server-build.worker.js.map +1 -1
- package/dist/workers/server-runtime.worker.js +4 -4
- package/dist/workers/server-runtime.worker.js.map +1 -1
- package/docs/config.md +26 -0
- package/docs/pwa-configuration-types.md +1 -1
- package/package.json +8 -10
- package/src/angular/client-transform-stylesheet.ts +104 -2
- package/src/angular/vite-angular-plugin.ts +92 -31
- package/src/capacitor/capacitor.ts +10 -26
- package/src/commands/check.ts +8 -11
- package/src/commands/device.ts +38 -3
- package/src/commands/lint.ts +2 -3
- package/src/commands/publish.ts +2 -2
- package/src/commands/typecheck.ts +0 -1
- package/src/electron/electron.ts +62 -43
- package/src/engines/BaseEngine.ts +1 -1
- package/src/engines/NgtscEngine.ts +0 -1
- package/src/engines/ServerEsbuildEngine.ts +0 -1
- package/src/engines/TscEngine.ts +0 -1
- package/src/engines/ViteEngine.ts +7 -1
- package/src/engines/index.ts +0 -10
- package/src/engines/types.ts +0 -1
- package/src/infra/SignalHandler.ts +4 -14
- package/src/orchestrators/BuildOrchestrator.ts +7 -9
- package/src/orchestrators/DevWatchOrchestrator.ts +21 -9
- package/src/sd-cli-entry.ts +11 -16
- package/src/sd-config.types.ts +12 -1
- package/src/utils/angular-compiler.ts +21 -21
- package/src/utils/esbuild-config.ts +2 -5
- package/src/utils/ngtsc-build-core.ts +7 -0
- package/src/utils/tsc-build.ts +7 -0
- package/src/utils/vite-config.ts +23 -55
- package/src/utils/vite-pwa-plugin.ts +168 -0
- package/src/utils/worker-utils.ts +5 -11
- package/src/workers/client.worker.ts +11 -3
- package/src/workers/library-build.worker.ts +6 -2
- package/src/workers/ngtsc-build.worker.ts +2 -2
- package/src/workers/server-build.worker.ts +7 -2
- package/src/workers/server-runtime.worker.ts +4 -4
- package/tests/angular/client-transform-stylesheet.spec.ts +43 -0
- package/tests/angular/find-affected-by-scss.spec.ts +37 -0
- package/tests/angular/fixtures/basic-app/scss/_colors.scss +1 -0
- package/tests/angular/fixtures/basic-app/scss/_variables.scss +3 -0
- package/tests/angular/fixtures/basic-app/src/styled.component.ts +14 -0
- package/tests/angular/linker-disk-cache.spec.ts +158 -0
- package/tests/angular/scss-disk-cache.spec.ts +162 -0
- package/tests/angular/vite-angular-plugin-hmr-fallback.spec.ts +15 -15
- package/tests/angular/vite-angular-plugin-hmr.spec.ts +9 -9
- package/tests/angular/vite-angular-plugin-lint.spec.ts +4 -4
- package/tests/angular/vite-angular-plugin-scss-hmr.spec.ts +87 -0
- package/tests/angular/vite-angular-plugin.spec.ts +15 -15
- package/tests/capacitor/capacitor-icon.spec.ts +2 -4
- package/tests/capacitor/capacitor-init.spec.ts +2 -4
- package/tests/capacitor/capacitor-workspace.spec.ts +2 -4
- package/tests/commands/device.spec.ts +100 -0
- package/tests/electron/electron.spec.ts +24 -17
- package/tests/engines/ngtsc-engine.spec.ts +0 -3
- package/tests/engines/server-esbuild-engine.spec.ts +0 -3
- package/tests/engines/tsc-engine.spec.ts +1 -2
- package/tests/engines/vite-engine.spec.ts +0 -2
- package/tests/infra/signal-handler.spec.ts +1 -12
- package/tests/orchestrators/build-orchestrator.spec.ts +0 -6
- package/tests/orchestrators/dev-watch-orchestrator.spec.ts +24 -66
- package/tests/utils/angular-compiler.spec.ts +1396 -32
- package/tests/utils/esbuild-config.spec.ts +4 -7
- package/tests/utils/{ngtsc-build-core-angular-compiler.spec.ts → ngtsc-build-core.spec.ts} +142 -11
- package/tests/utils/tsc-build.spec.ts +4 -1
- package/tests/utils/vite-config.spec.ts +130 -261
- package/tests/utils/vite-pwa-plugin.acc.spec.ts +143 -0
- package/tests/utils/vite-pwa-plugin.spec.ts +350 -0
- package/tests/utils/worker-utils.spec.ts +8 -7
- package/tests/workers/client-worker.spec.ts +50 -1
- package/tests/workers/dev-port-file.verify.md +6 -0
- package/tests/workers/library-build-lint.spec.ts +1 -1
- package/tests/workers/library-build-worker.spec.ts +1 -1
- package/tests/workers/ngtsc-build-lint.spec.ts +1 -1
- package/tests/workers/server-build-lint.spec.ts +1 -1
- package/tests/workers/server-build-worker.spec.ts +1 -1
- package/tests/workers/server-runtime-worker.spec.ts +8 -1
- package/dist/infra/WorkerManager.d.ts +0 -40
- package/dist/infra/WorkerManager.d.ts.map +0 -1
- package/dist/infra/WorkerManager.js +0 -59
- package/dist/infra/WorkerManager.js.map +0 -1
- package/dist/utils/SdCliReporter.d.ts +0 -18
- package/dist/utils/SdCliReporter.d.ts.map +0 -1
- package/dist/utils/SdCliReporter.js +0 -144
- package/dist/utils/SdCliReporter.js.map +0 -1
- package/src/infra/WorkerManager.ts +0 -65
- package/src/utils/SdCliReporter.ts +0 -177
- package/tests/angular/scss-compiler-async.spec.ts +0 -54
- package/tests/commands/dev.spec.ts +0 -53
- package/tests/commands/watch.spec.ts +0 -53
- package/tests/infra/worker-manager.spec.ts +0 -63
- package/tests/utils/angular-compiler-emit.spec.ts +0 -570
- package/tests/utils/angular-compiler-init.spec.ts +0 -705
- package/tests/utils/angular-compiler-update.spec.ts +0 -293
- package/tests/utils/build-env.spec.ts +0 -33
- package/tests/utils/ngtsc-build-core-transform-stylesheet.spec.ts +0 -124
- package/tests/utils/ngtsc-scss-refactor.spec.ts +0 -47
|
@@ -285,11 +285,16 @@ export class AngularCompiler {
|
|
|
285
285
|
const programFiles = tsProgram.getSourceFiles();
|
|
286
286
|
logger.debug(`ts.Program 소스 파일: ${programFiles.length}개`);
|
|
287
287
|
|
|
288
|
-
// 9. BuilderProgram 생성
|
|
288
|
+
// 9. BuilderProgram 생성 (진단 + affected file 탐지용)
|
|
289
|
+
// .tsbuildinfo에서 이전 상태를 복원하여 프로세스 재시작 후에도 incremental 진단 유지
|
|
290
|
+
let oldBuilderProgram = this._builderProgram;
|
|
291
|
+
if (oldBuilderProgram == null) {
|
|
292
|
+
oldBuilderProgram = ts.readBuilderProgram(mergedOptions, host) ?? undefined;
|
|
293
|
+
}
|
|
289
294
|
const builderProgram = ts.createEmitAndSemanticDiagnosticsBuilderProgram(
|
|
290
295
|
tsProgram,
|
|
291
296
|
host,
|
|
292
|
-
|
|
297
|
+
oldBuilderProgram,
|
|
293
298
|
);
|
|
294
299
|
|
|
295
300
|
// 10. AOT 분석
|
|
@@ -446,7 +451,7 @@ export class AngularCompiler {
|
|
|
446
451
|
}
|
|
447
452
|
|
|
448
453
|
const angularCompiler = this._ngtscProgram.compiler;
|
|
449
|
-
const
|
|
454
|
+
const tsProgram = this._ngtscProgram.getTsProgram();
|
|
450
455
|
const affectedFiles = this._affectedFiles;
|
|
451
456
|
|
|
452
457
|
// 2. prepareEmit() → Angular transformers 획득
|
|
@@ -466,7 +471,6 @@ export class AngularCompiler {
|
|
|
466
471
|
|
|
467
472
|
// 4. emit 결과를 수집하는 구조
|
|
468
473
|
const emitResults: EmitResult[] = [];
|
|
469
|
-
const emittedSourceFiles = new Set<ts.SourceFile>();
|
|
470
474
|
const emitDeclarationOnly = !!compilerOptions.emitDeclarationOnly;
|
|
471
475
|
|
|
472
476
|
const writeFileCallback: ts.WriteFileCallback = (
|
|
@@ -484,25 +488,16 @@ export class AngularCompiler {
|
|
|
484
488
|
return;
|
|
485
489
|
}
|
|
486
490
|
angularCompiler.incrementalCompilation.recordSuccessfulEmit(sourceFile);
|
|
487
|
-
emittedSourceFiles.add(sourceFile);
|
|
488
491
|
emitResults.push({ filename, contents, sourceFileName: sourceFile.fileName });
|
|
489
492
|
};
|
|
490
493
|
|
|
491
|
-
// 5.
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
)
|
|
499
|
-
) {
|
|
500
|
-
/* empty */
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
// 6. 2차 루프: TypeScript가 affected로 판단하지 않았지만 Angular이 처리해야 할 파일
|
|
504
|
-
for (const sourceFile of builderProgram.getSourceFiles()) {
|
|
505
|
-
if (emittedSourceFiles.has(sourceFile) || angularCompiler.ignoreForEmit.has(sourceFile)) {
|
|
494
|
+
// 5. ts.Program.emit()으로 직접 emit (NgtscProgram.emit 패턴)
|
|
495
|
+
// EmitAndSemanticDiagnosticsBuilderProgram.emitNextAffectedFile()은 내부적으로
|
|
496
|
+
// emitKind를 DTS-only로 결정할 수 있어 Angular before transformer가 .js를 생성하지 않고
|
|
497
|
+
// DtsTransformRegistry에 메타데이터를 등록하지 않는 문제가 있다.
|
|
498
|
+
// ts.Program.emit()을 직접 호출하면 항상 full emit이 수행된다.
|
|
499
|
+
for (const sourceFile of tsProgram.getSourceFiles()) {
|
|
500
|
+
if (angularCompiler.ignoreForEmit.has(sourceFile)) {
|
|
506
501
|
continue;
|
|
507
502
|
}
|
|
508
503
|
if (sourceFile.isDeclarationFile) {
|
|
@@ -514,7 +509,7 @@ export class AngularCompiler {
|
|
|
514
509
|
) {
|
|
515
510
|
continue;
|
|
516
511
|
}
|
|
517
|
-
|
|
512
|
+
tsProgram.emit(
|
|
518
513
|
sourceFile,
|
|
519
514
|
writeFileCallback,
|
|
520
515
|
undefined,
|
|
@@ -523,6 +518,11 @@ export class AngularCompiler {
|
|
|
523
518
|
);
|
|
524
519
|
}
|
|
525
520
|
|
|
521
|
+
// 6. .tsbuildinfo 영속화 (프로세스 재시작 후 incremental 진단 유지)
|
|
522
|
+
// TS 5.9에서 emitBuildInfo()가 제거됨. emit()이 내부적으로 build info를 기록한다.
|
|
523
|
+
// no-op writeFile로 JS/DTS 재출력 없이 build info만 갱신.
|
|
524
|
+
this._builderProgram.emit(undefined, () => {});
|
|
525
|
+
|
|
526
526
|
// 7. sourceFilter 적용 후 yield
|
|
527
527
|
logger.debug(`emitAffectedFiles 완료 (${emitResults.length}개 파일)`);
|
|
528
528
|
for (const result of emitResults) {
|
|
@@ -14,9 +14,8 @@ const logger = consola.withTag("sd:cli:esbuild-config");
|
|
|
14
14
|
* - 기타 파일(.js.map 등): 원본 내용을 그대로 비교한다
|
|
15
15
|
* - 기존 파일과 내용이 동일하면 타임스탬프 보존을 위해 쓰기를 스킵한다
|
|
16
16
|
*/
|
|
17
|
-
export async function writeChangedOutputFiles(outputFiles: esbuild.OutputFile[]): Promise<
|
|
17
|
+
export async function writeChangedOutputFiles(outputFiles: esbuild.OutputFile[]): Promise<void> {
|
|
18
18
|
logger.debug(`변경된 출력 파일 쓰기 시작 (${outputFiles.length}개)`);
|
|
19
|
-
let hasChanges = false;
|
|
20
19
|
await Promise.all(
|
|
21
20
|
outputFiles.map(async (file) => {
|
|
22
21
|
const finalText = file.path.endsWith(".js")
|
|
@@ -36,13 +35,11 @@ export async function writeChangedOutputFiles(outputFiles: esbuild.OutputFile[])
|
|
|
36
35
|
// 파일이 아직 존재하지 않음
|
|
37
36
|
}
|
|
38
37
|
|
|
39
|
-
hasChanges = true;
|
|
40
38
|
await fs.mkdir(path.dirname(file.path), { recursive: true });
|
|
41
39
|
await fs.writeFile(file.path, finalText);
|
|
42
40
|
}),
|
|
43
41
|
);
|
|
44
|
-
logger.debug(
|
|
45
|
-
return hasChanges;
|
|
42
|
+
logger.debug("변경된 출력 파일 쓰기 완료");
|
|
46
43
|
}
|
|
47
44
|
|
|
48
45
|
/**
|
|
@@ -59,10 +59,17 @@ export function buildCompilerOptions(
|
|
|
59
59
|
pkgDir: string,
|
|
60
60
|
output: BuildOutput,
|
|
61
61
|
): ts.CompilerOptions {
|
|
62
|
+
const needsEmit = output.js || output.dts;
|
|
62
63
|
const options: ts.CompilerOptions = {
|
|
63
64
|
...baseOptions,
|
|
64
65
|
sourceMap: false,
|
|
65
66
|
outDir: path.join(pkgDir, "dist"),
|
|
67
|
+
incremental: true,
|
|
68
|
+
tsBuildInfoFile: path.join(
|
|
69
|
+
pkgDir,
|
|
70
|
+
".cache",
|
|
71
|
+
needsEmit ? "ngtsc-build.tsbuildinfo" : "ngtsc-typecheck.tsbuildinfo",
|
|
72
|
+
),
|
|
66
73
|
};
|
|
67
74
|
|
|
68
75
|
if (output.js && output.dts) {
|
package/src/utils/tsc-build.ts
CHANGED
|
@@ -30,6 +30,8 @@ export interface TscPackageBuildOptions {
|
|
|
30
30
|
env?: TypecheckEnv;
|
|
31
31
|
/** 타입체크 전용 모드에서 tests/ 파일 포함 여부. 기본값 false. */
|
|
32
32
|
includeTests?: boolean;
|
|
33
|
+
/** 이전 빌드의 BuilderProgram. watch 모드에서 SourceFile 재사용을 위해 전달한다. */
|
|
34
|
+
oldBuilderProgram?: ts.EmitAndSemanticDiagnosticsBuilderProgram;
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
/**
|
|
@@ -46,6 +48,9 @@ export interface TscPackageBuildResult {
|
|
|
46
48
|
/** 이 빌드에서 영향받은 파일 (정규화된 순방향 슬래시 경로).
|
|
47
49
|
* watch 모드에서 증분 lint에 사용한다. */
|
|
48
50
|
affectedFiles?: ReadonlySet<string>;
|
|
51
|
+
/** 다음 빌드에서 SourceFile 재사용을 위한 BuilderProgram.
|
|
52
|
+
* watch 모드에서 이 값을 저장해두고 다음 빌드 시 oldBuilderProgram으로 전달한다. */
|
|
53
|
+
builderProgram?: ts.EmitAndSemanticDiagnosticsBuilderProgram;
|
|
49
54
|
}
|
|
50
55
|
|
|
51
56
|
/**
|
|
@@ -142,6 +147,7 @@ export function runTscPackageBuild(options: TscPackageBuildOptions): TscPackageB
|
|
|
142
147
|
rootFiles,
|
|
143
148
|
compilerOptions,
|
|
144
149
|
host,
|
|
150
|
+
options.oldBuilderProgram,
|
|
145
151
|
);
|
|
146
152
|
|
|
147
153
|
// builder program의 증분 분석을 통해 affected 파일을 추적한다.
|
|
@@ -199,6 +205,7 @@ export function runTscPackageBuild(options: TscPackageBuildOptions): TscPackageB
|
|
|
199
205
|
warningCount,
|
|
200
206
|
program: builderProgram.getProgram(),
|
|
201
207
|
affectedFiles,
|
|
208
|
+
builderProgram,
|
|
202
209
|
};
|
|
203
210
|
} catch (err) {
|
|
204
211
|
const message = errNs.message(err);
|
package/src/utils/vite-config.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { InlineConfig, PluginOption } from "vite";
|
|
2
2
|
import path from "path";
|
|
3
|
-
import tsconfigPaths from "vite-tsconfig-paths";
|
|
4
3
|
import browserslistToEsbuild from "browserslist-to-esbuild";
|
|
5
4
|
import { sdAngularPlugin } from "../angular/vite-angular-plugin.js";
|
|
6
5
|
import solidPlugin from "vite-plugin-solid";
|
|
@@ -10,8 +9,7 @@ import {
|
|
|
10
9
|
} from "./vite-scope-watch-plugin.js";
|
|
11
10
|
import { sdPostCssInlinePlugin } from "../angular/vite-postcss-inline-plugin.js";
|
|
12
11
|
import type { SdPwaConfig } from "../sd-config.types.js";
|
|
13
|
-
import {
|
|
14
|
-
import { generatePwaIcons } from "./generate-pwa-icons.js";
|
|
12
|
+
import { sdPwaPlugin } from "./vite-pwa-plugin.js";
|
|
15
13
|
|
|
16
14
|
/** createClientViteConfig 옵션 */
|
|
17
15
|
export interface CreateClientViteConfigOptions {
|
|
@@ -70,9 +68,9 @@ export interface CreateClientViteConfigOptions {
|
|
|
70
68
|
* Angular AOT 플러그인, tsconfigPaths, env define, server/build 기본 설정,
|
|
71
69
|
* browserslist, PostCSS, polyfills, legacyModule (inlineDynamicImports) 등을 통합 구성한다.
|
|
72
70
|
*/
|
|
73
|
-
export
|
|
71
|
+
export function createClientViteConfig(
|
|
74
72
|
options: CreateClientViteConfigOptions,
|
|
75
|
-
):
|
|
73
|
+
): InlineConfig {
|
|
76
74
|
const name = options.pkgName.replace(/^@[^/]+\//, "");
|
|
77
75
|
|
|
78
76
|
// browserslist → esbuild target
|
|
@@ -101,9 +99,7 @@ export async function createClientViteConfig(
|
|
|
101
99
|
}
|
|
102
100
|
|
|
103
101
|
// plugins
|
|
104
|
-
const plugins: PluginOption[] = [
|
|
105
|
-
tsconfigPaths({ projects: [options.tsconfigPath] }),
|
|
106
|
-
];
|
|
102
|
+
const plugins: PluginOption[] = [];
|
|
107
103
|
|
|
108
104
|
if (options.framework === "solid") {
|
|
109
105
|
plugins.push(solidPlugin());
|
|
@@ -170,59 +166,23 @@ export async function createClientViteConfig(
|
|
|
170
166
|
const config: InlineConfig = {
|
|
171
167
|
root: options.pkgDir,
|
|
172
168
|
base: options.base ?? `/${name}/`,
|
|
169
|
+
resolve: { tsconfigPaths: true },
|
|
173
170
|
define: Object.keys(define).length > 0 ? define : undefined,
|
|
174
171
|
plugins,
|
|
175
172
|
server: serverConfig,
|
|
176
173
|
css: cssConfig,
|
|
177
|
-
esbuild: {
|
|
178
|
-
target: esbuildTarget,
|
|
179
|
-
},
|
|
180
174
|
build: {
|
|
181
175
|
target: esbuildTarget,
|
|
182
176
|
},
|
|
183
177
|
optimizeDeps: {
|
|
184
178
|
...optimizeDepsConfig,
|
|
185
|
-
esbuildOptions: {
|
|
186
|
-
target: esbuildTarget as string[],
|
|
187
|
-
},
|
|
188
179
|
},
|
|
189
180
|
};
|
|
190
181
|
|
|
191
182
|
// PWA (build 모드 + pwa !== false)
|
|
192
183
|
if (options.mode === "build" && options.pwa !== false) {
|
|
193
|
-
const pwaConfig = typeof options.pwa === "object" ? options.pwa : {};
|
|
194
|
-
|
|
195
|
-
// 아이콘 자동 생성 (커스텀 icons 미설정 시)
|
|
196
|
-
let iconsConfig: Record<string, unknown> = {};
|
|
197
|
-
if (pwaConfig.manifest?.icons != null) {
|
|
198
|
-
iconsConfig = { icons: pwaConfig.manifest.icons };
|
|
199
|
-
} else {
|
|
200
|
-
const generatedIcons = await generatePwaIcons(options.pkgDir);
|
|
201
|
-
if (generatedIcons.length > 0) {
|
|
202
|
-
iconsConfig = { icons: generatedIcons };
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const pwaManifest = {
|
|
207
|
-
name: pwaConfig.manifest?.name ?? name,
|
|
208
|
-
short_name: pwaConfig.manifest?.short_name ?? name,
|
|
209
|
-
display: pwaConfig.manifest?.display ?? "standalone",
|
|
210
|
-
theme_color: pwaConfig.manifest?.theme_color ?? "#ffffff",
|
|
211
|
-
background_color: pwaConfig.manifest?.background_color ?? "#ffffff",
|
|
212
|
-
...iconsConfig,
|
|
213
|
-
};
|
|
214
|
-
const pwaWorkbox = {
|
|
215
|
-
globPatterns: pwaConfig.workbox?.globPatterns ?? [
|
|
216
|
-
"**/*.{js,css,html,ico,png,svg,woff2}",
|
|
217
|
-
],
|
|
218
|
-
};
|
|
219
184
|
(config.plugins as PluginOption[]).push(
|
|
220
|
-
|
|
221
|
-
registerType: "prompt",
|
|
222
|
-
injectRegister: "script",
|
|
223
|
-
manifest: pwaManifest,
|
|
224
|
-
workbox: pwaWorkbox,
|
|
225
|
-
}),
|
|
185
|
+
sdPwaPlugin({ pkgDir: options.pkgDir, pkgName: name, pwa: options.pwa }),
|
|
226
186
|
);
|
|
227
187
|
}
|
|
228
188
|
|
|
@@ -271,24 +231,18 @@ export async function createClientViteConfig(
|
|
|
271
231
|
}
|
|
272
232
|
}
|
|
273
233
|
|
|
274
|
-
// legacyModule: true → 코드 스플리팅 비활성화 +
|
|
234
|
+
// legacyModule: true → 코드 스플리팅 비활성화 + import.meta/import() 치환 (Chrome 61 호환)
|
|
275
235
|
if (options.legacyModule === true) {
|
|
276
|
-
config.esbuild = {
|
|
277
|
-
...config.esbuild,
|
|
278
|
-
supported: {
|
|
279
|
-
"import-meta": false,
|
|
280
|
-
},
|
|
281
|
-
};
|
|
282
236
|
config.build = {
|
|
283
237
|
...config.build,
|
|
284
|
-
|
|
238
|
+
rolldownOptions: {
|
|
285
239
|
output: {
|
|
286
240
|
inlineDynamicImports: true,
|
|
287
241
|
},
|
|
288
242
|
},
|
|
289
243
|
};
|
|
290
244
|
|
|
291
|
-
//
|
|
245
|
+
// Rolldown이 인라인하지 못한 잔여 dynamic import()를 제거한다.
|
|
292
246
|
// inlineDynamicImports가 정적 경로를 모두 인라인한 후에도,
|
|
293
247
|
// @vite-ignore나 런타임 계산 경로의 import()가 남을 수 있다.
|
|
294
248
|
// Chrome 61은 import() 구문을 파싱하지 못하므로 no-op 함수로 치환한다.
|
|
@@ -306,6 +260,20 @@ export async function createClientViteConfig(
|
|
|
306
260
|
};
|
|
307
261
|
},
|
|
308
262
|
});
|
|
263
|
+
|
|
264
|
+
// import.meta 구문을 치환한다. Chrome 61은 import.meta를 파싱하지 못한다 (Chrome 64+).
|
|
265
|
+
// Vite/Rolldown이 빌드 시 대부분의 import.meta를 resolve하지만, 잔여분에 대한 안전망이다.
|
|
266
|
+
(config.plugins as PluginOption[]).push({
|
|
267
|
+
name: "sd-legacy-strip-import-meta",
|
|
268
|
+
enforce: "post",
|
|
269
|
+
renderChunk(code) {
|
|
270
|
+
if (!code.includes("import.meta")) return null;
|
|
271
|
+
return {
|
|
272
|
+
code: code.replace(/\bimport\.meta\b/g, "(void 0)"),
|
|
273
|
+
map: null,
|
|
274
|
+
};
|
|
275
|
+
},
|
|
276
|
+
});
|
|
309
277
|
}
|
|
310
278
|
|
|
311
279
|
// build 모드 설정 (프로덕션 빌드 또는 legacyModule dev)
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import type { PluginOption, ResolvedConfig } from "vite";
|
|
2
|
+
import type { SdPwaConfig } from "../sd-config.types.js";
|
|
3
|
+
import { generatePwaIcons } from "./generate-pwa-icons.js";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { glob } from "glob";
|
|
7
|
+
|
|
8
|
+
export interface SdPwaPluginOptions {
|
|
9
|
+
pkgDir: string;
|
|
10
|
+
pkgName: string;
|
|
11
|
+
pwa?: SdPwaConfig;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function sdPwaPlugin(options: SdPwaPluginOptions): PluginOption {
|
|
15
|
+
const pwaConfig = options.pwa ?? {};
|
|
16
|
+
let resolvedBase: string;
|
|
17
|
+
let resolvedOutDir: string;
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
name: "sd-pwa",
|
|
21
|
+
|
|
22
|
+
configResolved(config: ResolvedConfig) {
|
|
23
|
+
resolvedBase = config.base;
|
|
24
|
+
resolvedOutDir = config.build.outDir;
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
transformIndexHtml() {
|
|
28
|
+
return [
|
|
29
|
+
{
|
|
30
|
+
tag: "link",
|
|
31
|
+
attrs: { rel: "manifest", href: "manifest.webmanifest" },
|
|
32
|
+
injectTo: "head" as const,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
tag: "script",
|
|
36
|
+
children: generateRegistrationScript(),
|
|
37
|
+
injectTo: "body" as const,
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
async closeBundle() {
|
|
43
|
+
// Read version from package.json
|
|
44
|
+
const pkgJsonPath = path.join(options.pkgDir, "package.json");
|
|
45
|
+
const pkgJson = JSON.parse(
|
|
46
|
+
fs.readFileSync(pkgJsonPath, "utf-8"),
|
|
47
|
+
) as Record<string, unknown>;
|
|
48
|
+
const version = pkgJson["version"] as string;
|
|
49
|
+
|
|
50
|
+
// Icons
|
|
51
|
+
let iconsField: Record<string, unknown> = {};
|
|
52
|
+
if (pwaConfig.manifest?.icons != null) {
|
|
53
|
+
iconsField = { icons: pwaConfig.manifest.icons };
|
|
54
|
+
} else {
|
|
55
|
+
const generated = await generatePwaIcons(options.pkgDir);
|
|
56
|
+
if (generated.length > 0) {
|
|
57
|
+
iconsField = { icons: generated };
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Manifest
|
|
62
|
+
const manifest = {
|
|
63
|
+
name: pwaConfig.manifest?.name ?? options.pkgName,
|
|
64
|
+
short_name: pwaConfig.manifest?.short_name ?? options.pkgName,
|
|
65
|
+
display: pwaConfig.manifest?.display ?? "standalone",
|
|
66
|
+
theme_color: pwaConfig.manifest?.theme_color ?? "#ffffff",
|
|
67
|
+
background_color: pwaConfig.manifest?.background_color ?? "#ffffff",
|
|
68
|
+
start_url: ".",
|
|
69
|
+
scope: ".",
|
|
70
|
+
...iconsField,
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
fs.writeFileSync(
|
|
74
|
+
path.join(resolvedOutDir, "manifest.webmanifest"),
|
|
75
|
+
JSON.stringify(manifest, null, 2),
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
// Precache file list
|
|
79
|
+
const globPatterns = pwaConfig.workbox?.globPatterns ?? [
|
|
80
|
+
"**/*.{js,css,html,ico,png,svg,woff2}",
|
|
81
|
+
];
|
|
82
|
+
const globResults = await Promise.all(
|
|
83
|
+
globPatterns.map((pattern) => glob(pattern, { cwd: resolvedOutDir })),
|
|
84
|
+
);
|
|
85
|
+
const precacheUrls = [...new Set(globResults.flat())]
|
|
86
|
+
.filter((f) => f !== "sw.js" && f !== "manifest.webmanifest")
|
|
87
|
+
.map((f) => f.replace(/\\/g, "/"));
|
|
88
|
+
|
|
89
|
+
// Service Worker
|
|
90
|
+
const swContent = generateSwContent(version, resolvedBase, precacheUrls);
|
|
91
|
+
fs.writeFileSync(path.join(resolvedOutDir, "sw.js"), swContent);
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function generateRegistrationScript(): string {
|
|
97
|
+
return `(function(){
|
|
98
|
+
if(!("serviceWorker" in navigator))return;
|
|
99
|
+
navigator.serviceWorker.register("sw.js").then(function(reg){
|
|
100
|
+
if(reg.waiting){d(reg.waiting);return}
|
|
101
|
+
reg.addEventListener("updatefound",function(){
|
|
102
|
+
var w=reg.installing;
|
|
103
|
+
if(!w)return;
|
|
104
|
+
w.addEventListener("statechange",function(){
|
|
105
|
+
if(w.state==="installed"&&navigator.serviceWorker.controller)d(w);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
var r=false;
|
|
110
|
+
navigator.serviceWorker.addEventListener("controllerchange",function(){
|
|
111
|
+
if(!r){r=true;window.location.reload()}
|
|
112
|
+
});
|
|
113
|
+
function d(w){
|
|
114
|
+
window.dispatchEvent(new CustomEvent("sd-pwa-update-ready",{
|
|
115
|
+
detail:{update:function(){w.postMessage({type:"SKIP_WAITING"})}}
|
|
116
|
+
}));
|
|
117
|
+
}
|
|
118
|
+
})();`;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function generateSwContent(
|
|
122
|
+
version: string,
|
|
123
|
+
base: string,
|
|
124
|
+
precacheUrls: string[],
|
|
125
|
+
): string {
|
|
126
|
+
const urlsArray = JSON.stringify(precacheUrls, null, 2);
|
|
127
|
+
return `const APP_VERSION = ${JSON.stringify(version)};
|
|
128
|
+
const CACHE_NAME = "precache-" + APP_VERSION;
|
|
129
|
+
const BASE_URL = ${JSON.stringify(base)};
|
|
130
|
+
const PRECACHE_URLS = ${urlsArray};
|
|
131
|
+
|
|
132
|
+
self.addEventListener("install", (event) => {
|
|
133
|
+
event.waitUntil(
|
|
134
|
+
caches.open(CACHE_NAME).then((cache) => cache.addAll(PRECACHE_URLS))
|
|
135
|
+
);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
self.addEventListener("activate", (event) => {
|
|
139
|
+
event.waitUntil(
|
|
140
|
+
caches.keys().then((names) =>
|
|
141
|
+
Promise.all(
|
|
142
|
+
names
|
|
143
|
+
.filter((name) => name.startsWith("precache-") && name !== CACHE_NAME)
|
|
144
|
+
.map((name) => caches.delete(name))
|
|
145
|
+
)
|
|
146
|
+
).then(() => self.clients.claim())
|
|
147
|
+
);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
self.addEventListener("fetch", (event) => {
|
|
151
|
+
event.respondWith(
|
|
152
|
+
caches.match(event.request).then((cached) => {
|
|
153
|
+
if (cached) return cached;
|
|
154
|
+
if (event.request.mode === "navigate") {
|
|
155
|
+
return caches.match(BASE_URL + "index.html").then((resp) => resp || fetch(event.request));
|
|
156
|
+
}
|
|
157
|
+
return fetch(event.request);
|
|
158
|
+
})
|
|
159
|
+
);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
self.addEventListener("message", (event) => {
|
|
163
|
+
if (event.data && event.data.type === "SKIP_WAITING") {
|
|
164
|
+
self.skipWaiting();
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
`;
|
|
168
|
+
}
|
|
@@ -1,18 +1,12 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { type ConsolaInstance } from "consola";
|
|
2
|
+
import { setupConsola } from "@simplysm/core-node";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* 워커 스레드에서
|
|
6
|
-
*
|
|
7
|
-
* SD_DEBUG 환경변수(메인 프로세스의 --debug 플래그로 설정)를 확인하고
|
|
8
|
-
* 현재 워커 스레드의 consola에 디버그 로그 레벨을 적용한다.
|
|
5
|
+
* 워커 스레드에서 consola를 설정한다.
|
|
9
6
|
* 워커 모듈 최상위에서 호출해야 한다.
|
|
10
7
|
*/
|
|
11
|
-
export function
|
|
12
|
-
|
|
13
|
-
if (process.env["SD_DEBUG"] === "true") {
|
|
14
|
-
consola.level = LogLevels.debug;
|
|
15
|
-
}
|
|
8
|
+
export function setupWorkerConsola(): void {
|
|
9
|
+
setupConsola({ cli: true });
|
|
16
10
|
}
|
|
17
11
|
|
|
18
12
|
/**
|
|
@@ -6,13 +6,13 @@ import mime from "mime";
|
|
|
6
6
|
import { createWorker } from "@simplysm/core-node";
|
|
7
7
|
import { err as errNs } from "@simplysm/core-common";
|
|
8
8
|
import { consola } from "consola";
|
|
9
|
-
import { registerCleanupHandlers,
|
|
9
|
+
import { registerCleanupHandlers, setupWorkerConsola } from "../utils/worker-utils.js";
|
|
10
10
|
import { createClientViteConfig } from "../utils/vite-config.js";
|
|
11
11
|
import type { ScopeWatchReplaceDep } from "../utils/vite-scope-watch-plugin.js";
|
|
12
12
|
import type { SdBrowserSupportConfig, SdPwaConfig } from "../sd-config.types.js";
|
|
13
13
|
import type { LintWithProgramResult } from "../utils/lint-with-program.js";
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
setupWorkerConsola();
|
|
16
16
|
|
|
17
17
|
//#region Types
|
|
18
18
|
|
|
@@ -247,8 +247,13 @@ async function startWatch(info: ClientBuildInfo): Promise<ClientBuildResult> {
|
|
|
247
247
|
|
|
248
248
|
sender.send("serverReady", { port: actualPort });
|
|
249
249
|
|
|
250
|
+
// .dev-port 기록 (device 명령어에서 자동 탐지용)
|
|
251
|
+
const distDir = path.join(info.pkgDir, "dist");
|
|
252
|
+
fs.mkdirSync(distDir, { recursive: true });
|
|
253
|
+
fs.writeFileSync(path.join(distDir, ".dev-port"), String(actualPort));
|
|
254
|
+
|
|
250
255
|
// .config.json 생성
|
|
251
|
-
writeConfigJson(
|
|
256
|
+
writeConfigJson(distDir, info.configs);
|
|
252
257
|
|
|
253
258
|
return { success: true };
|
|
254
259
|
} catch (err) {
|
|
@@ -323,6 +328,9 @@ async function startLegacyWatch(info: ClientBuildInfo): Promise<ClientBuildResul
|
|
|
323
328
|
|
|
324
329
|
sender.send("serverReady", { port: serverPort });
|
|
325
330
|
|
|
331
|
+
// .dev-port 기록 (device 명령어에서 자동 탐지용)
|
|
332
|
+
fs.writeFileSync(path.join(info.pkgDir, "dist", ".dev-port"), String(serverPort));
|
|
333
|
+
|
|
326
334
|
// 첫 빌드 완료 대기
|
|
327
335
|
return await new Promise<ClientBuildResult>((resolve) => {
|
|
328
336
|
let firstBuildResolved = false;
|
|
@@ -9,9 +9,9 @@ import type { LintWithProgramResult } from "../utils/lint-with-program";
|
|
|
9
9
|
import { runTscPackageBuild } from "../utils/tsc-build";
|
|
10
10
|
import { LintWithProgramRunner } from "../utils/lint-with-program";
|
|
11
11
|
import { collectDeps } from "../utils/package-utils";
|
|
12
|
-
import { registerCleanupHandlers, createOnceGuard,
|
|
12
|
+
import { registerCleanupHandlers, createOnceGuard, setupWorkerConsola } from "../utils/worker-utils";
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
setupWorkerConsola();
|
|
15
15
|
|
|
16
16
|
//#region Types
|
|
17
17
|
|
|
@@ -53,6 +53,7 @@ async function cleanup(): Promise<void> {
|
|
|
53
53
|
const watcherToClose = fsWatcher;
|
|
54
54
|
fsWatcher = undefined;
|
|
55
55
|
lastSourceFilePaths = undefined;
|
|
56
|
+
lastBuilderProgram = undefined;
|
|
56
57
|
await watcherToClose?.close();
|
|
57
58
|
}
|
|
58
59
|
|
|
@@ -106,6 +107,7 @@ const guardStartWatch = createOnceGuard("startWatch");
|
|
|
106
107
|
let watchInfo: LibraryBuildInfo | undefined;
|
|
107
108
|
let watchLintRunner: LintWithProgramRunner | undefined;
|
|
108
109
|
let lastSourceFilePaths: Set<string> | undefined;
|
|
110
|
+
let lastBuilderProgram: ts.EmitAndSemanticDiagnosticsBuilderProgram | undefined;
|
|
109
111
|
|
|
110
112
|
function extractSourceFilePaths(program: ts.Program | undefined): Set<string> | undefined {
|
|
111
113
|
if (program == null) return undefined;
|
|
@@ -126,7 +128,9 @@ async function rebuildAll(): Promise<CombinedBuildEvent> {
|
|
|
126
128
|
output: info.output,
|
|
127
129
|
env: info.output.env,
|
|
128
130
|
includeTests: info.output.includeTests,
|
|
131
|
+
oldBuilderProgram: lastBuilderProgram,
|
|
129
132
|
});
|
|
133
|
+
lastBuilderProgram = tscResult.builderProgram ?? lastBuilderProgram;
|
|
130
134
|
|
|
131
135
|
// 의존성 필터링을 위한 소스 파일 경로 업데이트
|
|
132
136
|
lastSourceFilePaths = extractSourceFilePaths(tscResult.program) ?? lastSourceFilePaths;
|
|
@@ -3,7 +3,7 @@ import ts from "typescript";
|
|
|
3
3
|
import { createWorker, FsWatcher, pathx } from "@simplysm/core-node";
|
|
4
4
|
import { err as errNs } from "@simplysm/core-common";
|
|
5
5
|
import { consola } from "consola";
|
|
6
|
-
import { registerCleanupHandlers, createOnceGuard,
|
|
6
|
+
import { registerCleanupHandlers, createOnceGuard, setupWorkerConsola } from "../utils/worker-utils";
|
|
7
7
|
import {
|
|
8
8
|
runNgtscBuild,
|
|
9
9
|
buildCompilerOptions,
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
import { AngularCompiler, AngularSourceFileCache } from "../utils/angular-compiler";
|
|
29
29
|
import { collectDeps } from "../utils/package-utils";
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
setupWorkerConsola();
|
|
32
32
|
|
|
33
33
|
//#region 타입 (워커 인터페이스용 re-export)
|
|
34
34
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type ts from "typescript";
|
|
1
2
|
import path from "path";
|
|
2
3
|
import fs from "fs";
|
|
3
4
|
import esbuild from "esbuild";
|
|
@@ -18,7 +19,7 @@ import {
|
|
|
18
19
|
} from "../utils/esbuild-config";
|
|
19
20
|
import { runTscPackageBuild } from "../utils/tsc-build";
|
|
20
21
|
import { LintWithProgramRunner } from "../utils/lint-with-program";
|
|
21
|
-
import { registerCleanupHandlers, createOnceGuard,
|
|
22
|
+
import { registerCleanupHandlers, createOnceGuard, setupWorkerConsola } from "../utils/worker-utils";
|
|
22
23
|
import { collectDeps } from "../utils/package-utils";
|
|
23
24
|
import { copyPublicFiles, watchPublicFiles } from "../utils/copy-public";
|
|
24
25
|
|
|
@@ -96,7 +97,7 @@ export interface ServerBuildWorkerEvents extends Record<string, unknown> {
|
|
|
96
97
|
|
|
97
98
|
//#region Resource Management
|
|
98
99
|
|
|
99
|
-
|
|
100
|
+
setupWorkerConsola();
|
|
100
101
|
|
|
101
102
|
const logger = consola.withTag("sd:cli:server-build:worker");
|
|
102
103
|
|
|
@@ -116,6 +117,7 @@ async function cleanup(): Promise<void> {
|
|
|
116
117
|
const contextToDispose = esbuildContext;
|
|
117
118
|
esbuildContext = undefined;
|
|
118
119
|
lastMetafile = undefined;
|
|
120
|
+
lastBuilderProgram = undefined;
|
|
119
121
|
|
|
120
122
|
const watcherToClose = publicWatcher;
|
|
121
123
|
publicWatcher = undefined;
|
|
@@ -427,6 +429,7 @@ const guardStartWatch = createOnceGuard("startWatch");
|
|
|
427
429
|
// watch 모드용 가변 상태
|
|
428
430
|
let watchInfo: ServerWatchInfo | undefined;
|
|
429
431
|
let watchLintRunner: LintWithProgramRunner | undefined;
|
|
432
|
+
let lastBuilderProgram: ts.EmitAndSemanticDiagnosticsBuilderProgram | undefined;
|
|
430
433
|
|
|
431
434
|
/**
|
|
432
435
|
* esbuild + tsc 병렬 리빌드 (watch 모드)
|
|
@@ -467,7 +470,9 @@ async function rebuildAll(): Promise<ServerCombinedBuildEvent> {
|
|
|
467
470
|
parsedConfig,
|
|
468
471
|
env: info.output.env,
|
|
469
472
|
includeTests: info.output.includeTests,
|
|
473
|
+
oldBuilderProgram: lastBuilderProgram,
|
|
470
474
|
});
|
|
475
|
+
lastBuilderProgram = tscResult.builderProgram ?? lastBuilderProgram;
|
|
471
476
|
|
|
472
477
|
// lint 실행 (활성화 + program 사용 가능 시)
|
|
473
478
|
let lint: LintWithProgramResult | undefined;
|