@simplysm/sd-cli 13.0.0-beta.45 → 13.0.0-beta.47
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 +3 -3
- package/dist/builders/BaseBuilder.js.map +0 -1
- package/dist/builders/DtsBuilder.js.map +0 -1
- package/dist/builders/LibraryBuilder.js.map +0 -1
- package/dist/builders/index.js.map +0 -1
- package/dist/builders/types.js.map +0 -1
- package/dist/capacitor/capacitor.js.map +0 -1
- package/dist/commands/add-client.js.map +0 -1
- package/dist/commands/add-server.js.map +0 -1
- package/dist/commands/build.js.map +0 -1
- package/dist/commands/dev.js.map +0 -1
- package/dist/commands/device.js.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/lint.js.map +0 -1
- package/dist/commands/publish.js.map +0 -1
- package/dist/commands/typecheck.js.map +0 -1
- package/dist/commands/watch.js.map +0 -1
- package/dist/electron/electron.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/infra/ResultCollector.js.map +0 -1
- package/dist/infra/SignalHandler.js.map +0 -1
- package/dist/infra/WorkerManager.js.map +0 -1
- package/dist/infra/index.js.map +0 -1
- package/dist/orchestrators/WatchOrchestrator.js.map +0 -1
- package/dist/orchestrators/index.js.map +0 -1
- package/dist/sd-cli.js.map +0 -1
- package/dist/sd-config.types.js.map +0 -1
- package/dist/utils/build-env.js.map +0 -1
- package/dist/utils/config-editor.js.map +0 -1
- package/dist/utils/copy-src.js.map +0 -1
- package/dist/utils/esbuild-config.d.ts +1 -0
- package/dist/utils/esbuild-config.d.ts.map +1 -1
- package/dist/utils/esbuild-config.js +13 -2
- package/dist/utils/esbuild-config.js.map +1 -2
- package/dist/utils/listr-manager.js.map +0 -1
- package/dist/utils/output-utils.js.map +0 -1
- package/dist/utils/package-utils.js.map +0 -1
- package/dist/utils/replace-deps.js.map +0 -1
- package/dist/utils/sd-config.js.map +0 -1
- package/dist/utils/spawn.js.map +0 -1
- package/dist/utils/tailwind-config-deps.js.map +0 -1
- package/dist/utils/template.js.map +0 -1
- package/dist/utils/tsconfig.js.map +0 -1
- package/dist/utils/typecheck-serialization.js.map +0 -1
- package/dist/utils/vite-config.js.map +0 -1
- package/dist/utils/worker-events.js.map +0 -1
- package/dist/workers/client.worker.js.map +0 -1
- package/dist/workers/dts.worker.js.map +0 -1
- package/dist/workers/library.worker.js.map +0 -1
- package/dist/workers/server-runtime.worker.js.map +0 -1
- package/dist/workers/server.worker.js.map +0 -1
- package/package.json +6 -4
- package/src/builders/BaseBuilder.ts +141 -0
- package/src/builders/DtsBuilder.ts +138 -0
- package/src/builders/LibraryBuilder.ts +161 -0
- package/src/builders/index.ts +4 -0
- package/src/builders/types.ts +55 -0
- package/src/capacitor/capacitor.ts +827 -0
- package/src/commands/add-client.ts +135 -0
- package/src/commands/add-server.ts +150 -0
- package/src/commands/build.ts +475 -0
- package/src/commands/dev.ts +602 -0
- package/src/commands/device.ts +151 -0
- package/src/commands/init.ts +104 -0
- package/src/commands/lint.ts +216 -0
- package/src/commands/publish.ts +836 -0
- package/src/commands/typecheck.ts +329 -0
- package/src/commands/watch.ts +38 -0
- package/src/electron/electron.ts +329 -0
- package/src/index.ts +1 -0
- package/src/infra/ResultCollector.ts +81 -0
- package/src/infra/SignalHandler.ts +52 -0
- package/src/infra/WorkerManager.ts +65 -0
- package/src/infra/index.ts +3 -0
- package/src/orchestrators/WatchOrchestrator.ts +211 -0
- package/src/orchestrators/index.ts +1 -0
- package/src/sd-cli.ts +307 -0
- package/src/sd-config.types.ts +271 -0
- package/src/utils/build-env.ts +12 -0
- package/src/utils/config-editor.ts +131 -0
- package/src/utils/copy-src.ts +60 -0
- package/src/utils/esbuild-config.ts +263 -0
- package/src/utils/listr-manager.ts +89 -0
- package/src/utils/output-utils.ts +61 -0
- package/src/utils/package-utils.ts +63 -0
- package/src/utils/replace-deps.ts +163 -0
- package/src/utils/sd-config.ts +44 -0
- package/src/utils/spawn.ts +79 -0
- package/src/utils/tailwind-config-deps.ts +95 -0
- package/src/utils/template.ts +51 -0
- package/src/utils/tsconfig.ts +111 -0
- package/src/utils/typecheck-serialization.ts +82 -0
- package/src/utils/vite-config.ts +184 -0
- package/src/utils/worker-events.ts +102 -0
- package/src/workers/client.worker.ts +236 -0
- package/src/workers/dts.worker.ts +416 -0
- package/src/workers/library.worker.ts +245 -0
- package/src/workers/server-runtime.worker.ts +154 -0
- package/src/workers/server.worker.ts +435 -0
- package/templates/add-client/__CLIENT__/package.json.hbs +1 -1
- package/templates/add-server/__SERVER__/package.json.hbs +2 -2
- package/templates/init/package.json.hbs +3 -3
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import ts from "typescript";
|
|
3
|
+
import { Listr, type ListrTask } from "listr2";
|
|
4
|
+
import { Worker, type WorkerProxy, fsRm } from "@simplysm/core-node";
|
|
5
|
+
import "@simplysm/core-common";
|
|
6
|
+
import { consola, LogLevels } from "consola";
|
|
7
|
+
import type { SdConfig, SdBuildPackageConfig, SdClientPackageConfig, SdServerPackageConfig } from "../sd-config.types";
|
|
8
|
+
import { loadSdConfig } from "../utils/sd-config";
|
|
9
|
+
import { getVersion } from "../utils/build-env";
|
|
10
|
+
import { setupReplaceDeps } from "../utils/replace-deps";
|
|
11
|
+
import type { TypecheckEnv } from "../utils/tsconfig";
|
|
12
|
+
import { deserializeDiagnostic } from "../utils/typecheck-serialization";
|
|
13
|
+
import { runLint, type LintOptions } from "./lint";
|
|
14
|
+
import type * as LibraryWorkerModule from "../workers/library.worker";
|
|
15
|
+
import type * as ServerWorkerModule from "../workers/server.worker";
|
|
16
|
+
import type * as ClientWorkerModule from "../workers/client.worker";
|
|
17
|
+
import type * as DtsWorkerModule from "../workers/dts.worker";
|
|
18
|
+
import { Capacitor } from "../capacitor/capacitor";
|
|
19
|
+
import { Electron } from "../electron/electron";
|
|
20
|
+
import { copySrcFiles } from "../utils/copy-src";
|
|
21
|
+
|
|
22
|
+
//#region Types
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Build 명령 옵션
|
|
26
|
+
*/
|
|
27
|
+
export interface BuildOptions {
|
|
28
|
+
/** 빌드할 패키지 필터 (빈 배열이면 모든 패키지) */
|
|
29
|
+
targets: string[];
|
|
30
|
+
/** sd.config.ts에 전달할 추가 옵션 */
|
|
31
|
+
options: string[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 빌드 결과
|
|
36
|
+
*/
|
|
37
|
+
interface BuildResult {
|
|
38
|
+
name: string;
|
|
39
|
+
target: string;
|
|
40
|
+
type: "js" | "dts" | "vite" | "capacitor" | "electron";
|
|
41
|
+
success: boolean;
|
|
42
|
+
errors?: string[];
|
|
43
|
+
diagnostics?: ts.Diagnostic[];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 패키지 분류 결과
|
|
48
|
+
*/
|
|
49
|
+
interface ClassifiedPackages {
|
|
50
|
+
/** node/browser/neutral 타겟 (JS + dts) */
|
|
51
|
+
buildPackages: Array<{ name: string; config: SdBuildPackageConfig }>;
|
|
52
|
+
/** client 타겟 (Vite build + typecheck) */
|
|
53
|
+
clientPackages: Array<{ name: string; config: SdClientPackageConfig }>;
|
|
54
|
+
/** server 타겟 (JS 빌드, dts 제외) */
|
|
55
|
+
serverPackages: Array<{ name: string; config: SdServerPackageConfig }>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
//#endregion
|
|
59
|
+
|
|
60
|
+
//#region Utilities
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* 패키지를 타겟별로 분류
|
|
64
|
+
* - node/browser/neutral: buildPackages (JS + dts)
|
|
65
|
+
* - client: clientPackages (Vite build + typecheck)
|
|
66
|
+
* - server: serverPackages (JS 빌드, dts 제외)
|
|
67
|
+
* - scripts: 제외
|
|
68
|
+
*/
|
|
69
|
+
function classifyPackages(
|
|
70
|
+
packages: Record<
|
|
71
|
+
string,
|
|
72
|
+
SdBuildPackageConfig | SdClientPackageConfig | SdServerPackageConfig | { target: "scripts" } | undefined
|
|
73
|
+
>,
|
|
74
|
+
targets: string[],
|
|
75
|
+
): ClassifiedPackages {
|
|
76
|
+
const buildPackages: ClassifiedPackages["buildPackages"] = [];
|
|
77
|
+
const clientPackages: ClassifiedPackages["clientPackages"] = [];
|
|
78
|
+
const serverPackages: ClassifiedPackages["serverPackages"] = [];
|
|
79
|
+
|
|
80
|
+
for (const [name, config] of Object.entries(packages)) {
|
|
81
|
+
if (config == null) continue;
|
|
82
|
+
if (config.target === "scripts") continue;
|
|
83
|
+
|
|
84
|
+
// targets가 지정되면 해당 패키지만 포함
|
|
85
|
+
if (targets.length > 0 && !targets.includes(name)) continue;
|
|
86
|
+
|
|
87
|
+
if (config.target === "client") {
|
|
88
|
+
clientPackages.push({ name, config });
|
|
89
|
+
} else if (config.target === "server") {
|
|
90
|
+
serverPackages.push({ name, config });
|
|
91
|
+
} else {
|
|
92
|
+
buildPackages.push({ name, config });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return { buildPackages, clientPackages, serverPackages };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* dist 폴더 삭제
|
|
101
|
+
*/
|
|
102
|
+
async function cleanDistFolders(cwd: string, packageNames: string[]): Promise<void> {
|
|
103
|
+
await Promise.all(packageNames.map((name) => fsRm(path.join(cwd, "packages", name, "dist"))));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
//#endregion
|
|
107
|
+
|
|
108
|
+
//#region Main
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* 프로덕션 빌드를 실행한다.
|
|
112
|
+
*
|
|
113
|
+
* - `sd.config.ts`를 로드하여 패키지별 빌드 타겟 정보 확인 (필수)
|
|
114
|
+
* - lint 실행
|
|
115
|
+
* - dist 폴더 정리 (clean build)
|
|
116
|
+
* - `node`/`browser`/`neutral` 타겟: esbuild JS 빌드 + dts 생성 (타입체크 포함)
|
|
117
|
+
* - `client` 타겟: Vite production 빌드 + typecheck (dts 불필요)
|
|
118
|
+
* - 하나라도 실패하면 `process.exitCode = 1` 설정
|
|
119
|
+
*
|
|
120
|
+
* @param options - build 실행 옵션
|
|
121
|
+
* @returns 완료 시 resolve
|
|
122
|
+
*/
|
|
123
|
+
export async function runBuild(options: BuildOptions): Promise<void> {
|
|
124
|
+
const { targets } = options;
|
|
125
|
+
const cwd = process.cwd();
|
|
126
|
+
const logger = consola.withTag("sd:cli:build");
|
|
127
|
+
|
|
128
|
+
logger.debug("빌드 시작", { targets });
|
|
129
|
+
|
|
130
|
+
// sd.config.ts 로드
|
|
131
|
+
let sdConfig: SdConfig;
|
|
132
|
+
try {
|
|
133
|
+
sdConfig = await loadSdConfig({ cwd, dev: false, opt: options.options });
|
|
134
|
+
logger.debug("sd.config.ts 로드 완료");
|
|
135
|
+
} catch (err) {
|
|
136
|
+
consola.error(`sd.config.ts 로드 실패: ${err instanceof Error ? err.message : err}`);
|
|
137
|
+
process.exitCode = 1;
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// replaceDeps 설정이 있으면 symlink 교체
|
|
142
|
+
if (sdConfig.replaceDeps != null) {
|
|
143
|
+
await setupReplaceDeps(cwd, sdConfig.replaceDeps);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// VER, DEV 환경변수 준비
|
|
147
|
+
const version = await getVersion(cwd);
|
|
148
|
+
const baseEnv = { VER: version, DEV: "false" };
|
|
149
|
+
|
|
150
|
+
// 패키지 분류
|
|
151
|
+
const { buildPackages, clientPackages, serverPackages } = classifyPackages(sdConfig.packages, targets);
|
|
152
|
+
const allPackageNames = [
|
|
153
|
+
...buildPackages.map((p) => p.name),
|
|
154
|
+
...clientPackages.map((p) => p.name),
|
|
155
|
+
...serverPackages.map((p) => p.name),
|
|
156
|
+
];
|
|
157
|
+
|
|
158
|
+
if (allPackageNames.length === 0) {
|
|
159
|
+
process.stdout.write("✔ 빌드할 패키지가 없습니다.\n");
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
logger.debug("패키지 분류 완료", {
|
|
164
|
+
buildPackages: buildPackages.map((p) => p.name),
|
|
165
|
+
clientPackages: clientPackages.map((p) => p.name),
|
|
166
|
+
serverPackages: serverPackages.map((p) => p.name),
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
// 결과 수집
|
|
170
|
+
const results: BuildResult[] = [];
|
|
171
|
+
// 에러 추적 (객체로 래핑하여 콜백 내 수정 추적 가능하게 함)
|
|
172
|
+
const state = { hasError: false };
|
|
173
|
+
|
|
174
|
+
// Worker 경로
|
|
175
|
+
const libraryWorkerPath = import.meta.resolve("../workers/library.worker");
|
|
176
|
+
const serverWorkerPath = import.meta.resolve("../workers/server.worker");
|
|
177
|
+
const clientWorkerPath = import.meta.resolve("../workers/client.worker");
|
|
178
|
+
const dtsWorkerPath = import.meta.resolve("../workers/dts.worker");
|
|
179
|
+
|
|
180
|
+
// 파일 캐시 (diagnostics 출력용)
|
|
181
|
+
const fileCache = new Map<string, string>();
|
|
182
|
+
|
|
183
|
+
// formatHost (diagnostics 출력용)
|
|
184
|
+
const formatHost: ts.FormatDiagnosticsHost = {
|
|
185
|
+
getCanonicalFileName: (f) => f,
|
|
186
|
+
getCurrentDirectory: () => cwd,
|
|
187
|
+
getNewLine: () => ts.sys.newLine,
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// Lint 옵션 (전체 패키지 대상)
|
|
191
|
+
const lintOptions: LintOptions = {
|
|
192
|
+
targets: allPackageNames.map((name) => `packages/${name}`),
|
|
193
|
+
fix: false,
|
|
194
|
+
timing: false,
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
// Listr 구조: Lint → Clean → Build (순차)
|
|
198
|
+
const mainListr = new Listr(
|
|
199
|
+
[
|
|
200
|
+
{
|
|
201
|
+
title: "Lint",
|
|
202
|
+
task: async () => {
|
|
203
|
+
await runLint(lintOptions);
|
|
204
|
+
// lint 에러가 있으면 process.exitCode가 1로 설정됨
|
|
205
|
+
if (process.exitCode === 1) {
|
|
206
|
+
state.hasError = true;
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
title: "Clean",
|
|
212
|
+
task: async () => {
|
|
213
|
+
await cleanDistFolders(cwd, allPackageNames);
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
title: "Build",
|
|
218
|
+
task: (_, task) => {
|
|
219
|
+
const buildTasks: ListrTask[] = [];
|
|
220
|
+
|
|
221
|
+
// buildPackages: JS 빌드 + dts 생성
|
|
222
|
+
for (const { name, config } of buildPackages) {
|
|
223
|
+
const pkgDir = path.join(cwd, "packages", name);
|
|
224
|
+
const env: TypecheckEnv = config.target === "node" ? "node" : "browser";
|
|
225
|
+
|
|
226
|
+
buildTasks.push({
|
|
227
|
+
title: `${name} (${config.target})`,
|
|
228
|
+
task: async () => {
|
|
229
|
+
// JS 빌드와 DTS 생성을 병렬 실행
|
|
230
|
+
const libraryWorker: WorkerProxy<typeof LibraryWorkerModule> =
|
|
231
|
+
Worker.create<typeof LibraryWorkerModule>(libraryWorkerPath);
|
|
232
|
+
const dtsWorker: WorkerProxy<typeof DtsWorkerModule> =
|
|
233
|
+
Worker.create<typeof DtsWorkerModule>(dtsWorkerPath);
|
|
234
|
+
|
|
235
|
+
try {
|
|
236
|
+
const [buildResult, dtsResult] = await Promise.all([
|
|
237
|
+
// JS 빌드
|
|
238
|
+
libraryWorker.build({ name, config, cwd, pkgDir }),
|
|
239
|
+
// DTS 생성
|
|
240
|
+
dtsWorker.buildDts({ name, cwd, pkgDir, env, emit: true }),
|
|
241
|
+
]);
|
|
242
|
+
|
|
243
|
+
// JS 빌드 결과 처리
|
|
244
|
+
results.push({
|
|
245
|
+
name,
|
|
246
|
+
target: config.target,
|
|
247
|
+
type: "js",
|
|
248
|
+
success: buildResult.success,
|
|
249
|
+
errors: buildResult.errors,
|
|
250
|
+
});
|
|
251
|
+
if (!buildResult.success) state.hasError = true;
|
|
252
|
+
|
|
253
|
+
// DTS 결과 처리
|
|
254
|
+
const diagnostics = dtsResult.diagnostics.map((d) => deserializeDiagnostic(d, fileCache));
|
|
255
|
+
results.push({
|
|
256
|
+
name,
|
|
257
|
+
target: config.target,
|
|
258
|
+
type: "dts",
|
|
259
|
+
success: dtsResult.success,
|
|
260
|
+
errors: dtsResult.errors,
|
|
261
|
+
diagnostics,
|
|
262
|
+
});
|
|
263
|
+
if (!dtsResult.success) state.hasError = true;
|
|
264
|
+
} finally {
|
|
265
|
+
await Promise.all([libraryWorker.terminate(), dtsWorker.terminate()]);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// copySrc 파일 복사
|
|
269
|
+
if (config.copySrc != null && config.copySrc.length > 0) {
|
|
270
|
+
await copySrcFiles(pkgDir, config.copySrc);
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// clientPackages: Vite 빌드 + typecheck + Capacitor 빌드
|
|
277
|
+
for (const { name, config } of clientPackages) {
|
|
278
|
+
const pkgDir = path.join(cwd, "packages", name);
|
|
279
|
+
|
|
280
|
+
buildTasks.push({
|
|
281
|
+
title: `${name} (client)`,
|
|
282
|
+
task: async () => {
|
|
283
|
+
// Vite 빌드와 타입체크를 병렬 실행
|
|
284
|
+
const clientWorker: WorkerProxy<typeof ClientWorkerModule> =
|
|
285
|
+
Worker.create<typeof ClientWorkerModule>(clientWorkerPath);
|
|
286
|
+
const dtsWorker: WorkerProxy<typeof DtsWorkerModule> =
|
|
287
|
+
Worker.create<typeof DtsWorkerModule>(dtsWorkerPath);
|
|
288
|
+
|
|
289
|
+
try {
|
|
290
|
+
const clientConfig: SdClientPackageConfig = {
|
|
291
|
+
...config,
|
|
292
|
+
env: { ...baseEnv, ...config.env },
|
|
293
|
+
};
|
|
294
|
+
const [clientResult, dtsResult] = await Promise.all([
|
|
295
|
+
// Vite production 빌드
|
|
296
|
+
clientWorker.build({ name, config: clientConfig, cwd, pkgDir }),
|
|
297
|
+
// typecheck (dts 없이)
|
|
298
|
+
dtsWorker.buildDts({
|
|
299
|
+
name,
|
|
300
|
+
cwd,
|
|
301
|
+
pkgDir,
|
|
302
|
+
env: "browser",
|
|
303
|
+
emit: false,
|
|
304
|
+
}),
|
|
305
|
+
]);
|
|
306
|
+
|
|
307
|
+
// Vite 빌드 결과 처리
|
|
308
|
+
results.push({
|
|
309
|
+
name,
|
|
310
|
+
target: "client",
|
|
311
|
+
type: "vite",
|
|
312
|
+
success: clientResult.success,
|
|
313
|
+
errors: clientResult.errors,
|
|
314
|
+
});
|
|
315
|
+
if (!clientResult.success) state.hasError = true;
|
|
316
|
+
|
|
317
|
+
// 타입체크 결과 처리
|
|
318
|
+
const diagnostics = dtsResult.diagnostics.map((d) => deserializeDiagnostic(d, fileCache));
|
|
319
|
+
results.push({
|
|
320
|
+
name,
|
|
321
|
+
target: "client",
|
|
322
|
+
type: "dts",
|
|
323
|
+
success: dtsResult.success,
|
|
324
|
+
errors: dtsResult.errors,
|
|
325
|
+
diagnostics,
|
|
326
|
+
});
|
|
327
|
+
if (!dtsResult.success) state.hasError = true;
|
|
328
|
+
} finally {
|
|
329
|
+
await Promise.all([clientWorker.terminate(), dtsWorker.terminate()]);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Capacitor 빌드 (설정이 있는 경우만)
|
|
333
|
+
if (config.capacitor != null) {
|
|
334
|
+
const outPath = path.join(pkgDir, "dist");
|
|
335
|
+
try {
|
|
336
|
+
const cap = await Capacitor.create(pkgDir, config.capacitor);
|
|
337
|
+
await cap.initialize();
|
|
338
|
+
await cap.build(outPath);
|
|
339
|
+
results.push({
|
|
340
|
+
name,
|
|
341
|
+
target: "client",
|
|
342
|
+
type: "capacitor",
|
|
343
|
+
success: true,
|
|
344
|
+
});
|
|
345
|
+
} catch (err) {
|
|
346
|
+
results.push({
|
|
347
|
+
name,
|
|
348
|
+
target: "client",
|
|
349
|
+
type: "capacitor",
|
|
350
|
+
success: false,
|
|
351
|
+
errors: [err instanceof Error ? err.message : String(err)],
|
|
352
|
+
});
|
|
353
|
+
state.hasError = true;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// Electron 빌드 (설정이 있는 경우만)
|
|
358
|
+
if (config.electron != null) {
|
|
359
|
+
const outPath = path.join(pkgDir, "dist");
|
|
360
|
+
try {
|
|
361
|
+
const electron = await Electron.create(pkgDir, config.electron);
|
|
362
|
+
await electron.initialize();
|
|
363
|
+
await electron.build(outPath);
|
|
364
|
+
results.push({
|
|
365
|
+
name,
|
|
366
|
+
target: "client",
|
|
367
|
+
type: "electron",
|
|
368
|
+
success: true,
|
|
369
|
+
});
|
|
370
|
+
} catch (err) {
|
|
371
|
+
results.push({
|
|
372
|
+
name,
|
|
373
|
+
target: "client",
|
|
374
|
+
type: "electron",
|
|
375
|
+
success: false,
|
|
376
|
+
errors: [err instanceof Error ? err.message : String(err)],
|
|
377
|
+
});
|
|
378
|
+
state.hasError = true;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// serverPackages: JS 빌드만 (dts 생성 제외)
|
|
386
|
+
for (const { name, config } of serverPackages) {
|
|
387
|
+
const pkgDir = path.join(cwd, "packages", name);
|
|
388
|
+
|
|
389
|
+
buildTasks.push({
|
|
390
|
+
title: `${name} (server)`,
|
|
391
|
+
task: async () => {
|
|
392
|
+
const serverWorker: WorkerProxy<typeof ServerWorkerModule> =
|
|
393
|
+
Worker.create<typeof ServerWorkerModule>(serverWorkerPath);
|
|
394
|
+
|
|
395
|
+
try {
|
|
396
|
+
const buildResult = await serverWorker.build({
|
|
397
|
+
name,
|
|
398
|
+
cwd,
|
|
399
|
+
pkgDir,
|
|
400
|
+
env: { ...baseEnv, ...config.env },
|
|
401
|
+
configs: config.configs,
|
|
402
|
+
externals: config.externals,
|
|
403
|
+
pm2: config.pm2,
|
|
404
|
+
packageManager: config.packageManager,
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
results.push({
|
|
408
|
+
name,
|
|
409
|
+
target: "server",
|
|
410
|
+
type: "js",
|
|
411
|
+
success: buildResult.success,
|
|
412
|
+
errors: buildResult.errors,
|
|
413
|
+
});
|
|
414
|
+
if (!buildResult.success) state.hasError = true;
|
|
415
|
+
} finally {
|
|
416
|
+
await serverWorker.terminate();
|
|
417
|
+
}
|
|
418
|
+
},
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
return task.newListr(buildTasks, { concurrent: true, exitOnError: false });
|
|
423
|
+
},
|
|
424
|
+
},
|
|
425
|
+
],
|
|
426
|
+
{
|
|
427
|
+
concurrent: false,
|
|
428
|
+
exitOnError: false,
|
|
429
|
+
renderer: consola.level >= LogLevels.debug ? "verbose" : "default",
|
|
430
|
+
},
|
|
431
|
+
);
|
|
432
|
+
|
|
433
|
+
try {
|
|
434
|
+
await mainListr.run();
|
|
435
|
+
} catch {
|
|
436
|
+
// Listr 내부 에러는 results에 이미 수집됨
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// 결과 출력
|
|
440
|
+
const allDiagnostics: ts.Diagnostic[] = [];
|
|
441
|
+
for (const result of results) {
|
|
442
|
+
if (!result.success) {
|
|
443
|
+
const typeLabel = result.type === "dts" ? "dts" : result.target;
|
|
444
|
+
const errorLines: string[] = [`${result.name} (${typeLabel})`];
|
|
445
|
+
if (result.errors != null) {
|
|
446
|
+
for (const error of result.errors) {
|
|
447
|
+
for (const line of error.split("\n")) {
|
|
448
|
+
errorLines.push(` → ${line}`);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
consola.error(errorLines.join("\n"));
|
|
453
|
+
}
|
|
454
|
+
if (result.diagnostics != null) {
|
|
455
|
+
allDiagnostics.push(...result.diagnostics);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// diagnostics 출력 (중복 제거)
|
|
460
|
+
if (allDiagnostics.length > 0) {
|
|
461
|
+
const uniqueDiagnostics = ts.sortAndDeduplicateDiagnostics(allDiagnostics);
|
|
462
|
+
const message = ts.formatDiagnosticsWithColorAndContext(uniqueDiagnostics, formatHost);
|
|
463
|
+
process.stdout.write(message);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// 결과 로그 출력
|
|
467
|
+
if (state.hasError) {
|
|
468
|
+
logger.error("빌드 실패");
|
|
469
|
+
process.exitCode = 1;
|
|
470
|
+
} else {
|
|
471
|
+
logger.info("빌드 완료");
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
//#endregion
|